Skip to content

Commit

Permalink
CreateUndeployApplicationVersion Role Based Access Control (#837)
Browse files Browse the repository at this point in the history
Add RBAC to the `CreateUndeployApplicationVersion` action.

Rev: DSN-J1WO8X
  • Loading branch information
bernardo-bastos authored Aug 4, 2023
1 parent 2610ffa commit f7b0a88
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 8 deletions.
9 changes: 7 additions & 2 deletions pkg/testutil/testutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,21 @@ func MakeTestContext() context.Context {
}

func MakeTestContextDexEnabled() context.Context {
// Default user role.
return MakeTestContextDexEnabledUser("developer")
}

func MakeTestContextDexEnabledUser(role string) context.Context {
u := auth.User{
Email: "testmail@example.com",
Name: "test tester",
DexAuthContext: &auth.DexAuthContext{Role: "developer"},
DexAuthContext: &auth.DexAuthContext{Role: role},
}
ctx := auth.WriteUserToContext(context.Background(), u)
ctx = metadata.NewIncomingContext(ctx, metadata.New(map[string]string{
auth.HeaderUserEmail: auth.Encode64("myemail@example.com"),
auth.HeaderUserName: auth.Encode64("my name"),
auth.HeaderUserRole: auth.Encode64("Developer"),
auth.HeaderUserRole: auth.Encode64(role),
}))
return ctx
}
10 changes: 7 additions & 3 deletions services/cd-service/pkg/repository/transformer.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ func isLatestsVersion(state *State, application string, version uint64) (bool, e
}

type CreateUndeployApplicationVersion struct {
Authentication
Application string
}

Expand Down Expand Up @@ -370,6 +371,10 @@ func (c *CreateUndeployApplicationVersion) Transform(ctx context.Context, state
}
result := ""
for env := range configs {
err := state.checkUserPermissions(ctx, env, c.Application, auth.PermissionCreateUndeploy, c.RBACConfig)
if err != nil {
return "", err
}
envDir := fs.Join(releaseDir, "environments", env)

config, found := configs[env]
Expand All @@ -388,14 +393,14 @@ func (c *CreateUndeployApplicationVersion) Transform(ctx context.Context, state
if err := util.WriteFile(fs, fs.Join(envDir, "manifests.yaml"), []byte(" "), 0666); err != nil {
return "", err
}

if hasUpstream && config.Upstream.Latest {
d := &DeployApplicationVersion{
Environment: env,
Application: c.Application,
Version: lastRelease + 1,
// the train should queue deployments, instead of giving up:
LockBehaviour: api.LockBehavior_Record,
LockBehaviour: api.LockBehavior_Record,
Authentication: c.Authentication,
}
deployResult, err := d.Transform(ctx, state)
if err != nil {
Expand Down Expand Up @@ -630,7 +635,6 @@ func (s *State) checkUserPermissions(ctx context.Context, env, application, acti
if group == "" {
return fmt.Errorf("group not found for environment: %s", env)
}

return auth.CheckUserPermissions(RBACConfig, user, env, group, application, action)
}

Expand Down
109 changes: 107 additions & 2 deletions services/cd-service/pkg/repository/transformer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -790,9 +790,94 @@ func TestReleaseTrainErrors(t *testing.T) {
func TestRbacTransformerTest(t *testing.T) {
tcs := []struct {
Name string
ctx context.Context
Transformers []Transformer
ExpectedError string
}{
{
Name: "able to create undeploy with permissions policy",
Transformers: []Transformer{
&CreateEnvironment{
Environment: "staging",
Config: config.EnvironmentConfig{Upstream: &config.EnvironmentConfigUpstream{Latest: true}},
},
&CreateEnvironment{
Environment: "production",
Config: config.EnvironmentConfig{Upstream: &config.EnvironmentConfigUpstream{Environment: "staging"}},
},
&CreateApplicationVersion{
Application: "app1",
Manifests: map[string]string{
"production": "production",
"staging": "staging",
},
Authentication: Authentication{RBACConfig: auth.RBACConfig{DexEnabled: false}},
},
&CreateUndeployApplicationVersion{
Application: "app1",
Authentication: Authentication{RBACConfig: auth.RBACConfig{DexEnabled: true, Policy: map[string]*auth.Permission{
"developer,CreateUndeploy,production:*,app1,allow": {Role: "developer"},
"developer,CreateUndeploy,staging:*,app1,allow": {Role: "developer"},
"developer,DeployRelease,staging:*,app1,allow": {Role: "developer"},
}}},
},
},
},
{
Name: "unable to create undeploy without permissions policy: Missing DeployRelease permission",
Transformers: []Transformer{
&CreateEnvironment{
Environment: "staging",
Config: config.EnvironmentConfig{Upstream: &config.EnvironmentConfigUpstream{Latest: true}},
},
&CreateEnvironment{
Environment: "production",
Config: config.EnvironmentConfig{Upstream: &config.EnvironmentConfigUpstream{Environment: "staging"}},
},
&CreateApplicationVersion{
Application: "app1",
Manifests: map[string]string{
"production": "production",
"staging": "staging",
},
Authentication: Authentication{RBACConfig: auth.RBACConfig{DexEnabled: false}},
},
&CreateUndeployApplicationVersion{
Application: "app1",
Authentication: Authentication{RBACConfig: auth.RBACConfig{DexEnabled: true, Policy: map[string]*auth.Permission{
"developer,CreateUndeploy,production:*,app1,allow": {Role: "developer"},
"developer,CreateUndeploy,staging:*,app1,allow": {Role: "developer"},
}}},
},
},
ExpectedError: "user does not have permissions for: developer,DeployRelease,staging:staging,app1,allow",
},
{
Name: "unable to create undeploy without permissions policy: Missing CreateUndeploy permission",
Transformers: []Transformer{
&CreateEnvironment{
Environment: "staging",
Config: config.EnvironmentConfig{Upstream: &config.EnvironmentConfigUpstream{Latest: true}},
},
&CreateEnvironment{
Environment: "production",
Config: config.EnvironmentConfig{Upstream: &config.EnvironmentConfigUpstream{Environment: "staging"}},
},
&CreateApplicationVersion{
Application: "app1",
Manifests: map[string]string{
"production": "production",
"staging": "staging",
},
Authentication: Authentication{RBACConfig: auth.RBACConfig{DexEnabled: false}},
},
&CreateUndeployApplicationVersion{
Application: "app1",
Authentication: Authentication{RBACConfig: auth.RBACConfig{DexEnabled: true, Policy: map[string]*auth.Permission{}}},
},
},
ExpectedError: "user does not have permissions for: developer,CreateUndeploy,production:*,app1,allow",
},
{
Name: "able to create release train with permissions policy",
Transformers: ReleaseTrainTestSetup(&ReleaseTrain{
Expand Down Expand Up @@ -888,6 +973,7 @@ func TestRbacTransformerTest(t *testing.T) {
Manifests: map[string]string{
envAcceptance: "acceptance", // not empty
},
Authentication: Authentication{RBACConfig: auth.RBACConfig{DexEnabled: false}},
},
&DeployApplicationVersion{
Environment: envAcceptance,
Expand All @@ -911,6 +997,7 @@ func TestRbacTransformerTest(t *testing.T) {
Manifests: map[string]string{
envAcceptance: "acceptance", // not empty
},
Authentication: Authentication{RBACConfig: auth.RBACConfig{DexEnabled: false}},
},
&DeployApplicationVersion{
Environment: envAcceptance,
Expand All @@ -935,6 +1022,20 @@ func TestRbacTransformerTest(t *testing.T) {
},
},
},
{
Name: "able to create environment lock with permissions policy: different user",
Transformers: []Transformer{
&CreateEnvironment{Environment: "production"},
&CreateEnvironmentLock{
Environment: "production",
Message: "don't",
LockId: "manual",
Authentication: Authentication{RBACConfig: auth.RBACConfig{DexEnabled: true, Policy: map[string]*auth.Permission{
"releaseManager,CreateLock,production:production,*,allow": {Role: "releaseManager"}}}},
},
},
ctx: testutil.MakeTestContextDexEnabledUser("releaseManager"),
},
{
Name: "unable to create environment lock without permissions policy",
Transformers: []Transformer{
Expand Down Expand Up @@ -1152,8 +1253,12 @@ func TestRbacTransformerTest(t *testing.T) {
cmd := exec.Command("git", "init", "--bare", remoteDir)
cmd.Start()
cmd.Wait()
ctx := testutil.MakeTestContextDexEnabled()
if tc.ctx != nil {
ctx = tc.ctx
}
repo, err := New(
testutil.MakeTestContextDexEnabled(),
ctx,
RepositoryConfig{
URL: remoteDir,
Path: localDir,
Expand All @@ -1166,7 +1271,7 @@ func TestRbacTransformerTest(t *testing.T) {
t.Fatal(err)
}
for _, tf := range tc.Transformers {
err = repo.Apply(testutil.MakeTestContextDexEnabled(), tf)
err = repo.Apply(ctx, tf)
if err != nil {
break
}
Expand Down
3 changes: 2 additions & 1 deletion services/cd-service/pkg/service/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ func (d *BatchServer) processAction(
return nil, nil, err
}
return &repository.CreateUndeployApplicationVersion{
Application: act.Application,
Application: act.Application,
Authentication: repository.Authentication{RBACConfig: d.RBACConfig},
}, nil, nil
case *api.BatchAction_Undeploy:
act := action.Undeploy
Expand Down

0 comments on commit f7b0a88

Please sign in to comment.