Skip to content
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

feat(api): add region_project rbac model #7176

Merged
merged 3 commits into from
Oct 17, 2024
Merged
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
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