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): project mfa required for v2 routes #7326

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
6 changes: 2 additions & 4 deletions engine/api/router_middleware_rbac.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ import (
"context"
"net/http"

"github.com/go-gorp/gorp"
"github.com/gorilla/mux"
"github.com/rockbears/log"

"github.com/ovh/cds/engine/cache"
"github.com/ovh/cds/engine/service"
"github.com/ovh/cds/sdk"
cdslog "github.com/ovh/cds/sdk/log"
Expand All @@ -17,7 +15,7 @@ import (
func (api *API) rbacMiddleware(ctx context.Context, w http.ResponseWriter, req *http.Request, rc *service.HandlerConfig) (context.Context, error) {
for _, checker := range rc.RbacCheckers {
ctx := context.WithValue(ctx, cdslog.RbackCheckerName, sdk.GetFuncName(checker))
if err := checker(ctx, getUserConsumer(ctx), api.Cache, api.mustDB(), mux.Vars(req)); err != nil {
if err := checker(ctx, mux.Vars(req)); err != nil {
if isAdmin(ctx) {
trackSudo(ctx, w)
return ctx, nil
Expand All @@ -29,7 +27,7 @@ func (api *API) rbacMiddleware(ctx context.Context, w http.ResponseWriter, req *
return ctx, nil
}

func (api *API) checkSessionPermission(ctx context.Context, auth *sdk.AuthUserConsumer, store cache.Store, db gorp.SqlExecutor, _ map[string]string) error {
func (api *API) checkSessionPermission(ctx context.Context, _ map[string]string) error {
if isCDN(ctx) {
return nil
}
Expand Down
5 changes: 1 addition & 4 deletions engine/api/router_rbac_rule_admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@ package api
import (
"context"

"github.com/go-gorp/gorp"

"github.com/ovh/cds/engine/cache"
"github.com/ovh/cds/sdk"
)

func (api *API) isAdmin(ctx context.Context, _ *sdk.AuthUserConsumer, _ cache.Store, _ gorp.SqlExecutor, _ map[string]string) error {
func (api *API) isAdmin(ctx context.Context, _ map[string]string) error {
if isAdmin(ctx) {
return nil
}
Expand Down
6 changes: 2 additions & 4 deletions engine/api/router_rbac_rule_cdn.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ package api
import (
"context"

"github.com/go-gorp/gorp"

"github.com/ovh/cds/engine/cache"
"github.com/ovh/cds/sdk"
)

func (api *API) isCDNService(_ context.Context, auth *sdk.AuthUserConsumer, _ cache.Store, _ gorp.SqlExecutor, _ map[string]string) error {
func (api *API) isCDNService(ctx context.Context, _ map[string]string) error {
auth := getUserConsumer(ctx)
if auth == nil {
return sdk.WithStack(sdk.ErrForbidden)
}
Expand Down
8 changes: 2 additions & 6 deletions engine/api/router_rbac_rule_entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,10 @@ package api
import (
"context"

"github.com/go-gorp/gorp"

"github.com/ovh/cds/engine/cache"
"github.com/ovh/cds/sdk"
)

func (api *API) entityRead(ctx context.Context, auth *sdk.AuthUserConsumer, store cache.Store, db gorp.SqlExecutor, vars map[string]string) error {
projectKey := vars["projectKey"]
func (api *API) entityRead(ctx context.Context, vars map[string]string) error {
entityType := vars["entityType"]
hatch := getHatcheryConsumer(ctx)

Expand All @@ -22,5 +18,5 @@ func (api *API) entityRead(ctx context.Context, auth *sdk.AuthUserConsumer, stor
if isHooks(ctx) {
return nil
}
return hasRoleOnProject(ctx, auth, store, db, projectKey, sdk.ProjectRoleRead)
return api.hasRoleOnProject(ctx, vars, sdk.ProjectRoleRead)
}
6 changes: 4 additions & 2 deletions engine/api/router_rbac_rule_entity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ projects:
AuthentifiedUser: user1,
},
}
require.NoError(t, api.entityRead(context.TODO(), &c, api.Cache, db, map[string]string{"projectKey": p.Key}))
require.NoError(t, api.entityRead(context.WithValue(context.TODO(), contextUserConsumer, &c),
map[string]string{"projectKey": p.Key}))

cNo := sdk.AuthUserConsumer{
AuthConsumerUser: sdk.AuthUserConsumerData{
Expand All @@ -53,6 +54,7 @@ projects:
},
},
}
err = api.entityRead(context.TODO(), &cNo, api.Cache, db, map[string]string{"projectKey": p.Key})
err = api.entityRead(context.WithValue(context.TODO(), contextUserConsumer, &cNo),
map[string]string{"projectKey": p.Key})
require.True(t, sdk.ErrorIs(err, sdk.ErrForbidden))
}
28 changes: 13 additions & 15 deletions engine/api/router_rbac_rule_global.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,18 @@ package api
import (
"context"

"github.com/go-gorp/gorp"

"github.com/ovh/cds/engine/api/rbac"
"github.com/ovh/cds/engine/cache"
"github.com/ovh/cds/sdk"
cdslog "github.com/ovh/cds/sdk/log"
)

func hasGlobalRole(ctx context.Context, auth *sdk.AuthUserConsumer, _ cache.Store, db gorp.SqlExecutor, role string) error {
func (api *API) hasGlobalRole(ctx context.Context, role string) error {
auth := getUserConsumer(ctx)
if auth == nil {
return sdk.WithStack(sdk.ErrForbidden)
}

hasRole, err := rbac.HasGlobalRole(ctx, db, role, auth.AuthConsumerUser.AuthentifiedUser.ID)
hasRole, err := rbac.HasGlobalRole(ctx, api.mustDBWithCtx(ctx), role, auth.AuthConsumerUser.AuthentifiedUser.ID)
if err != nil {
return err
}
Expand All @@ -29,22 +27,22 @@ func hasGlobalRole(ctx context.Context, auth *sdk.AuthUserConsumer, _ cache.Stor
}

// GlobalPermissionManage return nil if the current AuthConsumer have the ProjectRoleManage on current project KEY
func (api *API) globalPermissionManage(ctx context.Context, auth *sdk.AuthUserConsumer, store cache.Store, db gorp.SqlExecutor, _ map[string]string) error {
return hasGlobalRole(ctx, auth, store, db, sdk.GlobalRoleManagePermission)
func (api *API) globalPermissionManage(ctx context.Context, _ map[string]string) error {
return api.hasGlobalRole(ctx, sdk.GlobalRoleManagePermission)
}

func (api *API) globalOrganizationManage(ctx context.Context, auth *sdk.AuthUserConsumer, store cache.Store, db gorp.SqlExecutor, _ map[string]string) error {
return hasGlobalRole(ctx, auth, store, db, sdk.GlobalRoleManageOrganization)
func (api *API) globalOrganizationManage(ctx context.Context, _ map[string]string) error {
return api.hasGlobalRole(ctx, sdk.GlobalRoleManageOrganization)
}

func (api *API) globalRegionManage(ctx context.Context, auth *sdk.AuthUserConsumer, store cache.Store, db gorp.SqlExecutor, _ map[string]string) error {
return hasGlobalRole(ctx, auth, store, db, sdk.GlobalRoleManageRegion)
func (api *API) globalRegionManage(ctx context.Context, _ map[string]string) error {
return api.hasGlobalRole(ctx, sdk.GlobalRoleManageRegion)
}

func (api *API) globalHatcheryManage(ctx context.Context, auth *sdk.AuthUserConsumer, store cache.Store, db gorp.SqlExecutor, _ map[string]string) error {
return hasGlobalRole(ctx, auth, store, db, sdk.GlobalRoleManageHatchery)
func (api *API) globalHatcheryManage(ctx context.Context, _ map[string]string) error {
return api.hasGlobalRole(ctx, sdk.GlobalRoleManageHatchery)
}

func (api *API) globalPluginManage(ctx context.Context, auth *sdk.AuthUserConsumer, store cache.Store, db gorp.SqlExecutor, _ map[string]string) error {
return hasGlobalRole(ctx, auth, store, db, sdk.GlobalRoleManagePlugin)
func (api *API) globalPluginManage(ctx context.Context, _ map[string]string) error {
return api.hasGlobalRole(ctx, sdk.GlobalRoleManagePlugin)
}
9 changes: 4 additions & 5 deletions engine/api/router_rbac_rule_hatchery.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (

"github.com/ovh/cds/engine/api/rbac"
"github.com/ovh/cds/engine/api/region"
"github.com/ovh/cds/engine/cache"
"github.com/ovh/cds/sdk"
)

Expand All @@ -32,16 +31,16 @@ func hatcheryHasRoleOnRegion(ctx context.Context, db gorp.SqlExecutor, hatcheryI
return sdk.WithStack(sdk.ErrForbidden)
}

func (api *API) isHatchery(ctx context.Context, _ *sdk.AuthUserConsumer, _ cache.Store, _ gorp.SqlExecutor, _ map[string]string) error {
func (api *API) isHatchery(ctx context.Context, _ map[string]string) error {
if getHatcheryConsumer(ctx) != nil && getWorker(ctx) == nil {
return nil
}
return sdk.WithStack(sdk.ErrForbidden)
}

func (api *API) canRegenHatcheryToken(ctx context.Context, auth *sdk.AuthUserConsumer, store cache.Store, db gorp.SqlExecutor, vars map[string]string) error {
if err := api.isHatchery(ctx, auth, store, db, vars); err == nil {
func (api *API) canRegenHatcheryToken(ctx context.Context, vars map[string]string) error {
if err := api.isHatchery(ctx, vars); err == nil {
return nil
}
return hasGlobalRole(ctx, auth, store, db, sdk.GlobalRoleManageHatchery)
return api.hasGlobalRole(ctx, sdk.GlobalRoleManageHatchery)
}
6 changes: 2 additions & 4 deletions engine/api/router_rbac_rule_hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ package api
import (
"context"

"github.com/go-gorp/gorp"

"github.com/ovh/cds/engine/cache"
"github.com/ovh/cds/sdk"
)

func (api *API) isHookService(_ context.Context, auth *sdk.AuthUserConsumer, _ cache.Store, _ gorp.SqlExecutor, _ map[string]string) error {
func (api *API) isHookService(ctx context.Context, _ map[string]string) error {
auth := getUserConsumer(ctx)
if auth == nil {
return sdk.WithStack(sdk.ErrForbidden)
}
Expand Down
27 changes: 12 additions & 15 deletions engine/api/router_rbac_rule_plugin.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
package api

import (
"context"
"context"

"github.com/go-gorp/gorp"

"github.com/ovh/cds/engine/cache"
"github.com/ovh/cds/sdk"
"github.com/ovh/cds/sdk"
)

func (api *API) pluginRead(ctx context.Context, _ *sdk.AuthUserConsumer, _ cache.Store, _ gorp.SqlExecutor, _ map[string]string) error {
// Old worker
if isWorker(ctx) || getUserConsumer(ctx) != nil {
return nil
}
// New worker
if getWorker(ctx) != nil {
return nil
}
func (api *API) pluginRead(ctx context.Context, _ map[string]string) error {
// Old worker
if isWorker(ctx) || getUserConsumer(ctx) != nil {
return nil
}
// New worker
if getWorker(ctx) != nil {
return nil
}

return sdk.WithStack(sdk.ErrForbidden)
return sdk.WithStack(sdk.ErrForbidden)
}
57 changes: 32 additions & 25 deletions engine/api/router_rbac_rule_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,60 @@ package api
import (
"context"

"github.com/go-gorp/gorp"

"github.com/ovh/cds/engine/api/database/gorpmapping"
"github.com/ovh/cds/engine/api/rbac"
"github.com/ovh/cds/engine/cache"
"github.com/ovh/cds/engine/featureflipping"
"github.com/ovh/cds/sdk"
cdslog "github.com/ovh/cds/sdk/log"
)

func hasRoleOnProject(ctx context.Context, auth *sdk.AuthUserConsumer, store cache.Store, db gorp.SqlExecutor, projectKey string, role string) error {
if auth == nil {
func (api *API) hasRoleOnProject(ctx context.Context, vars map[string]string, role string) error {
projectKey := vars["projectKey"]

c := getUserConsumer(ctx)
if c == nil {
return sdk.WithStack(sdk.ErrForbidden)
}

hasRole, err := rbac.HasRoleOnProjectAndUserID(ctx, db, role, auth.AuthConsumerUser.AuthentifiedUser.ID, projectKey)
if supportMFA(ctx) && !isMFA(ctx) {
_, requireMFA := featureflipping.IsEnabled(ctx, gorpmapping.Mapper, api.mustDBWithCtx(ctx), sdk.FeatureMFARequired, map[string]string{
"project_key": projectKey,
})
if requireMFA {
return sdk.WithStack(sdk.ErrMFARequired)
}
}

hasRole, err := rbac.HasRoleOnProjectAndUserID(ctx, api.mustDBWithCtx(ctx), role, c.AuthConsumerUser.AuthentifiedUser.ID, projectKey)
if err != nil {
return err
}

ctx = context.WithValue(ctx, cdslog.RbacRole, role)
if !hasRole {
return sdk.WithStack(sdk.ErrForbidden)
if hasRole {
return nil
}

return nil
return sdk.WithStack(sdk.ErrForbidden)
}

// ProjectManage return nil if the current AuthUserConsumer have the ProjectRoleManage on current project KEY
func (api *API) projectManage(ctx context.Context, auth *sdk.AuthUserConsumer, store cache.Store, db gorp.SqlExecutor, vars map[string]string) error {
projectKey := vars["projectKey"]
return hasRoleOnProject(ctx, auth, store, db, projectKey, sdk.ProjectRoleManage)
func (api *API) projectManage(ctx context.Context, vars map[string]string) error {
return api.hasRoleOnProject(ctx, vars, sdk.ProjectRoleManage)
}

// projectManageNotification return nil if the current AuthUserConsumer have the role ProjectRoleManageNotification on current project KEY
func (api *API) projectManageNotification(ctx context.Context, auth *sdk.AuthUserConsumer, store cache.Store, db gorp.SqlExecutor, vars map[string]string) error {
projectKey := vars["projectKey"]
return hasRoleOnProject(ctx, auth, store, db, projectKey, sdk.ProjectRoleManageNotification)
func (api *API) projectManageNotification(ctx context.Context, vars map[string]string) error {
return api.hasRoleOnProject(ctx, vars, sdk.ProjectRoleManageNotification)
}

// projectManageVariableSet return nil if the current AuthUserConsumer have the role ProjectRoleManageVariableSet on current project KEY
func (api *API) projectManageVariableSet(ctx context.Context, auth *sdk.AuthUserConsumer, store cache.Store, db gorp.SqlExecutor, vars map[string]string) error {
projectKey := vars["projectKey"]
return hasRoleOnProject(ctx, auth, store, db, projectKey, sdk.ProjectRoleManageVariableSet)
func (api *API) projectManageVariableSet(ctx context.Context, vars map[string]string) error {
return api.hasRoleOnProject(ctx, vars, sdk.ProjectRoleManageVariableSet)
}

// ProjectRead return nil if the current AuthUserConsumer have the ProjectRoleRead on current project KEY
func (api *API) projectRead(ctx context.Context, auth *sdk.AuthUserConsumer, store cache.Store, db gorp.SqlExecutor, vars map[string]string) error {
projectKey := vars["projectKey"]
func (api *API) projectRead(ctx context.Context, vars map[string]string) error {
entityType := vars["entityType"]
hatch := getHatcheryConsumer(ctx)

Expand All @@ -58,19 +65,19 @@ func (api *API) projectRead(ctx context.Context, auth *sdk.AuthUserConsumer, sto
return nil
}

return hasRoleOnProject(ctx, auth, store, db, projectKey, sdk.ProjectRoleRead)
return api.hasRoleOnProject(ctx, vars, sdk.ProjectRoleRead)
}

func (api *API) analysisRead(ctx context.Context, auth *sdk.AuthUserConsumer, store cache.Store, db gorp.SqlExecutor, vars map[string]string) error {
func (api *API) analysisRead(ctx context.Context, vars map[string]string) error {
if isHooks(ctx) {
return nil
}
return api.projectRead(ctx, auth, store, db, vars)
return api.projectRead(ctx, vars)
}

func (api *API) triggerAnalysis(ctx context.Context, auth *sdk.AuthUserConsumer, store cache.Store, db gorp.SqlExecutor, vars map[string]string) error {
func (api *API) triggerAnalysis(ctx context.Context, vars map[string]string) error {
if isHooks(ctx) {
return nil
}
return api.projectManage(ctx, auth, store, db, vars)
return api.projectManage(ctx, vars)
}
Loading