From bfad9f44437a4404f6590f2b1c0a8cf20be65ece Mon Sep 17 00:00:00 2001 From: Bernardo Bastos Date: Thu, 3 Aug 2023 18:34:43 +0100 Subject: [PATCH 1/2] Add RBAC to ReleaseTrain --- .../cd-service/pkg/repository/transformer.go | 6 + .../pkg/repository/transformer_test.go | 112 ++++++++++++++++++ services/cd-service/pkg/service/batch.go | 5 +- 3 files changed, 121 insertions(+), 2 deletions(-) diff --git a/services/cd-service/pkg/repository/transformer.go b/services/cd-service/pkg/repository/transformer.go index 3bee7330b..647901c3b 100644 --- a/services/cd-service/pkg/repository/transformer.go +++ b/services/cd-service/pkg/repository/transformer.go @@ -984,6 +984,7 @@ func (c *DeployApplicationVersion) Transform(ctx context.Context, state *State) } type ReleaseTrain struct { + Authentication Target string Team string } @@ -1055,6 +1056,11 @@ func (c *ReleaseTrain) Transform(ctx context.Context, state *State) (string, err if envConfig.Upstream == nil { return fmt.Sprintf("Environment %q does not have upstream configured - exiting.", envName), nil } + err := state.checkUserPermissions(ctx, envName, "*", auth.PermissionDeployReleaseTrain, c.RBACConfig) + if err != nil { + return "", err + } + var upstreamLatest = envConfig.Upstream.Latest var upstreamEnvName = envConfig.Upstream.Environment diff --git a/services/cd-service/pkg/repository/transformer_test.go b/services/cd-service/pkg/repository/transformer_test.go index 6ac211265..15e8d9710 100644 --- a/services/cd-service/pkg/repository/transformer_test.go +++ b/services/cd-service/pkg/repository/transformer_test.go @@ -793,6 +793,118 @@ func TestRbacTransformerTest(t *testing.T) { Transformers []Transformer ExpectedError string }{ + { + Name: "able to create release train with permissions policy", + Transformers: []Transformer{ + &CreateEnvironment{ + Environment: envProduction, + Config: config.EnvironmentConfig{ + Upstream: &config.EnvironmentConfigUpstream{ + Environment: envAcceptance, // train drives from acceptance to production + }, + }, + }, + &CreateEnvironment{ + Environment: envAcceptance, + Config: config.EnvironmentConfig{ + Upstream: &config.EnvironmentConfigUpstream{ + Environment: envAcceptance, + Latest: true, + }, + }, + }, + &CreateApplicationVersion{ + Application: "test", + Manifests: map[string]string{ + envProduction: "productionmanifest", + envAcceptance: "acceptancenmanifest", + }, + }, + &DeployApplicationVersion{ + Environment: envProduction, + Application: "test", + Version: 1, + }, + &CreateApplicationVersion{ + Application: "test", + Manifests: map[string]string{ + envProduction: "productionmanifest", + envAcceptance: "acceptancenmanifest", + }, + }, + &DeployApplicationVersion{ + Environment: envAcceptance, + Application: "test", + Version: 1, + }, + &DeployApplicationVersion{ + Environment: envAcceptance, + Application: "test", + Version: 2, + }, + &ReleaseTrain{ + Target: envProduction, + Authentication: Authentication{RBACConfig: auth.RBACConfig{DexEnabled: true, Policy: map[string]*auth.Permission{ + "developer,DeployReleaseTrain,production:production,*,allow": {Role: "developer"}, + }}}, + }, + }, + { + Name: "unable to create release train without permissions policy", + Transformers: []Transformer{ + &CreateEnvironment{ + Environment: envProduction, + Config: config.EnvironmentConfig{ + Upstream: &config.EnvironmentConfigUpstream{ + Environment: envAcceptance, // train drives from acceptance to production + }, + }, + }, + &CreateEnvironment{ + Environment: envAcceptance, + Config: config.EnvironmentConfig{ + Upstream: &config.EnvironmentConfigUpstream{ + Environment: envAcceptance, + Latest: true, + }, + }, + }, + &CreateApplicationVersion{ + Application: "test", + Manifests: map[string]string{ + envProduction: "productionmanifest", + envAcceptance: "acceptancenmanifest", + }, + }, + &DeployApplicationVersion{ + Environment: envProduction, + Application: "test", + Version: 1, + }, + &CreateApplicationVersion{ + Application: "test", + Manifests: map[string]string{ + envProduction: "productionmanifest", + envAcceptance: "acceptancenmanifest", + }, + }, + &DeployApplicationVersion{ + Environment: envAcceptance, + Application: "test", + Version: 1, + }, + &DeployApplicationVersion{ + Environment: envAcceptance, + Application: "test", + Version: 2, + }, + &ReleaseTrain{ + Target: envProduction, + Authentication: Authentication{RBACConfig: auth.RBACConfig{DexEnabled: true, Policy: map[string]*auth.Permission{}}}, + }, + }, + ExpectedError: "user does not have permissions for: developer,DeployReleaseTrain,production:production,*,allow", + }, { Name: "able to create application version with permissions policy", Transformers: []Transformer{ diff --git a/services/cd-service/pkg/service/batch.go b/services/cd-service/pkg/service/batch.go index 1a926e1f1..ecbdfba97 100644 --- a/services/cd-service/pkg/service/batch.go +++ b/services/cd-service/pkg/service/batch.go @@ -190,8 +190,9 @@ func (d *BatchServer) processAction( return nil, nil, status.Error(codes.InvalidArgument, "invalid Team name") } return &repository.ReleaseTrain{ - Target: in.Target, - Team: in.Team, + Target: in.Target, + Team: in.Team, + Authentication: repository.Authentication{RBACConfig: d.RBACConfig}, }, &api.BatchResult{ Result: &api.BatchResult_ReleaseTrain{ ReleaseTrain: &api.ReleaseTrainResponse{Target: in.Target, Team: in.Team}, From 80020ce527087f70fcf072bf62719b2713efd4cd Mon Sep 17 00:00:00 2001 From: Bernardo Bastos Date: Fri, 4 Aug 2023 12:58:05 +0100 Subject: [PATCH 2/2] Pass authentication to create release --- .../cd-service/pkg/repository/transformer.go | 9 +- .../pkg/repository/transformer_test.go | 178 +++++++----------- 2 files changed, 77 insertions(+), 110 deletions(-) diff --git a/services/cd-service/pkg/repository/transformer.go b/services/cd-service/pkg/repository/transformer.go index 647901c3b..f0b8d2078 100644 --- a/services/cd-service/pkg/repository/transformer.go +++ b/services/cd-service/pkg/repository/transformer.go @@ -1142,10 +1142,11 @@ func (c *ReleaseTrain) Transform(ctx context.Context, state *State) (string, err } d := &DeployApplicationVersion{ - Environment: envName, // here we deploy to the next env - Application: appName, - Version: versionToDeploy, - LockBehaviour: api.LockBehavior_Record, + Environment: envName, // here we deploy to the next env + Application: appName, + Version: versionToDeploy, + LockBehaviour: api.LockBehavior_Record, + Authentication: c.Authentication, } transform, err := d.Transform(ctx, state) if err != nil { diff --git a/services/cd-service/pkg/repository/transformer_test.go b/services/cd-service/pkg/repository/transformer_test.go index 15e8d9710..18aa12201 100644 --- a/services/cd-service/pkg/repository/transformer_test.go +++ b/services/cd-service/pkg/repository/transformer_test.go @@ -795,114 +795,30 @@ func TestRbacTransformerTest(t *testing.T) { }{ { Name: "able to create release train with permissions policy", - Transformers: []Transformer{ - &CreateEnvironment{ - Environment: envProduction, - Config: config.EnvironmentConfig{ - Upstream: &config.EnvironmentConfigUpstream{ - Environment: envAcceptance, // train drives from acceptance to production - }, - }, - }, - &CreateEnvironment{ - Environment: envAcceptance, - Config: config.EnvironmentConfig{ - Upstream: &config.EnvironmentConfigUpstream{ - Environment: envAcceptance, - Latest: true, - }, - }, - }, - &CreateApplicationVersion{ - Application: "test", - Manifests: map[string]string{ - envProduction: "productionmanifest", - envAcceptance: "acceptancenmanifest", - }, - }, - &DeployApplicationVersion{ - Environment: envProduction, - Application: "test", - Version: 1, - }, - &CreateApplicationVersion{ - Application: "test", - Manifests: map[string]string{ - envProduction: "productionmanifest", - envAcceptance: "acceptancenmanifest", - }, - }, - &DeployApplicationVersion{ - Environment: envAcceptance, - Application: "test", - Version: 1, - }, - &DeployApplicationVersion{ - Environment: envAcceptance, - Application: "test", - Version: 2, - }, - &ReleaseTrain{ - Target: envProduction, - Authentication: Authentication{RBACConfig: auth.RBACConfig{DexEnabled: true, Policy: map[string]*auth.Permission{ - "developer,DeployReleaseTrain,production:production,*,allow": {Role: "developer"}, - }}}, - }, + Transformers: ReleaseTrainTestSetup(&ReleaseTrain{ + Target: envProduction, + Authentication: Authentication{RBACConfig: auth.RBACConfig{DexEnabled: true, Policy: map[string]*auth.Permission{ + "developer,DeployReleaseTrain,production:production,*,allow": {Role: "developer"}, + "developer,DeployRelease,production:*,test,allow": {Role: "developer"}, + }}}, + }), }, { - Name: "unable to create release train without permissions policy", - Transformers: []Transformer{ - &CreateEnvironment{ - Environment: envProduction, - Config: config.EnvironmentConfig{ - Upstream: &config.EnvironmentConfigUpstream{ - Environment: envAcceptance, // train drives from acceptance to production - }, - }, - }, - &CreateEnvironment{ - Environment: envAcceptance, - Config: config.EnvironmentConfig{ - Upstream: &config.EnvironmentConfigUpstream{ - Environment: envAcceptance, - Latest: true, - }, - }, - }, - &CreateApplicationVersion{ - Application: "test", - Manifests: map[string]string{ - envProduction: "productionmanifest", - envAcceptance: "acceptancenmanifest", - }, - }, - &DeployApplicationVersion{ - Environment: envProduction, - Application: "test", - Version: 1, - }, - &CreateApplicationVersion{ - Application: "test", - Manifests: map[string]string{ - envProduction: "productionmanifest", - envAcceptance: "acceptancenmanifest", - }, - }, - &DeployApplicationVersion{ - Environment: envAcceptance, - Application: "test", - Version: 1, - }, - &DeployApplicationVersion{ - Environment: envAcceptance, - Application: "test", - Version: 2, - }, - &ReleaseTrain{ - Target: envProduction, - Authentication: Authentication{RBACConfig: auth.RBACConfig{DexEnabled: true, Policy: map[string]*auth.Permission{}}}, - }, - }, + Name: "unable to create release train without permissions policy: Missing DeployRelease permission", + Transformers: ReleaseTrainTestSetup(&ReleaseTrain{ + Target: envProduction, + Authentication: Authentication{RBACConfig: auth.RBACConfig{DexEnabled: true, Policy: map[string]*auth.Permission{ + "developer,DeployReleaseTrain,production:production,*,allow": {Role: "developer"}, + }}}, + }), + ExpectedError: "rpc error: code = Internal desc = internal error", + }, + { + Name: "unable to create release train without permissions policy: Missing ReleaseTrain permission", + Transformers: ReleaseTrainTestSetup(&ReleaseTrain{ + Target: envProduction, + Authentication: Authentication{RBACConfig: auth.RBACConfig{DexEnabled: true, Policy: map[string]*auth.Permission{}}}, + }), ExpectedError: "user does not have permissions for: developer,DeployReleaseTrain,production:production,*,allow", }, { @@ -1269,6 +1185,56 @@ func TestRbacTransformerTest(t *testing.T) { } } +// Helper method to setup release train unit tests. +func ReleaseTrainTestSetup(releaseTrainTransformer Transformer) []Transformer { + return append([]Transformer{ + &CreateEnvironment{ + Environment: envProduction, + Config: config.EnvironmentConfig{ + Upstream: &config.EnvironmentConfigUpstream{ + Environment: envAcceptance, // train drives from acceptance to production + }, + }, + }, + &CreateEnvironment{ + Environment: envAcceptance, + Config: config.EnvironmentConfig{ + Upstream: &config.EnvironmentConfigUpstream{ + Latest: true, + }, + }, + }, + &CreateApplicationVersion{ + Application: "test", + Manifests: map[string]string{ + envProduction: "productionmanifest", + envAcceptance: "acceptancenmanifest", + }, + }, + &DeployApplicationVersion{ + Environment: envProduction, + Application: "test", + Version: 1, + }, + &CreateApplicationVersion{ + Application: "test", + Manifests: map[string]string{ + envProduction: "productionmanifest", + envAcceptance: "acceptancenmanifest", + }, + }, + &DeployApplicationVersion{ + Environment: envAcceptance, + Application: "test", + Version: 1, + }, + &DeployApplicationVersion{ + Environment: envAcceptance, + Application: "test", + Version: 2, + }}, releaseTrainTransformer) +} + func TestTransformer(t *testing.T) { c1 := config.EnvironmentConfig{Upstream: &config.EnvironmentConfigUpstream{Latest: true}}