Skip to content

Commit

Permalink
feat(api): add region_project rbac model (#7176)
Browse files Browse the repository at this point in the history
  • Loading branch information
sguiheux authored Oct 17, 2024
1 parent 355b6ce commit d248054
Show file tree
Hide file tree
Showing 10 changed files with 289 additions and 52 deletions.
9 changes: 9 additions & 0 deletions engine/api/rbac/dao_rbac.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,15 @@ func Insert(ctx context.Context, db gorpmapper.SqlExecutorWithTx, rb *sdk.RBAC)
return err
}
}
for i := range rb.RegionProjects {
dbRbRegionProject := rbacRegionProject{
RbacID: dbRb.ID,
RBACRegionProject: rb.RegionProjects[i],
}
if err := insertRBACRegionProject(ctx, db, &dbRbRegionProject); err != nil {
return err
}
}

*rb = dbRb.RBAC
return nil
Expand Down
22 changes: 22 additions & 0 deletions engine/api/rbac/dao_rbac_region_project.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package rbac

import (
"context"

"github.com/ovh/cds/engine/api/database/gorpmapping"
"github.com/ovh/cds/engine/gorpmapper"
)

func insertRBACRegionProject(ctx context.Context, db gorpmapper.SqlExecutorWithTx, rbacRegionProject *rbacRegionProject) error {
if err := gorpmapping.InsertAndSign(ctx, db, rbacRegionProject); err != nil {
return err
}

for _, projectKey := range rbacRegionProject.RBACProjectKeys {
if err := insertRBACRegionProjectKey(ctx, db, rbacRegionProject.ID, projectKey); err != nil {
return err
}
}

return nil
}
55 changes: 55 additions & 0 deletions engine/api/rbac/dao_rbac_region_project_key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package rbac

import (
"context"

"github.com/go-gorp/gorp"
"github.com/ovh/cds/engine/api/database/gorpmapping"
"github.com/ovh/cds/engine/gorpmapper"
"github.com/ovh/cds/sdk"
"github.com/rockbears/log"
)

func getAllRBACRegionProjectKeys(ctx context.Context, db gorp.SqlExecutor, q gorpmapping.Query) ([]rbacRegionProjectKey, error) {
var rbacRegionProjectIdentifier []rbacRegionProjectKey
if err := gorpmapping.GetAll(ctx, db, q, &rbacRegionProjectIdentifier); err != nil {
return nil, err
}
rbacProjectIdentifierFiltered := make([]rbacRegionProjectKey, 0, len(rbacRegionProjectIdentifier))
for _, projectDatas := range rbacRegionProjectIdentifier {
isValid, err := gorpmapping.CheckSignature(projectDatas, projectDatas.Signature)
if err != nil {
return nil, sdk.WrapError(err, "error when checking signature for rbac_region_project_keys_project %d", projectDatas.ID)
}
if !isValid {
log.Error(ctx, "rbac.getAllRBACRegionProjectKeys> rbac_region_project_keys_project %d data corrupted", projectDatas.ID)
continue
}
rbacProjectIdentifierFiltered = append(rbacProjectIdentifierFiltered, projectDatas)
}
return rbacProjectIdentifierFiltered, nil
}

func insertRBACRegionProjectKey(ctx context.Context, db gorpmapper.SqlExecutorWithTx, rbacParentID int64, projectKey string) error {
rpk := rbacRegionProjectKey{
RbacRegionProjectID: rbacParentID,
ProjectKey: projectKey,
}
if err := gorpmapping.InsertAndSign(ctx, db, &rpk); err != nil {
return err
}
return nil
}

func loadRBACRegionProjectKeys(ctx context.Context, db gorp.SqlExecutor, rbacRegionProject *rbacRegionProject) error {
q := gorpmapping.NewQuery("SELECT * FROM rbac_region_project_keys_project WHERE rbac_region_project_id = $1").Args(rbacRegionProject.ID)
rbacRegionProjectKeys, err := getAllRBACRegionProjectKeys(ctx, db, q)
if err != nil {
return err
}
rbacRegionProject.RBACRegionProject.RBACProjectKeys = make([]string, 0, len(rbacRegionProjectKeys))
for _, projectDatas := range rbacRegionProjectKeys {
rbacRegionProject.RBACRegionProject.RBACProjectKeys = append(rbacRegionProject.RBACRegionProject.RBACProjectKeys, projectDatas.ProjectKey)
}
return nil
}
69 changes: 50 additions & 19 deletions engine/api/rbac/gorp_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ func (rg rbacGlobal) Canonical() gorpmapper.CanonicalForms {
}

type rbacGlobalUser struct {
ID int64 `db:"id"`
RbacGlobalID int64 `db:"rbac_global_id"`
RbacGlobalUserID string `db:"user_id"`
ID int64 `json:"-" db:"id"`
RbacGlobalID int64 `json:"-" db:"rbac_global_id"`
RbacGlobalUserID string `json:"-" db:"user_id"`
gorpmapper.SignedEntity
}

Expand All @@ -48,8 +48,8 @@ func (rgu rbacGlobalUser) Canonical() gorpmapper.CanonicalForms {

type rbacGlobalGroup struct {
ID int64 `json:"-" db:"id"`
RbacGlobalID int64 `db:"rbac_global_id"`
RbacGlobalGroupID int64 `db:"group_id"`
RbacGlobalID int64 `json:"-" db:"rbac_global_id"`
RbacGlobalGroupID int64 `json:"-" db:"group_id"`
gorpmapper.SignedEntity
}

Expand Down Expand Up @@ -130,6 +130,34 @@ func (rh rbacHatchery) Canonical() gorpmapper.CanonicalForms {
}
}

type rbacRegionProject struct {
ID int64 `json:"-" db:"id"`
RbacID string `json:"-" db:"rbac_id"`
sdk.RBACRegionProject
gorpmapper.SignedEntity
}

func (rr rbacRegionProject) Canonical() gorpmapper.CanonicalForms {
_ = []interface{}{rr.ID, rr.RbacID, rr.RegionID, rr.Role}
return []gorpmapper.CanonicalForm{
"{{.ID}}{{.RbacID}}{{.RegionID}}{{.Role}}",
}
}

type rbacRegionProjectKey struct {
ID int64 `json:"-" db:"id"`
RbacRegionProjectID int64 `json:"-" db:"rbac_region_project_id"`
ProjectKey string `json:"-" db:"project_key"`
gorpmapper.SignedEntity
}

func (rr rbacRegionProjectKey) Canonical() gorpmapper.CanonicalForms {
_ = []interface{}{rr.ID, rr.RbacRegionProjectID, rr.ProjectKey}
return []gorpmapper.CanonicalForm{
"{{.ID}}{{.RbacRegionProjectID}}{{.ProjectKey}}",
}
}

type rbacRegion struct {
sdk.RBACRegion
gorpmapper.SignedEntity
Expand All @@ -144,8 +172,8 @@ func (rr rbacRegion) Canonical() gorpmapper.CanonicalForms {

type rbacRegionUser struct {
ID int64 `json:"-" db:"id"`
RbacRegionID int64 `db:"rbac_region_id"`
RbacUserID string `db:"user_id"`
RbacRegionID int64 `json:"-" db:"rbac_region_id"`
RbacUserID string `json:"-" db:"user_id"`
gorpmapper.SignedEntity
}

Expand All @@ -158,8 +186,8 @@ func (rru rbacRegionUser) Canonical() gorpmapper.CanonicalForms {

type rbacRegionGroup struct {
ID int64 `json:"-" db:"id"`
RbacRegionID int64 `db:"rbac_region_id"`
RbacGroupID int64 `db:"group_id"`
RbacRegionID int64 `json:"-" db:"rbac_region_id"`
RbacGroupID int64 `json:"-" db:"group_id"`
gorpmapper.SignedEntity
}

Expand All @@ -172,8 +200,8 @@ func (rrg rbacRegionGroup) Canonical() gorpmapper.CanonicalForms {

type rbacRegionOrganization struct {
ID int64 `json:"-" db:"id"`
RbacRegionID int64 `db:"rbac_region_id"`
RbacOrganizationID string `db:"organization_id"`
RbacRegionID int64 `json:"-" db:"rbac_region_id"`
RbacOrganizationID string ` json:"-" db:"organization_id"`
gorpmapper.SignedEntity
}

Expand All @@ -200,8 +228,8 @@ func (rp rbacVariableSet) Canonical() gorpmapper.CanonicalForms {

type rbacVariableSetUser struct {
ID int64 `json:"-" db:"id"`
RbacVariableSetID int64 `db:"rbac_variableset_id"`
RbacVariableSetUserID string `db:"user_id"`
RbacVariableSetID int64 `json:"-" db:"rbac_variableset_id"`
RbacVariableSetUserID string `json:"-" db:"user_id"`
gorpmapper.SignedEntity
}

Expand All @@ -214,8 +242,8 @@ func (rgu rbacVariableSetUser) Canonical() gorpmapper.CanonicalForms {

type rbacVariableSetGroup struct {
ID int64 `json:"-" db:"id"`
RbacVariableSetID int64 `db:"rbac_variableset_id"`
RbacVariableSetGroupID int64 `db:"group_id"`
RbacVariableSetID int64 `json:"-" db:"rbac_variableset_id"`
RbacVariableSetGroupID int64 ` json:"-" db:"group_id"`
gorpmapper.SignedEntity
}

Expand All @@ -242,8 +270,8 @@ func (rp rbacWorkflow) Canonical() gorpmapper.CanonicalForms {

type rbacWorkflowUser struct {
ID int64 `json:"-" db:"id"`
RbacWorkflowID int64 `db:"rbac_workflow_id"`
RbacWorkflowUserID string `db:"user_id"`
RbacWorkflowID int64 `json:"-" db:"rbac_workflow_id"`
RbacWorkflowUserID string ` json:"-" db:"user_id"`
gorpmapper.SignedEntity
}

Expand All @@ -256,8 +284,8 @@ func (rgu rbacWorkflowUser) Canonical() gorpmapper.CanonicalForms {

type rbacWorkflowGroup struct {
ID int64 `json:"-" db:"id"`
RbacWorkflowID int64 `db:"rbac_workflow_id"`
RbacWorkflowGroupID int64 `db:"group_id"`
RbacWorkflowID int64 `json:"-" db:"rbac_workflow_id"`
RbacWorkflowGroupID int64 `json:"-" db:"group_id"`
gorpmapper.SignedEntity
}

Expand Down Expand Up @@ -294,4 +322,7 @@ func init() {
gorpmapping.Register(gorpmapping.New(rbacVariableSetUser{}, "rbac_variableset_users", true, "id"))
gorpmapping.Register(gorpmapping.New(rbacVariableSetGroup{}, "rbac_variableset_groups", true, "id"))

gorpmapping.Register(gorpmapping.New(rbacRegionProject{}, "rbac_region_project", true, "id"))
gorpmapping.Register(gorpmapping.New(rbacRegionProjectKey{}, "rbac_region_project_keys_project", true, "id"))

}
64 changes: 48 additions & 16 deletions engine/api/rbac/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,25 @@ type LoadOptionFunc func(context.Context, gorp.SqlExecutor, *rbac) error

// LoadOptions provides all options on rbac loads functions
var LoadOptions = struct {
Default LoadOptionFunc
LoadRBACGlobal LoadOptionFunc
LoadRBACProject LoadOptionFunc
LoadRBACHatchery LoadOptionFunc
LoadRBACRegion LoadOptionFunc
LoadRBACWorkflow LoadOptionFunc
LoadRBACVariableSet LoadOptionFunc
All LoadOptionFunc
Default LoadOptionFunc
LoadRBACGlobal LoadOptionFunc
LoadRBACProject LoadOptionFunc
LoadRBACHatchery LoadOptionFunc
LoadRBACRegion LoadOptionFunc
LoadRBACWorkflow LoadOptionFunc
LoadRBACVariableSet LoadOptionFunc
LoadRbacRegionProject LoadOptionFunc
All LoadOptionFunc
}{
Default: loadDefault,
LoadRBACGlobal: loadRBACGlobal,
LoadRBACProject: loadRBACProject,
LoadRBACHatchery: loadRBACHatchery,
LoadRBACRegion: loadRBACRegion,
LoadRBACWorkflow: loadRBACWorkflow,
LoadRBACVariableSet: loadRBACVariableSet,
All: loadAll,
Default: loadDefault,
LoadRBACGlobal: loadRBACGlobal,
LoadRBACProject: loadRBACProject,
LoadRBACHatchery: loadRBACHatchery,
LoadRBACRegion: loadRBACRegion,
LoadRBACWorkflow: loadRBACWorkflow,
LoadRBACVariableSet: loadRBACVariableSet,
LoadRbacRegionProject: loadRBACRegionProject,
All: loadAll,
}

func loadDefault(ctx context.Context, db gorp.SqlExecutor, rbac *rbac) error {
Expand Down Expand Up @@ -63,6 +65,9 @@ func loadAll(ctx context.Context, db gorp.SqlExecutor, rbac *rbac) error {
if err := loadRBACVariableSet(ctx, db, rbac); err != nil {
return err
}
if err := loadRBACRegionProject(ctx, db, rbac); err != nil {
return err
}
return nil
}

Expand Down Expand Up @@ -187,6 +192,33 @@ func loadRBACGlobal(ctx context.Context, db gorp.SqlExecutor, rbac *rbac) error
return nil
}

func loadRBACRegionProject(ctx context.Context, db gorp.SqlExecutor, rbac *rbac) error {
query := "SELECT * FROM rbac_region_project WHERE rbac_id = $1"
var rbacRegionProjects []rbacRegionProject
if err := gorpmapping.GetAll(ctx, db, gorpmapping.NewQuery(query).Args(rbac.ID), &rbacRegionProjects); err != nil {
return err
}
rbac.RegionProjects = make([]sdk.RBACRegionProject, 0, len(rbacRegionProjects))
for i := range rbacRegionProjects {
rbacRegionProject := &rbacRegionProjects[i]
isValid, err := gorpmapping.CheckSignature(rbacRegionProject, rbacRegionProject.Signature)
if err != nil {
return sdk.WrapError(err, "error when checking signature for rbac_region_project %d", rbacRegionProject.ID)
}
if !isValid {
log.Error(ctx, "loadRBACRegionProject> rbac_region_project %d data corrupted", rbacRegionProject.ID)
continue
}
if !rbacRegionProject.AllProjects {
if err := loadRBACRegionProjectKeys(ctx, db, rbacRegionProject); err != nil {
return err
}
}
rbac.RegionProjects = append(rbac.RegionProjects, rbacRegionProject.RBACRegionProject)
}
return nil
}

func loadRBACRegion(ctx context.Context, db gorp.SqlExecutor, rbac *rbac) error {
query := "SELECT * FROM rbac_region WHERE rbac_id = $1"
var rbacRegions []rbacRegion
Expand Down
39 changes: 33 additions & 6 deletions engine/api/v2_rbac.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,7 @@ func (api *API) getRBACHandler() ([]service.RbacChecker, service.Handler) {
vars := mux.Vars(req)
rbacIdentifier := vars["rbacIdentifier"]
perm, err := api.getRBACByIdentifier(ctx, rbacIdentifier,
rbac.LoadOptions.LoadRBACGlobal,
rbac.LoadOptions.LoadRBACProject,
rbac.LoadOptions.LoadRBACWorkflow,
rbac.LoadOptions.LoadRBACHatchery,
rbac.LoadOptions.LoadRBACVariableSet,
rbac.LoadOptions.LoadRBACRegion)
rbac.LoadOptions.All)
if err != nil {
return err
}
Expand Down Expand Up @@ -214,6 +209,13 @@ func (rl *RBACLoader) FillRBACWithNames(ctx context.Context, r *sdk.RBAC) error
return err
}
}
for rpID := range r.RegionProjects {
rp := &r.RegionProjects[rpID]
if err := rl.fillRBACRegionProjectWithNames(ctx, rp); err != nil {
return err
}
}

return nil
}

Expand Down Expand Up @@ -265,6 +267,12 @@ func (rl *RBACLoader) FillRBACWithIDs(ctx context.Context, r *sdk.RBAC) error {
return err
}
}
for rpID := range r.RegionProjects {
rp := &r.RegionProjects[rpID]
if err := rl.fillRBACRegionProjectWithID(ctx, rp); err != nil {
return err
}
}
return nil
}

Expand Down Expand Up @@ -298,6 +306,25 @@ func (rl *RBACLoader) fillRBACHatcheryWithID(ctx context.Context, rbacHatchery *
return nil
}

func (rl *RBACLoader) fillRBACRegionProjectWithNames(ctx context.Context, rbacRegionProject *sdk.RBACRegionProject) error {
rg, err := region.LoadRegionByID(ctx, rl.db, rbacRegionProject.RegionID)
if err != nil {
return err
}
rbacRegionProject.RegionName = rg.Name
return nil
}

func (rl *RBACLoader) fillRBACRegionProjectWithID(ctx context.Context, rbacRegionProject *sdk.RBACRegionProject) error {
rg, err := region.LoadRegionByName(ctx, rl.db, rbacRegionProject.RegionName)
if err != nil {
return err
}
rbacRegionProject.RegionID = rg.ID

return nil
}

func (rl *RBACLoader) fillRBACRegionWithNames(ctx context.Context, rbacRegion *sdk.RBACRegion) error {
rg, err := region.LoadRegionByID(ctx, rl.db, rbacRegion.RegionID)
if err != nil {
Expand Down
Loading

0 comments on commit d248054

Please sign in to comment.