Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
Signed-off-by: francois  samin <[email protected]>
  • Loading branch information
fsamin committed Apr 1, 2022
1 parent 510c36c commit de7d55b
Show file tree
Hide file tree
Showing 14 changed files with 95 additions and 30 deletions.
12 changes: 12 additions & 0 deletions engine/api/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ func (api *API) getActionHandler() service.Handler {

func (api *API) putActionHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
if isService(ctx) {
return sdk.WithStack(sdk.ErrForbidden)
}

vars := mux.Vars(r)

groupName := vars["permGroupName"]
Expand Down Expand Up @@ -307,6 +311,10 @@ func (api *API) putActionHandler() service.Handler {

func (api *API) deleteActionHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
if isService(ctx) {
return sdk.WithStack(sdk.ErrForbidden)
}

vars := mux.Vars(r)

groupName := vars["permGroupName"]
Expand Down Expand Up @@ -425,6 +433,10 @@ func (api *API) getActionAuditHandler() service.Handler {

func (api *API) postActionAuditRollbackHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
if isService(ctx) {
return sdk.WithStack(sdk.ErrForbidden)
}

vars := mux.Vars(r)

groupName := vars["permGroupName"]
Expand Down
8 changes: 8 additions & 0 deletions engine/api/api_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ func isHatchery(ctx context.Context) bool {
return c.Service != nil && c.Service.Type == sdk.TypeHatchery
}

func isHatcheryShared(ctx context.Context) bool {
c := getAPIConsumer(ctx)
if c == nil {
return false
}
return isHatchery(ctx) && c.GroupIDs.Contains(group.SharedInfraGroup.ID)
}

func isCDN(ctx context.Context) bool {
c := getAPIConsumer(ctx)
if c == nil {
Expand Down
2 changes: 1 addition & 1 deletion engine/api/api_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ func (api *API) InitRouter() {
r.Handle("/project/{key}/workflows/{permWorkflowName}/hook/triggers/condition", Scope(sdk.AuthConsumerScopeRun), r.GET(api.getWorkflowTriggerHookConditionHandler))
r.Handle("/project/{key}/workflows/{permWorkflowName}/triggers/condition", Scope(sdk.AuthConsumerScopeRun), r.GET(api.getWorkflowTriggerConditionHandler))
r.Handle("/project/{key}/workflows/{permWorkflowName}/runs/{number}/nodes/{nodeRunID}/release", Scope(sdk.AuthConsumerScopeRunExecution), r.POSTEXECUTE(api.releaseApplicationWorkflowHandler, MaintenanceAware()))
r.Handle("/project/{key}/workflows/{permWorkflowName}/runs/{number}/hooks/{hookRunID}/callback", Scope(sdk.AuthConsumerScopeRun), r.POST(api.postWorkflowJobHookCallbackHandler, MaintenanceAware()))
r.Handle("/project/{key}/workflows/{permWorkflowNameAdvanced}/runs/{number}/hooks/{hookRunID}/callback", Scope(sdk.AuthConsumerScopeRun), r.POST(api.postWorkflowJobHookCallbackHandler, MaintenanceAware()))
r.Handle("/project/{key}/workflows/{permWorkflowName}/runs/{number}/hooks/{hookRunID}/details", Scope(sdk.AuthConsumerScopeRun), r.GET(api.getWorkflowJobHookDetailsHandler))

// Environment
Expand Down
2 changes: 2 additions & 0 deletions engine/api/auth_builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ func (api *API) postAuthBuiltinSigninHandler() service.Handler {
if hasService {
ctx = context.WithValue(ctx, cdslog.AuthServiceName, srv.Name)
SetTracker(w, cdslog.AuthServiceName, srv.Name)
ctx = context.WithValue(ctx, cdslog.AuthServiceType, srv.Type)
SetTracker(w, cdslog.AuthServiceType, srv.Type)

if err := api.serviceRegister(ctx, tx, &srv); err != nil {
return err
Expand Down
4 changes: 4 additions & 0 deletions engine/api/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ func (api *API) postGroupHandler() service.Handler {

func (api *API) putGroupHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
if isService(ctx) {
return sdk.WithStack(sdk.ErrForbidden)
}

vars := mux.Vars(r)
groupName := vars["permGroupName"]

Expand Down
2 changes: 2 additions & 0 deletions engine/api/router_middleware_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ func (api *API) authOptionalMiddleware(ctx context.Context, w http.ResponseWrite
if consumer.Service != nil {
ctx = context.WithValue(ctx, cdslog.AuthServiceName, consumer.Service.Name)
SetTracker(w, cdslog.AuthServiceName, consumer.Service.Name)
ctx = context.WithValue(ctx, cdslog.AuthServiceType, consumer.Service.Type)
SetTracker(w, cdslog.AuthServiceType, consumer.Service.Type)
}

// Add worker for consumer if exists
Expand Down
22 changes: 10 additions & 12 deletions engine/api/router_middleware_auth_permission.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,7 @@ func (api *API) checkJobIDPermissions(ctx context.Context, w http.ResponseWriter
return nil
}
if perm == sdk.PermissionRead {
if (isHatchery(ctx) && isGroupMember(ctx, group.SharedInfraGroup)) ||
isMaintainer(ctx) {
if isHatcheryShared(ctx) || isMaintainer(ctx) {
return nil
}
} else {
Expand Down Expand Up @@ -149,7 +148,7 @@ func (api *API) checkProjectPermissions(ctx context.Context, w http.ResponseWrit
log.Debug(ctx, "checkProjectPermissions> callerPermission=%d ", callerPermission)
// If it's about READ: we have to check if the user is a maintainer or an admin
if requiredPerm == sdk.PermissionRead {
if !isHooks(ctx) && !isMaintainer(ctx) {
if !isMaintainer(ctx) {
// The caller doesn't enough permission level from its groups and is neither a maintainer nor an admin
log.Debug(ctx, "checkProjectPermissions> %s(%s) is not authorized to %s", getAPIConsumer(ctx).Name, getAPIConsumer(ctx).ID, projectKey)
return sdk.WrapError(sdk.ErrNoProject, "not authorized for project %s", projectKey)
Expand All @@ -158,10 +157,6 @@ func (api *API) checkProjectPermissions(ctx context.Context, w http.ResponseWrit
log.Debug(ctx, "checkProjectPermissions> %s(%s) access granted to %s because is maintainer", getAPIConsumer(ctx).Name, getAPIConsumer(ctx).ID, projectKey)
telemetry.Current(ctx, telemetry.Tag(telemetry.TagPermission, "is_maintainer"))
}
if isHooks(ctx) {
log.Debug(ctx, "checkProjectPermissions> %s(%s) access granted to %s because is hooks", getAPIConsumer(ctx).Name, getAPIConsumer(ctx).ID, projectKey)
telemetry.Current(ctx, telemetry.Tag(telemetry.TagPermission, "is_hooks"))
}
return nil
}

Expand All @@ -188,13 +183,16 @@ func (api *API) checkWorkflowPermissions(ctx context.Context, w http.ResponseWri
// Same as checkWorkflowPermissions but also allows GET for workers on same project's workflows.
// This is needed as artifact download is allowed from a workflow to another in the same project.
func (api *API) checkWorkflowAdvancedPermissions(ctx context.Context, w http.ResponseWriter, workflowName string, perm int, routeVars map[string]string) error {
return api.checkWorkflowPermissionsWithOpts(CheckWorkflowPermissionsOpts{
AllowGETForWorkerOnSameProject: true,
})(ctx, w, workflowName, perm, routeVars)
return api.checkWorkflowPermissionsWithOpts(
CheckWorkflowPermissionsOpts{
AllowGETForWorkerOnSameProject: true,
AllowHooks: true,
})(ctx, w, workflowName, perm, routeVars)
}

type CheckWorkflowPermissionsOpts struct {
AllowGETForWorkerOnSameProject bool
AllowHooks bool
}

func (api *API) checkWorkflowPermissionsWithOpts(opts CheckWorkflowPermissionsOpts) PermCheckFunc {
Expand Down Expand Up @@ -289,7 +287,7 @@ func (api *API) checkWorkflowPermissionsWithOpts(opts CheckWorkflowPermissionsOp
log.Debug(ctx, "checkWorkflowPermissions> %s is not authorized to %s/%s", getAPIConsumer(ctx).ID, projectKey, workflowName)
return sdk.WrapError(sdk.ErrForbidden, "not authorized for workflow %s/%s", projectKey, workflowName)
}
if isHooks(ctx) {
if isHooks(ctx) && opts.AllowHooks {
log.Debug(ctx, "checkWorkflowPermissions> %s access granted to %s/%s because is hooks service", getAPIConsumer(ctx).ID, projectKey, workflowName)
telemetry.Current(ctx, telemetry.Tag(telemetry.TagPermission, "is_hooks"))
} else if isMaintainer(ctx) {
Expand Down Expand Up @@ -335,7 +333,7 @@ func (api *API) checkGroupPermissions(ctx context.Context, w http.ResponseWriter

if permissionValue > sdk.PermissionRead {
// Hatcheries started for "shared.infra" group are granted for group "shared.infra"
if g.ID == group.SharedInfraGroup.ID && isHatchery(ctx) && isGroupMember(ctx, g) {
if isHatcheryShared(ctx) {
return nil
}
// Only group administror or CDS administrator can update a group or its dependencies
Expand Down
12 changes: 12 additions & 0 deletions engine/api/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ func (api *API) getTemplateHandler() service.Handler {

func (api *API) putTemplateHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
if isService(ctx) {
return sdk.WithStack(sdk.ErrForbidden)
}

vars := mux.Vars(r)

groupName := vars["permGroupName"]
Expand Down Expand Up @@ -288,6 +292,10 @@ func (api *API) putTemplateHandler() service.Handler {

func (api *API) deleteTemplateHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
if isService(ctx) {
return sdk.WithStack(sdk.ErrForbidden)
}

vars := mux.Vars(r)

groupName := vars["permGroupName"]
Expand Down Expand Up @@ -917,6 +925,10 @@ func (api *API) deleteTemplateInstanceHandler() service.Handler {

func (api *API) postTemplatePullHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
if isService(ctx) {
return sdk.WithStack(sdk.ErrForbidden)
}

vars := mux.Vars(r)

groupName := vars["permGroupName"]
Expand Down
8 changes: 8 additions & 0 deletions engine/api/worker_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ func (api *API) postWorkerModelHandler() service.Handler {

func (api *API) putWorkerModelHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
if isService(ctx) {
return sdk.WithStack(sdk.ErrForbidden)
}

vars := mux.Vars(r)

groupName := vars["permGroupName"]
Expand Down Expand Up @@ -156,6 +160,10 @@ func (api *API) putWorkerModelHandler() service.Handler {

func (api *API) deleteWorkerModelHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
if isService(ctx) {
return sdk.WithStack(sdk.ErrForbidden)
}

vars := mux.Vars(r)

groupName := vars["permGroupName"]
Expand Down
3 changes: 1 addition & 2 deletions engine/api/worker_model_hatchery.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ import (

func (api *API) putBookWorkerModelHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
// this handler should only answer to an hatchery
if ok := isHatchery(ctx); !ok {
if !isHatchery(ctx) {
return sdk.WithStack(sdk.ErrForbidden)
}

Expand Down
8 changes: 6 additions & 2 deletions engine/api/workflow_hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,13 @@ func (api *API) putWorkflowHookModelHandler() service.Handler {

func (api *API) postWorkflowJobHookCallbackHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
if !isHooks(ctx) {
return sdk.WithStack(sdk.ErrForbidden)
}

vars := mux.Vars(r)
key := vars["key"]
workflowName := vars["permWorkflowName"]
workflowName := vars["permWorkflowNameAdvanced"]
hookRunID := vars["hookRunID"]
number, err := requestVarInt(r, "number")
if err != nil {
Expand Down Expand Up @@ -279,7 +283,7 @@ func (api *API) postWorkflowJobHookCallbackHandler() service.Handler {
DisableDetailledNodeRun: true,
})
if err != nil {
return sdk.WrapError(err, "cannot load workflow run")
return sdk.WrapError(err, "cannot load workflow %s/%s run %d", key, workflowName, number)
}

secrets, err := workflow.LoadDecryptSecrets(ctx, tx, wr, nil)
Expand Down
22 changes: 12 additions & 10 deletions sdk/cdsclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ import (
var _ Interface = new(client)

type client struct {
httpClient *http.Client
httpNoTimeoutClient *http.Client
httpWebsocketClient *websocket.Dialer
config *Config
name string
httpClient *http.Client
httpNoTimeoutClient *http.Client
httpWebsocketClient *websocket.Dialer
config *Config
name string
serviceAuthConsumerSigninRequest *sdk.AuthConsumerSigninRequest
}

func NewWebsocketDialer(insecureSkipVerifyTLS bool) *websocket.Dialer {
Expand Down Expand Up @@ -151,15 +152,16 @@ func NewServiceClient(ctx context.Context, clientConfig ServiceConfig, registerP
}
}

cli.serviceAuthConsumerSigninRequest = &sdk.AuthConsumerSigninRequest{
"token": clientConfig.Token,
"service": registerPayload,
}

var nbError int
retry:
var res sdk.AuthConsumerSigninResponse
_, headers, code, err := cli.RequestJSON(ctx, "POST", "/auth/consumer/"+string(sdk.ConsumerBuiltin)+"/signin",
sdk.AuthConsumerSigninRequest{
"token": clientConfig.Token,
"service": registerPayload,
},
&res)
cli.serviceAuthConsumerSigninRequest, &res)
if err != nil {
if code == 401 {
nbError++
Expand Down
18 changes: 15 additions & 3 deletions sdk/cdsclient/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,11 @@ func (c *client) StreamNoRetry(ctx context.Context, httpClient HTTPClient, metho
if c.config.Verbose {
log.Printf("session token invalid: (%s). Relogin...\n", c.config.SessionToken)
}
resp, err := c.AuthConsumerSignin(sdk.ConsumerBuiltin, sdk.AuthConsumerSigninRequest{"token": c.config.BuitinConsumerAuthenticationToken})
var req = sdk.AuthConsumerSigninRequest{"token": c.config.BuitinConsumerAuthenticationToken}
if c.serviceAuthConsumerSigninRequest != nil {
req = *c.serviceAuthConsumerSigninRequest
}
resp, err := c.AuthConsumerSignin(sdk.ConsumerBuiltin, req)
if err != nil {
return nil, nil, -1, err
}
Expand Down Expand Up @@ -287,7 +291,11 @@ func (c *client) Stream(ctx context.Context, httpClient HTTPClient, method strin
if c.config.Verbose {
log.Printf("session token invalid: (%s). Relogin...\n", c.config.SessionToken)
}
resp, err := c.AuthConsumerSignin(sdk.ConsumerBuiltin, sdk.AuthConsumerSigninRequest{"token": c.config.BuitinConsumerAuthenticationToken})
var req = sdk.AuthConsumerSigninRequest{"token": c.config.BuitinConsumerAuthenticationToken}
if c.serviceAuthConsumerSigninRequest != nil {
req = *c.serviceAuthConsumerSigninRequest
}
resp, err := c.AuthConsumerSignin(sdk.ConsumerBuiltin, req)
if err != nil {
return nil, nil, -1, err
}
Expand Down Expand Up @@ -418,7 +426,11 @@ func (c *client) UploadMultiPart(method string, path string, body *bytes.Buffer,
// Checks that current session_token is still valid
// If not, challenge a new one against the authenticationToken
if !c.config.HasValidSessionToken() && c.config.BuitinConsumerAuthenticationToken != "" {
resp, err := c.AuthConsumerSignin(sdk.ConsumerBuiltin, sdk.AuthConsumerSigninRequest{"token": c.config.BuitinConsumerAuthenticationToken})
var req = sdk.AuthConsumerSigninRequest{"token": c.config.BuitinConsumerAuthenticationToken}
if c.serviceAuthConsumerSigninRequest != nil {
req = *c.serviceAuthConsumerSigninRequest
}
resp, err := c.AuthConsumerSignin(sdk.ConsumerBuiltin, req)
if err != nil {
return nil, -1, err
}
Expand Down
2 changes: 2 additions & 0 deletions sdk/log/fields.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const (
Action = log.Field("action")
AuthConsumerID = log.Field("auth_consumer_id")
AuthServiceName = log.Field("auth_service_name")
AuthServiceType = log.Field("auth_service_type")
AuthSessionIAT = log.Field("auth_session_iat")
AuthSessionID = log.Field("auth_session_id")
AuthSessionTokenID = log.Field("auth_session_token")
Expand Down Expand Up @@ -45,6 +46,7 @@ func init() {
AuthUserID,
AuthUsername,
AuthServiceName,
AuthServiceType,
AuthWorkerName,
AuthConsumerID,
AuthSessionID,
Expand Down

0 comments on commit de7d55b

Please sign in to comment.