Skip to content

Add user for opa gatekeeper and secret in the cluster including account info #430

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions internal/delivery/http/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package http

import (
"fmt"
"github.com/openinfradev/tks-api/internal/helper"
"net/http"

"github.com/google/uuid"
Expand All @@ -16,12 +17,14 @@ import (
)

type ClusterHandler struct {
usecase usecase.IClusterUsecase
usecase usecase.IClusterUsecase
userUsecase usecase.IUserUsecase
}

func NewClusterHandler(h usecase.Usecase) *ClusterHandler {
return &ClusterHandler{
usecase: h.Cluster,
usecase: h.Cluster,
userUsecase: h.User,
}
}

Expand Down Expand Up @@ -169,6 +172,7 @@ func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) {

dto.ClusterType = domain.ClusterType_USER
dto.SetDefaultConf()
dto.OpaGatekeeperPassword = helper.GenerateRandomPassword(16)

//txHandle := r.Context().Value("txHandle").(*gorm.DB)
clusterId := domain.ClusterId("")
Expand All @@ -188,7 +192,13 @@ func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) {
ErrorJSON(w, r, err)
return
}
}

// create OPA Gatekeeper account
err = h.userUsecase.CreateReservedAccount(r.Context(), clusterId.String()+string(usecase.OPAGatekeeperReservedAccountIdSuffix), dto.OpaGatekeeperPassword)
if err != nil {
ErrorJSON(w, r, err)
return
}

var out domain.CreateClusterResponse
Expand Down
10 changes: 10 additions & 0 deletions internal/helper/password.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ func GenerateRandomString(length int) string {
return string(b)
}

func GenerateRandomPassword(length int) string {
// generate a random password with string of letters, digits, and special characters
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()")
b := make([]rune, length)
for i := range b {
b[i] = randomRune(letters)
}
return string(b)
}

func randomRune(chars []rune) rune {
n, err := rand.Int(rand.Reader, big.NewInt(int64(len(chars))))
if err != nil {
Expand Down
45 changes: 45 additions & 0 deletions internal/middleware/auth/authorizer/abac.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package authorizer

import (
"github.com/openinfradev/tks-api/internal/middleware/auth/request"
"github.com/openinfradev/tks-api/internal/repository"
"github.com/openinfradev/tks-api/pkg/log"
"net/http"
)

var (
userBasedAccessControl []func(r *http.Request) bool
)

func init() {
userBasedAccessControl = append(userBasedAccessControl, OpaGatekeeper)
}

func ABACFilter(handler http.Handler, repo repository.Repository) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
for _, f := range userBasedAccessControl {
if !f(r) {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
}

handler.ServeHTTP(w, r)
})
}

func OpaGatekeeper(r *http.Request) bool {
requestUserInfo, ok := request.UserFrom(r.Context())
if !ok {
log.Errorf(r.Context(), "user not found")
return false
}

_ = requestUserInfo
// ToDo: Add only API endpoints for OPA Gatekeeper
//if strings.HasSuffix(requestUserInfo.GetAccountId(), string(usecase.OPAGatekeeperReservedAccountIdSuffix)) {
// // Allow restricted API from OPA Gatekeeper
//}

return true
}
1 change: 1 addition & 0 deletions internal/middleware/auth/authorizer/authorizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func NewDefaultAuthorization(repo repository.Repository) *defaultAuthorization {
d := &defaultAuthorization{
repo: repo,
}
d.addFilters(ABACFilter)
d.addFilters(PasswordFilter)
//d.addFilters(RBACFilter)
//d.addFilters(RBACFilterWithEndpoint)
Expand Down
1 change: 1 addition & 0 deletions internal/model/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type Cluster struct {
UpdatorId *uuid.UUID `gorm:"type:uuid"`
Updator User `gorm:"foreignKey:UpdatorId"`
Policies []Policy `gorm:"many2many:policy_target_clusters"`
OpaGatekeeperPassword string `gorm:"-:all"`
}

func (m *Cluster) SetDefaultConf() {
Expand Down
1 change: 1 addition & 0 deletions internal/usecase/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ func (u *ClusterUsecase) Create(ctx context.Context, dto model.Cluster) (cluster
"base_repo_branch=" + viper.GetString("revision"),
"keycloak_url=" + viper.GetString("keycloak-address"),
"policy_ids=" + strings.Join(dto.PolicyIds, ","),
"opa_gatekeeper_password=" + dto.OpaGatekeeperPassword,
},
})
if err != nil {
Expand Down
30 changes: 29 additions & 1 deletion internal/usecase/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"net/http"
"strings"

"github.com/Nerzal/gocloak/v13"
"github.com/google/uuid"
Expand All @@ -18,6 +19,12 @@ import (
"github.com/pkg/errors"
)

type ReservedAccountIdSuffix string

const (
OPAGatekeeperReservedAccountIdSuffix ReservedAccountIdSuffix = "-opa-gatekeeper"
)

type IUserUsecase interface {
CreateAdmin(ctx context.Context, user *model.User) (*model.User, error)
DeleteAdmin(ctx context.Context, organizationId string) error
Expand Down Expand Up @@ -46,6 +53,7 @@ type IUserUsecase interface {
UpdateByAccountIdByAdmin(ctx context.Context, user *model.User) (*model.User, error)

ListUsersByRole(ctx context.Context, organizationId string, roleId string, pg *pagination.Pagination) (*[]model.User, error)
CreateReservedAccount(ctx context.Context, accountId string, password string) error
}

type UserUsecase struct {
Expand Down Expand Up @@ -448,7 +456,6 @@ func (u *UserUsecase) Create(ctx context.Context, user *model.User) (*model.User
if user.ID, err = uuid.Parse(userUuidStr); err != nil {
return nil, err
}

// Create user in DB
resUser, err := u.userRepository.Create(ctx, user)
//resUser, err := u.userRepository.Create(ctx, userUuid, user.AccountId, user.Name, user.Email,
Expand Down Expand Up @@ -537,3 +544,24 @@ func NewUserUsecase(r repository.Repository, kc keycloak.IKeycloak) IUserUsecase
organizationRepository: r.Organization,
}
}

func (u *UserUsecase) CreateReservedAccount(ctx context.Context, accountId string, password string) error {
if strings.HasSuffix(accountId, string(OPAGatekeeperReservedAccountIdSuffix)) {
_, err := u.kc.CreateUser(ctx, accountId, &gocloak.User{
Username: gocloak.StringP(accountId),
Credentials: &[]gocloak.CredentialRepresentation{
{
Type: gocloak.StringP("password"),
Value: gocloak.StringP(password),
Temporary: gocloak.BoolP(false),
},
},
})

if err != nil {
return err
}
}

return nil
}
Loading