From 470e6a30e123131a834160f5577a47f2dada137c Mon Sep 17 00:00:00 2001 From: Yann Brillouet <91869377+rhybrillou@users.noreply.github.com> Date: Sun, 20 Nov 2022 18:28:46 +0100 Subject: [PATCH] ROX-13326: Use UUID columns for roles, permissionsets and simpleaccessscopes in postgres mode. (#3802) --- central/role/accessscope_ids.go | 9 + central/role/datastore/permissionset_ids.go | 16 + central/role/datastore/singleton.go | 19 +- central/role/default.go | 19 +- .../store/permissionset/postgres/store.go | 4 +- .../store/simpleaccessscope/postgres/store.go | 4 +- central/role/validate.go | 42 +- central/role/validate_test.go | 107 ++- generated/storage/role.pb.go | 118 ++-- .../migration.go | 60 +- .../migration_test.go | 40 +- .../n_46_to_n_47_postgres_roles/migration.go | 56 +- .../migration_test.go | 40 +- .../legacypermissionsets}/rocksdb_plugin.go | 6 +- .../legacyroles}/rocksdb_plugin.go | 6 +- .../rocksdb_plugin.go | 6 +- .../migration.go | 232 ++++++- .../migration_test.go | 644 +++++++++++++++++- .../postgres_plugin.go | 22 +- .../postgresroles}/postgres_plugin.go | 9 +- .../postgres_plugin.go | 22 +- pkg/postgres/schema/permission_sets.go | 2 +- pkg/postgres/schema/simple_access_scopes.go | 2 +- proto/storage/role.proto | 8 +- .../src/test/groovy/BaseSpecification.groovy | 4 +- .../src/test/groovy/SACTest.groovy | 4 +- .../accessControlPermissionSets.test.js | 46 +- .../AccessScopes/AccessScopeForm.tsx | 8 +- .../AccessScopes/AccessScopeFormWrapper.tsx | 4 +- .../Containers/AccessControl/Roles/Roles.tsx | 26 +- .../src/services/AccessScopesService.ts | 13 + 31 files changed, 1261 insertions(+), 337 deletions(-) create mode 100644 central/role/accessscope_ids.go create mode 100644 central/role/datastore/permissionset_ids.go rename migrator/migrations/{n_37_to_n_38_postgres_permission_sets/legacy => n_52_to_n_53_postgres_simple_access_scopes/legacypermissionsets}/rocksdb_plugin.go (91%) rename migrator/migrations/{n_46_to_n_47_postgres_roles/legacy => n_52_to_n_53_postgres_simple_access_scopes/legacyroles}/rocksdb_plugin.go (90%) rename migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/{legacy => legacysimpleaccessscopes}/rocksdb_plugin.go (91%) rename migrator/migrations/{n_37_to_n_38_postgres_permission_sets/postgres => n_52_to_n_53_postgres_simple_access_scopes/postgrespermissionsets}/postgres_plugin.go (95%) rename migrator/migrations/{n_46_to_n_47_postgres_roles/postgres => n_52_to_n_53_postgres_simple_access_scopes/postgresroles}/postgres_plugin.go (98%) rename migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/{postgres => postgressimpleaccessscopes}/postgres_plugin.go (95%) diff --git a/central/role/accessscope_ids.go b/central/role/accessscope_ids.go new file mode 100644 index 0000000000000..2bfdb3beac518 --- /dev/null +++ b/central/role/accessscope_ids.go @@ -0,0 +1,9 @@ +package role + +// Postgres IDs for access scopes +// The values are UUIDs taken in descending order from ffffffff-ffff-fff4-f5ff-ffffffffffff +// Next ID: ffffffff-ffff-fff4-f5ff-fffffffffffd +const ( + unrestrictedAccessScopeID = "ffffffff-ffff-fff4-f5ff-ffffffffffff" + denyAllAccessScopeID = "ffffffff-ffff-fff4-f5ff-fffffffffffe" +) diff --git a/central/role/datastore/permissionset_ids.go b/central/role/datastore/permissionset_ids.go new file mode 100644 index 0000000000000..7c82bf7204b4a --- /dev/null +++ b/central/role/datastore/permissionset_ids.go @@ -0,0 +1,16 @@ +package datastore + +// Postgres IDs for permission sets +// The values are UUIDs taken in descending order from ffffffff-ffff-fff4-f5ff-ffffffffffff +// Next ID: ffffffff-ffff-fff4-f5ff-fffffffffff6 +const ( + adminPermissionSetID = "ffffffff-ffff-fff4-f5ff-ffffffffffff" + analystPermissionSetID = "ffffffff-ffff-fff4-f5ff-fffffffffffe" + continuousIntegrationPermissionSetID = "ffffffff-ffff-fff4-f5ff-fffffffffffd" + nonePermissionSetID = "ffffffff-ffff-fff4-f5ff-fffffffffffc" + scopeManagerPermissionSetID = "ffffffff-ffff-fff4-f5ff-fffffffffffb" + sensorCreatorPermissionSetID = "ffffffff-ffff-fff4-f5ff-fffffffffffa" + vulnMgmtApproverPermissionSetID = "ffffffff-ffff-fff4-f5ff-fffffffffff9" + vulnMgmtRequesterPermissionSetID = "ffffffff-ffff-fff4-f5ff-fffffffffff8" + vulnReporterPermissionSetID = "ffffffff-ffff-fff4-f5ff-fffffffffff7" +) diff --git a/central/role/datastore/singleton.go b/central/role/datastore/singleton.go index 15ff981a18527..6e4212a156bff 100644 --- a/central/role/datastore/singleton.go +++ b/central/role/datastore/singleton.go @@ -67,23 +67,34 @@ func Singleton() DataStore { type roleAttributes struct { idSuffix string + postgresID string // postgresID should be populated with valid UUID values. description string resourceWithAccess []permissions.ResourceWithAccess } +func (attributes *roleAttributes) getID() string { + if env.PostgresDatastoreEnabled.BooleanSetting() { + return attributes.postgresID + } + return rolePkg.EnsureValidPermissionSetID(attributes.idSuffix) +} + var defaultRoles = map[string]roleAttributes{ rolePkg.Admin: { idSuffix: "admin", + postgresID: adminPermissionSetID, description: "For users: use it to provide read and write access to all the resources", resourceWithAccess: resources.AllResourcesModifyPermissions(), }, rolePkg.Analyst: { idSuffix: "analyst", + postgresID: analystPermissionSetID, resourceWithAccess: rolePkg.GetAnalystPermissions(), description: "For users: use it to give read-only access to all the resources", }, rolePkg.ContinuousIntegration: { idSuffix: "continuousintegration", + postgresID: continuousIntegrationPermissionSetID, description: "For automation: it includes the permissions required to enforce deployment policies", resourceWithAccess: []permissions.ResourceWithAccess{ permissions.View(resources.Detection), @@ -92,10 +103,12 @@ var defaultRoles = map[string]roleAttributes{ }, rolePkg.None: { idSuffix: "none", + postgresID: nonePermissionSetID, description: "For users: use it to provide no read and write access to any resource", }, rolePkg.ScopeManager: { idSuffix: "scopemanager", + postgresID: scopeManagerPermissionSetID, description: "For users: use it to create and modify scopes for the purpose of access control or vulnerability reporting", resourceWithAccess: []permissions.ResourceWithAccess{ permissions.View(resources.Access), @@ -107,6 +120,7 @@ var defaultRoles = map[string]roleAttributes{ }, rolePkg.SensorCreator: { idSuffix: "sensorcreator", + postgresID: sensorCreatorPermissionSetID, description: "For automation: it consists of the permissions to create Sensors in secured clusters", resourceWithAccess: []permissions.ResourceWithAccess{ permissions.View(resources.Cluster), @@ -117,6 +131,7 @@ var defaultRoles = map[string]roleAttributes{ }, rolePkg.VulnMgmtApprover: { idSuffix: "vulnmgmtapprover", + postgresID: vulnMgmtApproverPermissionSetID, description: "For users: use it to provide access to approve vulnerability deferrals or false positive requests", resourceWithAccess: []permissions.ResourceWithAccess{ permissions.View(resources.VulnerabilityManagementApprovals), @@ -125,6 +140,7 @@ var defaultRoles = map[string]roleAttributes{ }, rolePkg.VulnMgmtRequester: { idSuffix: "vulnmgmtrequester", + postgresID: vulnMgmtRequesterPermissionSetID, description: "For users: use it to provide access to request vulnerability deferrals or false positives", resourceWithAccess: []permissions.ResourceWithAccess{ permissions.View(resources.VulnerabilityManagementRequests), @@ -136,6 +152,7 @@ var defaultRoles = map[string]roleAttributes{ var vulnReportingDefaultRoles = map[string]roleAttributes{ rolePkg.VulnReporter: { idSuffix: "vulnreporter", + postgresID: vulnReporterPermissionSetID, description: "For users: use it to create and manage vulnerability reporting configurations for scheduled vulnerability reports", resourceWithAccess: []permissions.ResourceWithAccess{ permissions.View(resources.VulnerabilityReports), // required for vuln report configurations @@ -161,7 +178,7 @@ func getDefaultObjects() ([]*storage.Role, []*storage.PermissionSet, []*storage. } permissionSet := &storage.PermissionSet{ - Id: rolePkg.EnsureValidPermissionSetID(attributes.idSuffix), + Id: attributes.getID(), Name: role.Name, Description: role.Description, ResourceToAccess: resourceToAccess, diff --git a/central/role/default.go b/central/role/default.go index 4a3a0ec8c3266..d4fc02ce2a645 100644 --- a/central/role/default.go +++ b/central/role/default.go @@ -4,6 +4,7 @@ import ( "github.com/stackrox/rox/central/role/resources" "github.com/stackrox/rox/generated/storage" "github.com/stackrox/rox/pkg/auth/permissions" + "github.com/stackrox/rox/pkg/env" "github.com/stackrox/rox/pkg/grpc/authn" "github.com/stackrox/rox/pkg/set" ) @@ -48,7 +49,7 @@ var ( // AccessScopeExcludeAll has empty rules and hence excludes all // scoped resources. Global resources must be unaffected. AccessScopeExcludeAll = &storage.SimpleAccessScope{ - Id: EnsureValidAccessScopeID("denyall"), + Id: getAccessScopeExcludeAllID(), Name: "Deny All", Description: "No access to scoped resources", Rules: &storage.SimpleAccessScope_Rules{}, @@ -57,12 +58,26 @@ var ( // AccessScopeIncludeAll gives access to all resources. It is checked by ID, as // Rules cannot represent unrestricted scope. AccessScopeIncludeAll = &storage.SimpleAccessScope{ - Id: EnsureValidAccessScopeID("unrestricted"), + Id: getAccessScopeIncludeAllID(), Name: "Unrestricted", Description: "Access to all clusters and namespaces", } ) +func getAccessScopeExcludeAllID() string { + if env.PostgresDatastoreEnabled.BooleanSetting() { + return denyAllAccessScopeID + } + return EnsureValidAccessScopeID("denyall") +} + +func getAccessScopeIncludeAllID() string { + if env.PostgresDatastoreEnabled.BooleanSetting() { + return unrestrictedAccessScopeID + } + return EnsureValidAccessScopeID("unrestricted") +} + // IsDefaultRoleName checks if a given role name corresponds to a default role. func IsDefaultRoleName(name string) bool { return DefaultRoleNames.Contains(name) diff --git a/central/role/store/permissionset/postgres/store.go b/central/role/store/permissionset/postgres/store.go index d453ebc785bb7..94557d3c785d1 100644 --- a/central/role/store/permissionset/postgres/store.go +++ b/central/role/store/permissionset/postgres/store.go @@ -84,7 +84,7 @@ func insertIntoPermissionSets(ctx context.Context, batch *pgx.Batch, obj *storag values := []interface{}{ // parent primary keys start - obj.GetId(), + pgutils.NilOrUUID(obj.GetId()), obj.GetName(), serialized, } @@ -125,7 +125,7 @@ func (s *storeImpl) copyFromPermissionSets(ctx context.Context, tx pgx.Tx, objs inputRows = append(inputRows, []interface{}{ - obj.GetId(), + pgutils.NilOrUUID(obj.GetId()), obj.GetName(), diff --git a/central/role/store/simpleaccessscope/postgres/store.go b/central/role/store/simpleaccessscope/postgres/store.go index 966957950c0a8..3e11b8b86fd7a 100644 --- a/central/role/store/simpleaccessscope/postgres/store.go +++ b/central/role/store/simpleaccessscope/postgres/store.go @@ -84,7 +84,7 @@ func insertIntoSimpleAccessScopes(ctx context.Context, batch *pgx.Batch, obj *st values := []interface{}{ // parent primary keys start - obj.GetId(), + pgutils.NilOrUUID(obj.GetId()), obj.GetName(), serialized, } @@ -125,7 +125,7 @@ func (s *storeImpl) copyFromSimpleAccessScopes(ctx context.Context, tx pgx.Tx, o inputRows = append(inputRows, []interface{}{ - obj.GetId(), + pgutils.NilOrUUID(obj.GetId()), obj.GetName(), diff --git a/central/role/validate.go b/central/role/validate.go index 5fb83049f56c7..5b77a6d69538e 100644 --- a/central/role/validate.go +++ b/central/role/validate.go @@ -8,6 +8,7 @@ import ( "github.com/stackrox/rox/central/role/resources" "github.com/stackrox/rox/generated/storage" "github.com/stackrox/rox/pkg/auth/permissions" + "github.com/stackrox/rox/pkg/env" "github.com/stackrox/rox/pkg/sac/effectiveaccessscope" "github.com/stackrox/rox/pkg/uuid" "k8s.io/apimachinery/pkg/labels" @@ -25,34 +26,60 @@ const ( accessScopeIDPrefix = "io.stackrox.authz.accessscope." ) +func generateIdentifier(prefix string) string { + generatedIDSuffix := uuid.NewV4().String() + if env.PostgresDatastoreEnabled.BooleanSetting() { + return generatedIDSuffix + } + return prefix + generatedIDSuffix +} + +func isValidIdentifier(prefix string, id string) bool { + if env.PostgresDatastoreEnabled.BooleanSetting() { + _, parseErr := uuid.FromString(id) + return parseErr == nil + } + return strings.HasPrefix(id, prefix) +} + // GeneratePermissionSetID returns a random valid permission set ID. func GeneratePermissionSetID() string { - return permissionSetIDPrefix + uuid.NewV4().String() + return generateIdentifier(permissionSetIDPrefix) } // EnsureValidPermissionSetID converts id to the correct format if necessary. func EnsureValidPermissionSetID(id string) string { - if strings.HasPrefix(id, permissionSetIDPrefix) { + if isValidIdentifier(permissionSetIDPrefix, id) { return id } + if env.PostgresDatastoreEnabled.BooleanSetting() { + return generateIdentifier(permissionSetIDPrefix) + } return permissionSetIDPrefix + id } // GenerateAccessScopeID returns a random valid access scope ID. func GenerateAccessScopeID() string { - return accessScopeIDPrefix + uuid.NewV4().String() + return generateIdentifier(accessScopeIDPrefix) } // EnsureValidAccessScopeID converts id to the correct format if necessary. func EnsureValidAccessScopeID(id string) string { - if strings.HasPrefix(id, accessScopeIDPrefix) { + if isValidIdentifier(accessScopeIDPrefix, id) { return id } + if env.PostgresDatastoreEnabled.BooleanSetting() { + return generateIdentifier(accessScopeIDPrefix) + } return accessScopeIDPrefix + id } // ValidateAccessScopeID returns an error if the scope ID prefix is not correct. func ValidateAccessScopeID(scope *storage.SimpleAccessScope) error { + if env.PostgresDatastoreEnabled.BooleanSetting() { + _, parseErr := uuid.FromString(scope.GetId()) + return parseErr + } if !strings.HasPrefix(scope.GetId(), accessScopeIDPrefix) { return errors.Errorf("id field must be in '%s*' format", accessScopeIDPrefix) } @@ -92,7 +119,12 @@ func ValidateRole(role *storage.Role) error { func ValidatePermissionSet(ps *storage.PermissionSet) error { var multiErr error - if !strings.HasPrefix(ps.GetId(), permissionSetIDPrefix) { + if env.PostgresDatastoreEnabled.BooleanSetting() { + _, parseErr := uuid.FromString(ps.GetId()) + if parseErr != nil { + multiErr = multierror.Append(multiErr, errors.Wrap(parseErr, "id field must be a valid UUID")) + } + } else if !strings.HasPrefix(ps.GetId(), permissionSetIDPrefix) { multiErr = multierror.Append(multiErr, errors.Errorf("id field must be in '%s*' format", permissionSetIDPrefix)) } if ps.GetName() == "" { diff --git a/central/role/validate_test.go b/central/role/validate_test.go index 811ac4bc39266..56267d6a95884 100644 --- a/central/role/validate_test.go +++ b/central/role/validate_test.go @@ -2,11 +2,14 @@ package role import ( "errors" + "strings" "testing" "github.com/hashicorp/go-multierror" "github.com/stackrox/rox/generated/storage" + "github.com/stackrox/rox/pkg/env" labelUtils "github.com/stackrox/rox/pkg/labels" + "github.com/stackrox/rox/pkg/uuid" "github.com/stretchr/testify/assert" ) @@ -51,7 +54,12 @@ func constructRole(name, permissionSetID, accessScopeID string) *storage.Role { } func TestValidatePermissionSet(t *testing.T) { - mockGoodID := permissionSetIDPrefix + "Tanis Half-Elven" + var mockGoodID string + if env.PostgresDatastoreEnabled.BooleanSetting() { + mockGoodID = uuid.NewDummy().String() + } else { + mockGoodID = permissionSetIDPrefix + "Tanis Half-Elven" + } mockBadID := "Tanis Half-Elven" mockName := "Hero of the Lance" mockGoodResource := "K8sRoleBinding" @@ -107,8 +115,62 @@ func TestValidatePermissionSet(t *testing.T) { } } +func TestGeneratePermissionSetID(t *testing.T) { + generatedID := GeneratePermissionSetID() + if !env.PostgresDatastoreEnabled.BooleanSetting() { + assert.True(t, strings.HasPrefix(generatedID, permissionSetIDPrefix)) + } + var generatedIDSuffix string + if env.PostgresDatastoreEnabled.BooleanSetting() { + generatedIDSuffix = generatedID + } else { + generatedIDSuffix = strings.TrimPrefix(generatedID, permissionSetIDPrefix) + } + _, err := uuid.FromString(generatedIDSuffix) + assert.NoError(t, err) +} + +func TestEnsureValidPermissionSetID(t *testing.T) { + if env.PostgresDatastoreEnabled.BooleanSetting() { + t.Skip() + } + validID := GeneratePermissionSetID() + checkedValidID := EnsureValidPermissionSetID(validID) + assert.Equal(t, validID, checkedValidID) + + suffix := "some identifier" + // Test that prefixed ID is returned as is + prefixedID := permissionSetIDPrefix + suffix + checkedPrefixedID := EnsureValidPermissionSetID(prefixedID) + assert.Equal(t, prefixedID, checkedPrefixedID) + // Test that unprefixed ID is returned with permissionSetID prefix prepended + checkedNonPrefixedID := EnsureValidPermissionSetID(suffix) + assert.Equal(t, permissionSetIDPrefix+suffix, checkedNonPrefixedID) +} + +func TestEnsureValidPermissionSetIDPostgres(t *testing.T) { + if !env.PostgresDatastoreEnabled.BooleanSetting() { + t.Skip() + } + validID := GeneratePermissionSetID() + checkedValidID := EnsureValidPermissionSetID(validID) + assert.Equal(t, validID, checkedValidID) + + // Test that an invalid ID triggers the generation of a valid UUID. + invalidID := "abcdefgh-ijkl-mnop-qrst-uvwxyz012345" + checkedInvalidID := EnsureValidPermissionSetID(invalidID) + assert.NotEqual(t, invalidID, checkedInvalidID) + _, err := uuid.FromString(checkedInvalidID) + assert.NoError(t, err) +} + func TestValidateSimpleAccessScope(t *testing.T) { - mockGoodID := EnsureValidAccessScopeID("42") + var mockGoodID string + if env.PostgresDatastoreEnabled.BooleanSetting() { + mockGoodID = uuid.NewDummy().String() + } else { + mockGoodID = EnsureValidAccessScopeID("42") + } mockBadID := "42" mockName := "Heart of Gold" mockDescription := "HHGTTG" @@ -343,7 +405,42 @@ func TestValidateSimpleAccessScopeRules(t *testing.T) { } func TestGenerateAccessScopeID(t *testing.T) { - id := GenerateAccessScopeID() - validID := EnsureValidAccessScopeID(id) - assert.Equal(t, id, validID) + generatedID := GenerateAccessScopeID() + validID := EnsureValidAccessScopeID(generatedID) + assert.Equal(t, generatedID, validID) + if !env.PostgresDatastoreEnabled.BooleanSetting() { + assert.True(t, strings.HasPrefix(generatedID, accessScopeIDPrefix)) + } + var generatedIDSuffix string + if env.PostgresDatastoreEnabled.BooleanSetting() { + generatedIDSuffix = generatedID + } else { + generatedIDSuffix = strings.TrimPrefix(generatedID, accessScopeIDPrefix) + } + _, err := uuid.FromString(generatedIDSuffix) + assert.NoError(t, err) +} + +func TestEnsureValidAccessScopeID(t *testing.T) { + validID := GenerateAccessScopeID() + checkedValidID := EnsureValidAccessScopeID(validID) + assert.Equal(t, validID, checkedValidID) + + if env.PostgresDatastoreEnabled.BooleanSetting() { + // Test that an invalid ID triggers the generation of a valid UUID. + invalidID := "abcdefgh-ijkl-mnop-qrst-uvwxyz012345" + checkedInvalidID := EnsureValidAccessScopeID(invalidID) + assert.NotEqual(t, invalidID, checkedInvalidID) + _, err := uuid.FromString(checkedInvalidID) + assert.NoError(t, err) + } else { + suffix := "some identifier" + // Test that prefixed ID is returned as is + prefixedID := accessScopeIDPrefix + suffix + checkedPrefixedID := EnsureValidAccessScopeID(prefixedID) + assert.Equal(t, prefixedID, checkedPrefixedID) + // Test that unprefixed ID is returned with permissionSetID prefix prepended + checkedNonPrefixedID := EnsureValidAccessScopeID(suffix) + assert.Equal(t, accessScopeIDPrefix+suffix, checkedNonPrefixedID) + } } diff --git a/generated/storage/role.pb.go b/generated/storage/role.pb.go index 1ad83a58a827e..413413ba00bbc 100644 --- a/generated/storage/role.pb.go +++ b/generated/storage/role.pb.go @@ -91,8 +91,8 @@ type Role struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty" sql:"pk"` Description string `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"` // The associated PermissionSet and AccessScope for this Role. - PermissionSetId string `protobuf:"bytes,6,opt,name=permission_set_id,json=permissionSetId,proto3" json:"permission_set_id,omitempty"` - AccessScopeId string `protobuf:"bytes,7,opt,name=access_scope_id,json=accessScopeId,proto3" json:"access_scope_id,omitempty"` + PermissionSetId string `protobuf:"bytes,6,opt,name=permission_set_id,json=permissionSetId,proto3" json:"permission_set_id,omitempty" sql:"type(uuid)"` + AccessScopeId string `protobuf:"bytes,7,opt,name=access_scope_id,json=accessScopeId,proto3" json:"access_scope_id,omitempty" sql:"type(uuid)"` // Minimum (not default!) access level for every resource. Can be extended // below by explicit permissions but not shrunk. // Deprecated 2021-04-20 in favor of `permission_set_id`. @@ -204,7 +204,7 @@ func (m *Role) Clone() *Role { // This encodes a set of permissions for StackRox resources. type PermissionSet struct { // id is generated and cannot be changed. - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" sql:"pk"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" sql:"pk,type(uuid)"` // `name` and `description` are provided by the user and can be changed. Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty" sql:"unique"` Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` @@ -298,7 +298,7 @@ func (m *PermissionSet) Clone() *PermissionSet { // It does *not* allow multi-component AND-rules nor set operations on names. type SimpleAccessScope struct { // `id` is generated and cannot be changed. - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" sql:"pk"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" sql:"pk,type(uuid)"` // `name` and `description` are provided by the user and can be changed. Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty" sql:"unique"` Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` @@ -847,60 +847,62 @@ func init() { func init() { proto.RegisterFile("storage/role.proto", fileDescriptor_dc9b4bbfaa99ac3e) } var fileDescriptor_dc9b4bbfaa99ac3e = []byte{ - // 844 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xe1, 0x8e, 0xdb, 0x44, - 0x10, 0x3e, 0xdb, 0xf1, 0xdd, 0x65, 0x9c, 0xdc, 0x39, 0x4b, 0x4e, 0x4d, 0x2d, 0x94, 0x86, 0xc0, - 0x41, 0x74, 0x20, 0x57, 0xa4, 0x08, 0xb5, 0x95, 0x10, 0x4a, 0x72, 0x11, 0x0a, 0x3d, 0xa5, 0xd5, - 0x26, 0xa1, 0xe8, 0xf8, 0x61, 0xf9, 0xec, 0x6d, 0x64, 0x9d, 0x2f, 0x9b, 0x7a, 0x9d, 0x8a, 0x3e, - 0x03, 0x2f, 0xc0, 0x0f, 0xfe, 0xf3, 0x08, 0x3c, 0x02, 0xfc, 0xec, 0x13, 0x54, 0xe8, 0x78, 0x83, - 0x7b, 0x02, 0xb4, 0xeb, 0xb5, 0xe3, 0x70, 0x2e, 0x9c, 0x84, 0xda, 0x7f, 0x9b, 0x6f, 0xbe, 0x99, - 0x9d, 0xf9, 0x66, 0x66, 0x63, 0x40, 0x2c, 0xa6, 0x91, 0x3b, 0x27, 0x77, 0x23, 0x1a, 0x12, 0x7b, - 0x19, 0xd1, 0x98, 0xa2, 0x1d, 0x89, 0x59, 0xf5, 0xd4, 0x18, 0xba, 0x67, 0x24, 0x64, 0x89, 0xd9, - 0xaa, 0xcf, 0xe9, 0x9c, 0x8a, 0xe3, 0x5d, 0x7e, 0x4a, 0xd0, 0xf6, 0x4f, 0x1a, 0x94, 0x30, 0x0d, - 0x09, 0x6a, 0x41, 0x69, 0xe1, 0x5e, 0x90, 0x86, 0xd2, 0x52, 0x3a, 0xe5, 0x7e, 0xe5, 0xea, 0xf5, - 0x9d, 0x5d, 0xf6, 0x3c, 0x7c, 0xd8, 0x5e, 0x9e, 0xb7, 0xb1, 0xb0, 0xa0, 0x16, 0x18, 0x3e, 0x61, - 0x5e, 0x14, 0x2c, 0xe3, 0x80, 0x2e, 0x1a, 0x3a, 0x27, 0xe2, 0x3c, 0x84, 0x8e, 0xa0, 0xb6, 0x24, - 0xd1, 0x45, 0xc0, 0x58, 0x40, 0x17, 0x0e, 0x23, 0xb1, 0x13, 0xf8, 0x8d, 0x6d, 0xc1, 0xdb, 0x5f, - 0x1b, 0x26, 0x24, 0x1e, 0xf9, 0xe8, 0x63, 0xd8, 0x77, 0x3d, 0x8f, 0x30, 0xe6, 0x30, 0x8f, 0x2e, - 0x09, 0x67, 0xee, 0x08, 0x66, 0x35, 0x81, 0x27, 0x1c, 0x1d, 0xf9, 0xe8, 0x3e, 0x54, 0xe7, 0x21, - 0x3d, 0x73, 0x43, 0x27, 0xc1, 0x1b, 0x6a, 0x4b, 0xe9, 0xec, 0x75, 0xf7, 0x6d, 0x59, 0xa4, 0xdd, - 0x13, 0x70, 0x5f, 0x6d, 0x28, 0xb8, 0x92, 0x30, 0x13, 0x04, 0xcd, 0x00, 0x45, 0x84, 0xd1, 0x55, - 0xe4, 0x11, 0x27, 0xa6, 0xa9, 0xbb, 0xd6, 0xd2, 0x3a, 0x46, 0xf7, 0xc3, 0xcc, 0x9d, 0x17, 0x6f, - 0x63, 0xc9, 0x9b, 0xd2, 0xc4, 0x77, 0xb8, 0x88, 0xa3, 0x97, 0x22, 0xa4, 0x19, 0xfd, 0xc3, 0x64, - 0x4d, 0xe1, 0xa0, 0x90, 0x8e, 0x4c, 0xd0, 0xce, 0xc9, 0xcb, 0x44, 0x40, 0xcc, 0x8f, 0xe8, 0x10, - 0xf4, 0x17, 0x6e, 0xb8, 0x22, 0x6f, 0xc8, 0x19, 0x27, 0xd6, 0x87, 0xea, 0x7d, 0xe5, 0xdb, 0xd2, - 0x6e, 0xc9, 0xd4, 0xdb, 0xbf, 0xaa, 0x50, 0x7d, 0x92, 0x17, 0x0a, 0xbd, 0x0f, 0x6a, 0xe0, 0x17, - 0x36, 0x45, 0x0d, 0x7c, 0xf4, 0x91, 0x6c, 0x9a, 0x2a, 0xec, 0xe6, 0xd5, 0xeb, 0x3b, 0x15, 0x61, - 0x5f, 0x2d, 0x82, 0xe7, 0x2b, 0xf2, 0x86, 0xc6, 0x69, 0xd7, 0x1b, 0x77, 0x5a, 0x28, 0x55, 0x49, - 0x48, 0xf5, 0x59, 0x96, 0xf5, 0x46, 0x66, 0xc5, 0x9a, 0xbd, 0x2b, 0xbd, 0xda, 0xaf, 0x4a, 0x50, - 0x9b, 0x04, 0x17, 0xcb, 0x90, 0xf4, 0xd6, 0xe3, 0xf2, 0x8e, 0xd4, 0xfa, 0x12, 0xf4, 0x68, 0x15, - 0x12, 0x2e, 0x90, 0xd2, 0x31, 0xba, 0xad, 0x2c, 0xcd, 0x6b, 0x09, 0xd9, 0x98, 0xf3, 0x70, 0x42, - 0xb7, 0x7e, 0xd1, 0x40, 0x17, 0x00, 0xfa, 0x14, 0x6a, 0xc1, 0xc2, 0x0b, 0x57, 0x3e, 0xf1, 0x1d, - 0x2f, 0x5c, 0xb1, 0x98, 0x44, 0xac, 0xa1, 0xb4, 0xb4, 0x4e, 0x19, 0x9b, 0xa9, 0x61, 0x20, 0x71, - 0xf4, 0x03, 0xbc, 0x97, 0x91, 0x79, 0x86, 0x6c, 0xe9, 0x7a, 0x84, 0xef, 0x01, 0xef, 0xce, 0xd1, - 0x7f, 0x5d, 0x6e, 0x8f, 0x53, 0x17, 0x8c, 0xd2, 0x30, 0x19, 0xc4, 0xd0, 0x77, 0x70, 0x4b, 0x26, - 0xe0, 0x88, 0xd7, 0xc2, 0x61, 0x24, 0x24, 0x5e, 0x4c, 0xa3, 0x74, 0x53, 0x9a, 0xeb, 0x0b, 0x48, - 0xdc, 0x77, 0x19, 0xf1, 0x4f, 0x38, 0x6f, 0x22, 0x69, 0xf8, 0x40, 0xba, 0x6f, 0xa0, 0x0c, 0x9d, - 0xc2, 0xed, 0x2c, 0xd7, 0x6b, 0x91, 0x4b, 0x37, 0x8a, 0x7c, 0x2b, 0x0b, 0xb0, 0x19, 0xdb, 0x9a, - 0x41, 0x39, 0xab, 0x00, 0x7d, 0x00, 0x95, 0xb4, 0x80, 0xf5, 0xfb, 0x85, 0x0d, 0x89, 0x71, 0x1e, - 0x3a, 0x84, 0xbd, 0x75, 0x2e, 0xeb, 0x09, 0xc0, 0xd5, 0x0c, 0xe5, 0xb4, 0xf6, 0xef, 0x3a, 0xd4, - 0x87, 0xcf, 0x9e, 0x11, 0x2f, 0x0e, 0x5e, 0x6c, 0x4c, 0x55, 0x0f, 0x76, 0x37, 0x9a, 0x64, 0x74, - 0x0f, 0xb3, 0xd4, 0x8b, 0x1c, 0x6c, 0xd9, 0x3a, 0x9c, 0xb9, 0x59, 0x57, 0x4a, 0x3e, 0xe7, 0xbd, - 0xf5, 0x98, 0x8a, 0xc1, 0x44, 0xf9, 0xc1, 0x94, 0x63, 0xf8, 0x00, 0x74, 0x16, 0xbb, 0x31, 0x11, - 0x03, 0xb8, 0x97, 0x7b, 0xb0, 0x0a, 0x6f, 0x9c, 0x70, 0x2a, 0x4e, 0x3c, 0xd0, 0x23, 0xd8, 0x4e, - 0x5e, 0x7e, 0x29, 0xf4, 0xbd, 0x7f, 0xf7, 0xcd, 0xf2, 0xb2, 0x85, 0xce, 0x72, 0x91, 0x65, 0x08, - 0xeb, 0x01, 0x18, 0x39, 0xb8, 0x60, 0x69, 0xeb, 0xf9, 0xa5, 0x2d, 0xe7, 0x76, 0xd4, 0xfa, 0x4d, - 0x85, 0x1d, 0x29, 0xc5, 0xdb, 0x2e, 0x79, 0x94, 0x95, 0xac, 0x8b, 0x92, 0x3f, 0xbf, 0x51, 0x83, - 0x8a, 0x0a, 0x46, 0xdf, 0x00, 0xe4, 0xb6, 0x2c, 0x51, 0xf0, 0x93, 0x1b, 0x2a, 0x88, 0x73, 0xae, - 0xff, 0x43, 0xb9, 0xf6, 0x57, 0xa0, 0x8b, 0xf2, 0x90, 0x01, 0x3b, 0xb3, 0xf1, 0xa3, 0xf1, 0xe3, - 0xa7, 0x63, 0x73, 0x0b, 0x55, 0x60, 0x77, 0x34, 0x1e, 0x9c, 0xcc, 0x8e, 0x87, 0xc7, 0xa6, 0xc2, - 0x7f, 0x0d, 0xbf, 0x97, 0xbf, 0x54, 0x4e, 0x7c, 0xd2, 0xc3, 0xd3, 0x51, 0xef, 0xc4, 0xd4, 0x8e, - 0xbe, 0x86, 0x6d, 0xf9, 0x1f, 0x58, 0x85, 0xf2, 0xf8, 0xb1, 0xd3, 0x1b, 0x0c, 0x86, 0x93, 0x89, - 0xb9, 0x85, 0xf6, 0xc1, 0xc0, 0xc3, 0xde, 0x71, 0x0a, 0x28, 0xe8, 0x00, 0x6a, 0x02, 0x78, 0x8a, - 0x47, 0xd3, 0x61, 0x0a, 0xab, 0xfd, 0x2f, 0xfe, 0xb8, 0x6c, 0x2a, 0xaf, 0x2e, 0x9b, 0xca, 0x9f, - 0x97, 0x4d, 0xe5, 0xe7, 0xbf, 0x9a, 0x5b, 0x70, 0x3b, 0xa0, 0x36, 0x8b, 0x5d, 0xef, 0x3c, 0xa2, - 0x3f, 0x26, 0x9f, 0x0e, 0xa9, 0x24, 0xa7, 0xe9, 0x77, 0xc7, 0xd9, 0xb6, 0xc0, 0xef, 0xfd, 0x1d, - 0x00, 0x00, 0xff, 0xff, 0x4e, 0x20, 0x25, 0x14, 0x9d, 0x08, 0x00, 0x00, + // 871 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x51, 0x6f, 0xdb, 0x54, + 0x14, 0xae, 0x9d, 0xb8, 0x6d, 0x8e, 0x93, 0xd6, 0xbd, 0x4b, 0xd5, 0xcc, 0x0f, 0x69, 0x30, 0x54, + 0x0b, 0x63, 0xf2, 0x44, 0x87, 0xd0, 0x36, 0x81, 0x20, 0x6d, 0x23, 0x14, 0x56, 0x65, 0xd3, 0x4d, + 0xcb, 0x50, 0x79, 0xb0, 0x5c, 0xfb, 0xae, 0xb2, 0xea, 0xe6, 0x7a, 0xbe, 0xf6, 0x44, 0xff, 0x09, + 0x0f, 0xfc, 0x0a, 0x5e, 0xf6, 0x13, 0xe0, 0x91, 0x77, 0xa4, 0x08, 0x95, 0x7f, 0x90, 0x5f, 0x80, + 0xee, 0xf5, 0xb5, 0xe3, 0xd0, 0x6c, 0x54, 0x42, 0xf4, 0xcd, 0xfe, 0xee, 0xf7, 0x1d, 0x9f, 0xf3, + 0x9d, 0x73, 0x6c, 0x03, 0x62, 0x09, 0x8d, 0xdd, 0x33, 0xf2, 0x30, 0xa6, 0x21, 0xb1, 0xa3, 0x98, + 0x26, 0x14, 0xad, 0x48, 0xcc, 0x6c, 0xe6, 0x87, 0xa1, 0x7b, 0x4a, 0x42, 0x96, 0x1d, 0x9b, 0xcd, + 0x33, 0x7a, 0x46, 0xc5, 0xe5, 0x43, 0x7e, 0x95, 0xa1, 0xd6, 0xdb, 0x0a, 0x54, 0x31, 0x0d, 0x09, + 0xea, 0x40, 0x75, 0xec, 0x5e, 0x90, 0x96, 0xd2, 0x51, 0xba, 0xb5, 0xbd, 0xfa, 0x74, 0xb2, 0xbd, + 0xca, 0x5e, 0x87, 0x4f, 0xad, 0xe8, 0xdc, 0xc2, 0xe2, 0x04, 0x75, 0x40, 0xf7, 0x09, 0xf3, 0xe2, + 0x20, 0x4a, 0x02, 0x3a, 0x6e, 0x69, 0x9c, 0x88, 0xcb, 0x10, 0xfa, 0x1a, 0x36, 0x22, 0x12, 0x5f, + 0x04, 0x8c, 0x05, 0x74, 0xec, 0x30, 0x92, 0x38, 0x81, 0xdf, 0x5a, 0x16, 0x01, 0x9b, 0xd3, 0xc9, + 0xb6, 0x21, 0x02, 0x26, 0x97, 0x11, 0xe9, 0xa6, 0x69, 0xe0, 0x7f, 0x6c, 0xe1, 0xf5, 0x19, 0x7d, + 0x44, 0x92, 0x81, 0x8f, 0xbe, 0x80, 0x75, 0xd7, 0xf3, 0x08, 0x63, 0x0e, 0xf3, 0x68, 0x44, 0xb8, + 0x7e, 0xe5, 0x3d, 0xfa, 0x46, 0x46, 0x1e, 0x71, 0xee, 0xc0, 0x47, 0x8f, 0xa1, 0x71, 0x16, 0xd2, + 0x53, 0x37, 0x74, 0x32, 0xbc, 0xa5, 0x76, 0x94, 0xee, 0xda, 0xee, 0xba, 0x2d, 0x0d, 0xb1, 0x7b, + 0x02, 0xde, 0x53, 0x5b, 0x0a, 0xae, 0x67, 0xcc, 0x0c, 0x41, 0xc7, 0x80, 0x62, 0xc2, 0x68, 0x1a, + 0x7b, 0xc4, 0x49, 0x68, 0x2e, 0xaf, 0x74, 0x2a, 0x5d, 0x7d, 0xf7, 0xc3, 0x42, 0xce, 0x8d, 0xb2, + 0xb1, 0xe4, 0x1d, 0xd1, 0x4c, 0xdb, 0x1f, 0x27, 0xf1, 0xa5, 0x08, 0x69, 0xc4, 0xff, 0x38, 0x32, + 0x8f, 0x60, 0x73, 0x21, 0x1d, 0x19, 0x50, 0x39, 0x27, 0x97, 0x99, 0xd9, 0x98, 0x5f, 0xa2, 0x1d, + 0xd0, 0xde, 0xb8, 0x61, 0x4a, 0xde, 0x91, 0x33, 0xce, 0x4e, 0x9f, 0xaa, 0x8f, 0x95, 0x6f, 0xab, + 0xab, 0x55, 0x43, 0xb3, 0x7e, 0x51, 0xa1, 0xf1, 0xa2, 0x6c, 0x1f, 0xba, 0x07, 0x6a, 0xe0, 0xcb, + 0x06, 0x6e, 0x4d, 0x27, 0xdb, 0x77, 0x64, 0x03, 0x1f, 0x94, 0x2d, 0x53, 0x03, 0x1f, 0x7d, 0x24, + 0x7b, 0xad, 0x0a, 0xaa, 0x31, 0x9d, 0x6c, 0xd7, 0x05, 0x35, 0x1d, 0x07, 0xaf, 0x53, 0xf2, 0x8e, + 0x7e, 0x57, 0xae, 0xf7, 0xfb, 0x64, 0xa1, 0x6b, 0x55, 0xe1, 0xda, 0x83, 0xa2, 0x80, 0xb9, 0x24, + 0x17, 0xdb, 0x77, 0x5b, 0xd6, 0x59, 0x7f, 0x54, 0x61, 0x63, 0x14, 0x5c, 0x44, 0x21, 0xe9, 0xcd, + 0x26, 0xe7, 0xf6, 0x8d, 0xfb, 0x1c, 0xb4, 0x38, 0x0d, 0x09, 0xf7, 0x4a, 0xe9, 0xea, 0xbb, 0x9d, + 0x22, 0xe3, 0x6b, 0xb9, 0xd9, 0x98, 0xf3, 0x70, 0x46, 0x37, 0x7f, 0xae, 0x80, 0x26, 0x00, 0xf4, + 0x09, 0x6c, 0x04, 0x63, 0x2f, 0x4c, 0x7d, 0xe2, 0x3b, 0x5e, 0x98, 0xb2, 0x84, 0xc4, 0xac, 0xa5, + 0x74, 0x2a, 0xdd, 0x1a, 0x36, 0xf2, 0x83, 0x7d, 0x89, 0xa3, 0x1f, 0xe0, 0x4e, 0x41, 0xe6, 0x19, + 0xb2, 0xc8, 0xf5, 0x08, 0xdf, 0x0e, 0xde, 0xa8, 0xfb, 0xff, 0xf6, 0x70, 0x7b, 0x98, 0x4b, 0x30, + 0xca, 0xc3, 0x14, 0x10, 0x43, 0xdf, 0xc1, 0x96, 0x4c, 0xc0, 0x11, 0xef, 0x1b, 0x87, 0x91, 0x90, + 0x78, 0x09, 0x8d, 0xf3, 0xfd, 0x69, 0xcf, 0x1e, 0x40, 0x92, 0x3d, 0x97, 0x11, 0xff, 0x90, 0xf3, + 0x46, 0x92, 0x86, 0x37, 0xa5, 0x7c, 0x0e, 0x65, 0xe8, 0x04, 0xee, 0x16, 0xb9, 0x5e, 0x8b, 0x5c, + 0xbd, 0x51, 0xe4, 0xad, 0x22, 0xc0, 0x7c, 0x6c, 0xf3, 0x18, 0x6a, 0x45, 0x05, 0xe8, 0x03, 0xa8, + 0xe7, 0x05, 0xcc, 0xde, 0x80, 0x58, 0x97, 0x18, 0xe7, 0xa1, 0x1d, 0x58, 0x9b, 0xe5, 0x32, 0x9b, + 0x00, 0xdc, 0x28, 0x50, 0x4e, 0xb3, 0x7e, 0xd5, 0xa0, 0xd9, 0x7f, 0xf5, 0x8a, 0x78, 0x49, 0xf0, + 0x66, 0x6e, 0xc0, 0x7a, 0xb0, 0x3a, 0xd7, 0x24, 0x7d, 0x77, 0xa7, 0x48, 0x7d, 0x91, 0xc0, 0x96, + 0xad, 0xc3, 0x85, 0xcc, 0x9c, 0x2a, 0xe5, 0x9c, 0xd7, 0x66, 0x13, 0x2b, 0x06, 0x13, 0x95, 0x07, + 0x53, 0x8e, 0xe1, 0x13, 0xd0, 0x58, 0xe2, 0x26, 0x44, 0x0c, 0xe0, 0x5a, 0xe9, 0x35, 0xb6, 0xf0, + 0x89, 0x23, 0x4e, 0xc5, 0x99, 0x02, 0x3d, 0x83, 0xe5, 0xec, 0xdb, 0x21, 0x8d, 0x7e, 0xf4, 0x7e, + 0x6d, 0x91, 0x97, 0x2d, 0x7c, 0x96, 0x3b, 0x2d, 0x43, 0x98, 0x4f, 0x40, 0x2f, 0xc1, 0x0b, 0xf6, + 0xb7, 0x59, 0xde, 0xdf, 0x5a, 0x69, 0x5d, 0xcd, 0xb7, 0x2a, 0xac, 0x48, 0x2b, 0xfe, 0xef, 0x92, + 0x07, 0x45, 0xc9, 0x9a, 0x28, 0xf9, 0xd3, 0x1b, 0x35, 0x68, 0x51, 0xc1, 0xe8, 0x1b, 0x80, 0xd2, + 0x96, 0x65, 0x0e, 0xde, 0xbb, 0xa1, 0x83, 0xb8, 0x24, 0xfd, 0x0f, 0xce, 0x59, 0x5f, 0x82, 0x26, + 0xca, 0x43, 0x3a, 0xac, 0x1c, 0x0f, 0x9f, 0x0d, 0x9f, 0xbf, 0x1c, 0x1a, 0x4b, 0xa8, 0x0e, 0xab, + 0x83, 0xe1, 0xfe, 0xe1, 0xf1, 0x41, 0xff, 0xc0, 0x50, 0xf8, 0x5d, 0xff, 0x7b, 0x79, 0xa7, 0x72, + 0xe2, 0x8b, 0x1e, 0x3e, 0x1a, 0xf4, 0x0e, 0x8d, 0xca, 0xfd, 0xaf, 0x60, 0x59, 0x7e, 0x19, 0x1b, + 0x50, 0x1b, 0x3e, 0x77, 0x7a, 0xfb, 0xfb, 0xfd, 0xd1, 0xc8, 0x58, 0x42, 0xeb, 0xa0, 0xe3, 0x7e, + 0xef, 0x20, 0x07, 0x14, 0xb4, 0x09, 0x1b, 0x02, 0x78, 0x89, 0x07, 0x47, 0xfd, 0x1c, 0x56, 0xf7, + 0x3e, 0xfb, 0xed, 0xaa, 0xad, 0xfc, 0x7e, 0xd5, 0x56, 0xfe, 0xbc, 0x6a, 0x2b, 0x3f, 0xfd, 0xd5, + 0x5e, 0x82, 0xbb, 0x01, 0xb5, 0x59, 0xe2, 0x7a, 0xe7, 0x31, 0xfd, 0x31, 0xfb, 0xf9, 0xc8, 0x2d, + 0x39, 0xc9, 0xff, 0x5c, 0x4e, 0x97, 0x05, 0xfe, 0xe8, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc3, + 0x59, 0x04, 0x59, 0xdf, 0x08, 0x00, 0x00, } func (m *Role) Marshal() (dAtA []byte, err error) { diff --git a/migrator/migrations/n_37_to_n_38_postgres_permission_sets/migration.go b/migrator/migrations/n_37_to_n_38_postgres_permission_sets/migration.go index 7741f99360160..d8cd008f70e46 100644 --- a/migrator/migrations/n_37_to_n_38_postgres_permission_sets/migration.go +++ b/migrator/migrations/n_37_to_n_38_postgres_permission_sets/migration.go @@ -1,21 +1,13 @@ -// Code generated by pg-bindings generator. DO NOT EDIT. package n37ton38 -import ( - "context" +// Code generation from pg-bindings generator disabled. To re-enable, check the gen.go file in +// central/role/store/permissionset/postgres - "github.com/jackc/pgx/v4/pgxpool" - "github.com/pkg/errors" +import ( "github.com/stackrox/rox/generated/storage" "github.com/stackrox/rox/migrator/migrations" - "github.com/stackrox/rox/migrator/migrations/loghelper" - legacy "github.com/stackrox/rox/migrator/migrations/n_37_to_n_38_postgres_permission_sets/legacy" - pgStore "github.com/stackrox/rox/migrator/migrations/n_37_to_n_38_postgres_permission_sets/postgres" "github.com/stackrox/rox/migrator/types" pkgMigrations "github.com/stackrox/rox/pkg/migrations" - pkgSchema "github.com/stackrox/rox/pkg/postgres/schema" - "github.com/stackrox/rox/pkg/sac" - "gorm.io/gorm" ) var ( @@ -23,54 +15,14 @@ var ( StartingSeqNum: pkgMigrations.CurrentDBVersionSeqNumWithoutPostgres() + 37, VersionAfter: &storage.Version{SeqNum: int32(pkgMigrations.CurrentDBVersionSeqNumWithoutPostgres()) + 38}, Run: func(databases *types.Databases) error { - legacyStore, err := legacy.New(databases.PkgRocksDB) - if err != nil { - return err - } - if err := move(databases.GormDB, databases.PostgresDB, legacyStore); err != nil { - return errors.Wrap(err, - "moving permission_sets from rocksdb to postgres") - } + // The data migration code was moved to the simpleaccessscope migrator. + // The goal is to be able to convert the IDs that do not parse as UUIDs to proper UUID values, + // and still be able to convert the references in the roles table. return nil }, } - batchSize = 10000 - schema = pkgSchema.PermissionSetsSchema - log = loghelper.LogWrapper{} ) -func move(gormDB *gorm.DB, postgresDB *pgxpool.Pool, legacyStore legacy.Store) error { - ctx := sac.WithAllAccess(context.Background()) - store := pgStore.New(postgresDB) - pkgSchema.ApplySchemaForTable(context.Background(), gormDB, schema.Table) - var permissionSets []*storage.PermissionSet - err := walk(ctx, legacyStore, func(obj *storage.PermissionSet) error { - permissionSets = append(permissionSets, obj) - if len(permissionSets) == batchSize { - if err := store.UpsertMany(ctx, permissionSets); err != nil { - log.WriteToStderrf("failed to persist permission_sets to store %v", err) - return err - } - permissionSets = permissionSets[:0] - } - return nil - }) - if err != nil { - return err - } - if len(permissionSets) > 0 { - if err = store.UpsertMany(ctx, permissionSets); err != nil { - log.WriteToStderrf("failed to persist permission_sets to store %v", err) - return err - } - } - return nil -} - -func walk(ctx context.Context, s legacy.Store, fn func(obj *storage.PermissionSet) error) error { - return s.Walk(ctx, fn) -} - func init() { migrations.MustRegisterMigration(migration) } diff --git a/migrator/migrations/n_37_to_n_38_postgres_permission_sets/migration_test.go b/migrator/migrations/n_37_to_n_38_postgres_permission_sets/migration_test.go index 4b37d50aaa5a5..79b04f6424c8e 100644 --- a/migrator/migrations/n_37_to_n_38_postgres_permission_sets/migration_test.go +++ b/migrator/migrations/n_37_to_n_38_postgres_permission_sets/migration_test.go @@ -1,22 +1,18 @@ -// Code generated by pg-bindings generator. DO NOT EDIT. - //go:build sql_integration package n37ton38 +// Code generation from pg-bindings generator disabled. To re-enable, check the gen.go file in +// central/role/store/permissionset/postgres + import ( "context" "testing" - "github.com/stackrox/rox/generated/storage" - legacy "github.com/stackrox/rox/migrator/migrations/n_37_to_n_38_postgres_permission_sets/legacy" - pgStore "github.com/stackrox/rox/migrator/migrations/n_37_to_n_38_postgres_permission_sets/postgres" pghelper "github.com/stackrox/rox/migrator/migrations/postgreshelper" - "github.com/stackrox/rox/pkg/env" "github.com/stackrox/rox/pkg/rocksdb" "github.com/stackrox/rox/pkg/sac" - "github.com/stackrox/rox/pkg/testutils" "github.com/stackrox/rox/pkg/testutils/rocksdbtest" "github.com/stretchr/testify/suite" ) @@ -56,33 +52,3 @@ func (s *postgresMigrationSuite) TearDownTest() { rocksdbtest.TearDownRocksDB(s.legacyDB) s.postgresDB.Teardown(s.T()) } - -func (s *postgresMigrationSuite) TestPermissionSetMigration() { - newStore := pgStore.New(s.postgresDB.Pool) - legacyStore, err := legacy.New(s.legacyDB) - s.NoError(err) - - // Prepare data and write to legacy DB - var permissionSets []*storage.PermissionSet - for i := 0; i < 200; i++ { - permissionSet := &storage.PermissionSet{} - s.NoError(testutils.FullInit(permissionSet, testutils.UniqueInitializer(), testutils.JSONFieldsFilter)) - permissionSets = append(permissionSets, permissionSet) - } - - s.NoError(legacyStore.UpsertMany(s.ctx, permissionSets)) - - // Move - s.NoError(move(s.postgresDB.GetGormDB(), s.postgresDB.Pool, legacyStore)) - - // Verify - count, err := newStore.Count(s.ctx) - s.NoError(err) - s.Equal(len(permissionSets), count) - for _, permissionSet := range permissionSets { - fetched, exists, err := newStore.Get(s.ctx, permissionSet.GetId()) - s.NoError(err) - s.True(exists) - s.Equal(permissionSet, fetched) - } -} diff --git a/migrator/migrations/n_46_to_n_47_postgres_roles/migration.go b/migrator/migrations/n_46_to_n_47_postgres_roles/migration.go index beacf38e5af9a..3fb86c7bbb5a8 100644 --- a/migrator/migrations/n_46_to_n_47_postgres_roles/migration.go +++ b/migrator/migrations/n_46_to_n_47_postgres_roles/migration.go @@ -1,20 +1,14 @@ -// Code generated by pg-bindings generator. DO NOT EDIT. package n46ton47 -import ( - "context" +// Code generation from pg-bindings generator disabled. To re-enable, check the gen.go file in +// central/role/store/role/postgres +import ( "github.com/jackc/pgx/v4/pgxpool" - "github.com/pkg/errors" "github.com/stackrox/rox/generated/storage" "github.com/stackrox/rox/migrator/migrations" - "github.com/stackrox/rox/migrator/migrations/loghelper" - legacy "github.com/stackrox/rox/migrator/migrations/n_46_to_n_47_postgres_roles/legacy" - pgStore "github.com/stackrox/rox/migrator/migrations/n_46_to_n_47_postgres_roles/postgres" "github.com/stackrox/rox/migrator/types" pkgMigrations "github.com/stackrox/rox/pkg/migrations" - pkgSchema "github.com/stackrox/rox/pkg/postgres/schema" - "github.com/stackrox/rox/pkg/sac" "gorm.io/gorm" ) @@ -23,54 +17,18 @@ var ( StartingSeqNum: pkgMigrations.CurrentDBVersionSeqNumWithoutPostgres() + 46, VersionAfter: &storage.Version{SeqNum: int32(pkgMigrations.CurrentDBVersionSeqNumWithoutPostgres()) + 47}, Run: func(databases *types.Databases) error { - legacyStore, err := legacy.New(databases.PkgRocksDB) - if err != nil { - return err - } - if err := move(databases.GormDB, databases.PostgresDB, legacyStore); err != nil { - return errors.Wrap(err, - "moving roles from rocksdb to postgres") - } + // The data migration code was moved to the simpleaccessscope migrator. + // The goal is to be able to convert the IDs that do not parse as UUIDs to proper UUID values, + // and still be able to convert the references in the roles table. return nil }, } - batchSize = 10000 - schema = pkgSchema.RolesSchema - log = loghelper.LogWrapper{} ) -func move(gormDB *gorm.DB, postgresDB *pgxpool.Pool, legacyStore legacy.Store) error { - ctx := sac.WithAllAccess(context.Background()) - store := pgStore.New(postgresDB) - pkgSchema.ApplySchemaForTable(context.Background(), gormDB, schema.Table) - var roles []*storage.Role - err := walk(ctx, legacyStore, func(obj *storage.Role) error { - roles = append(roles, obj) - if len(roles) == batchSize { - if err := store.UpsertMany(ctx, roles); err != nil { - log.WriteToStderrf("failed to persist roles to store %v", err) - return err - } - roles = roles[:0] - } - return nil - }) - if err != nil { - return err - } - if len(roles) > 0 { - if err = store.UpsertMany(ctx, roles); err != nil { - log.WriteToStderrf("failed to persist roles to store %v", err) - return err - } - } +func move(gormDB *gorm.DB, postgresDB *pgxpool.Pool) error { return nil } -func walk(ctx context.Context, s legacy.Store, fn func(obj *storage.Role) error) error { - return s.Walk(ctx, fn) -} - func init() { migrations.MustRegisterMigration(migration) } diff --git a/migrator/migrations/n_46_to_n_47_postgres_roles/migration_test.go b/migrator/migrations/n_46_to_n_47_postgres_roles/migration_test.go index aa2dc33f76d17..5f3e29412e544 100644 --- a/migrator/migrations/n_46_to_n_47_postgres_roles/migration_test.go +++ b/migrator/migrations/n_46_to_n_47_postgres_roles/migration_test.go @@ -1,22 +1,18 @@ -// Code generated by pg-bindings generator. DO NOT EDIT. - //go:build sql_integration package n46ton47 +// Code generation from pg-bindings generator disabled. To re-enable, check the gen.go file in +// central/role/store/role/postgres + import ( "context" "testing" - "github.com/stackrox/rox/generated/storage" - legacy "github.com/stackrox/rox/migrator/migrations/n_46_to_n_47_postgres_roles/legacy" - pgStore "github.com/stackrox/rox/migrator/migrations/n_46_to_n_47_postgres_roles/postgres" pghelper "github.com/stackrox/rox/migrator/migrations/postgreshelper" - "github.com/stackrox/rox/pkg/env" "github.com/stackrox/rox/pkg/rocksdb" "github.com/stackrox/rox/pkg/sac" - "github.com/stackrox/rox/pkg/testutils" "github.com/stackrox/rox/pkg/testutils/rocksdbtest" "github.com/stretchr/testify/suite" ) @@ -56,33 +52,3 @@ func (s *postgresMigrationSuite) TearDownTest() { rocksdbtest.TearDownRocksDB(s.legacyDB) s.postgresDB.Teardown(s.T()) } - -func (s *postgresMigrationSuite) TestRoleMigration() { - newStore := pgStore.New(s.postgresDB.Pool) - legacyStore, err := legacy.New(s.legacyDB) - s.NoError(err) - - // Prepare data and write to legacy DB - var roles []*storage.Role - for i := 0; i < 200; i++ { - role := &storage.Role{} - s.NoError(testutils.FullInit(role, testutils.UniqueInitializer(), testutils.JSONFieldsFilter)) - roles = append(roles, role) - } - - s.NoError(legacyStore.UpsertMany(s.ctx, roles)) - - // Move - s.NoError(move(s.postgresDB.GetGormDB(), s.postgresDB.Pool, legacyStore)) - - // Verify - count, err := newStore.Count(s.ctx) - s.NoError(err) - s.Equal(len(roles), count) - for _, role := range roles { - fetched, exists, err := newStore.Get(s.ctx, role.GetName()) - s.NoError(err) - s.True(exists) - s.Equal(role, fetched) - } -} diff --git a/migrator/migrations/n_37_to_n_38_postgres_permission_sets/legacy/rocksdb_plugin.go b/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacypermissionsets/rocksdb_plugin.go similarity index 91% rename from migrator/migrations/n_37_to_n_38_postgres_permission_sets/legacy/rocksdb_plugin.go rename to migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacypermissionsets/rocksdb_plugin.go index d7f8aee492bd7..dda3ce123619c 100644 --- a/migrator/migrations/n_37_to_n_38_postgres_permission_sets/legacy/rocksdb_plugin.go +++ b/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacypermissionsets/rocksdb_plugin.go @@ -1,5 +1,4 @@ -// Code generated by rocksdb-bindings generator. DO NOT EDIT. -package legacy +package legacypermissionsets import ( "context" @@ -15,6 +14,7 @@ var ( bucket = []byte("permission_sets") ) +// Store is the interface for interactions with the database storage type Store interface { UpsertMany(ctx context.Context, objs []*storage.PermissionSet) error Walk(ctx context.Context, fn func(obj *storage.PermissionSet) error) error @@ -38,7 +38,7 @@ func uniqKeyFunc(msg proto.Message) []byte { // New returns a new Store instance using the provided rocksdb instance. func New(db *rocksdb.RocksDB) (Store, error) { baseCRUD := generic.NewUniqueKeyCRUD(db, bucket, keyFunc, alloc, uniqKeyFunc, false) - return &storeImpl{crud: baseCRUD}, nil + return &storeImpl{crud: baseCRUD}, nil } // UpsertMany batches objects into the DB diff --git a/migrator/migrations/n_46_to_n_47_postgres_roles/legacy/rocksdb_plugin.go b/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacyroles/rocksdb_plugin.go similarity index 90% rename from migrator/migrations/n_46_to_n_47_postgres_roles/legacy/rocksdb_plugin.go rename to migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacyroles/rocksdb_plugin.go index 3869ac4ac64c5..a0ff58858eeae 100644 --- a/migrator/migrations/n_46_to_n_47_postgres_roles/legacy/rocksdb_plugin.go +++ b/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacyroles/rocksdb_plugin.go @@ -1,5 +1,4 @@ -// Code generated by rocksdb-bindings generator. DO NOT EDIT. -package legacy +package legacyroles import ( "context" @@ -15,6 +14,7 @@ var ( bucket = []byte("roles") ) +// Store is the interface for interactions with the database storage type Store interface { UpsertMany(ctx context.Context, objs []*storage.Role) error Walk(ctx context.Context, fn func(obj *storage.Role) error) error @@ -35,7 +35,7 @@ func keyFunc(msg proto.Message) []byte { // New returns a new Store instance using the provided rocksdb instance. func New(db *rocksdb.RocksDB) (Store, error) { baseCRUD := generic.NewCRUD(db, bucket, keyFunc, alloc, false) - return &storeImpl{crud: baseCRUD}, nil + return &storeImpl{crud: baseCRUD}, nil } // UpsertMany batches objects into the DB diff --git a/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacy/rocksdb_plugin.go b/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacysimpleaccessscopes/rocksdb_plugin.go similarity index 91% rename from migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacy/rocksdb_plugin.go rename to migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacysimpleaccessscopes/rocksdb_plugin.go index 99188dd513c86..c64bed3649599 100644 --- a/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacy/rocksdb_plugin.go +++ b/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacysimpleaccessscopes/rocksdb_plugin.go @@ -1,5 +1,4 @@ -// Code generated by rocksdb-bindings generator. DO NOT EDIT. -package legacy +package legacysimpleaccessscopes import ( "context" @@ -15,6 +14,7 @@ var ( bucket = []byte("simple_access_scopes") ) +// Store is the interface for interactions with the database storage type Store interface { UpsertMany(ctx context.Context, objs []*storage.SimpleAccessScope) error Walk(ctx context.Context, fn func(obj *storage.SimpleAccessScope) error) error @@ -38,7 +38,7 @@ func uniqKeyFunc(msg proto.Message) []byte { // New returns a new Store instance using the provided rocksdb instance. func New(db *rocksdb.RocksDB) (Store, error) { baseCRUD := generic.NewUniqueKeyCRUD(db, bucket, keyFunc, alloc, uniqKeyFunc, false) - return &storeImpl{crud: baseCRUD}, nil + return &storeImpl{crud: baseCRUD}, nil } // UpsertMany batches objects into the DB diff --git a/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/migration.go b/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/migration.go index 8dd8938ee1897..332ba16b4628d 100644 --- a/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/migration.go +++ b/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/migration.go @@ -1,50 +1,123 @@ -// Code generated by pg-bindings generator. DO NOT EDIT. package n52ton53 +// Code generation from pg-bindings generator disabled. To re-enable, check the gen.go file in +// central/role/store/permissionset/postgres +// central/role/store/role/postgres +// central/role/store/simpleaccessscope/postgres + import ( "context" + "strings" "github.com/jackc/pgx/v4/pgxpool" "github.com/pkg/errors" "github.com/stackrox/rox/generated/storage" "github.com/stackrox/rox/migrator/migrations" "github.com/stackrox/rox/migrator/migrations/loghelper" - legacy "github.com/stackrox/rox/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacy" - pgStore "github.com/stackrox/rox/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgres" + "github.com/stackrox/rox/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacypermissionsets" + "github.com/stackrox/rox/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacyroles" + "github.com/stackrox/rox/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacysimpleaccessscopes" + pgPermissionSetStore "github.com/stackrox/rox/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgrespermissionsets" + pgRoleStore "github.com/stackrox/rox/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgresroles" + pgSimpleAccessScopeStore "github.com/stackrox/rox/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgressimpleaccessscopes" "github.com/stackrox/rox/migrator/types" pkgMigrations "github.com/stackrox/rox/pkg/migrations" pkgSchema "github.com/stackrox/rox/pkg/postgres/schema" + rocksdb "github.com/stackrox/rox/pkg/rocksdb" "github.com/stackrox/rox/pkg/sac" + "github.com/stackrox/rox/pkg/uuid" "gorm.io/gorm" ) +const ( + accessScopeIDPrefix = "io.stackrox.authz.accessscope." + permissionSetIDPrefix = "io.stackrox.authz.permissionset." +) + var ( migration = types.Migration{ StartingSeqNum: pkgMigrations.CurrentDBVersionSeqNumWithoutPostgres() + 52, VersionAfter: &storage.Version{SeqNum: int32(pkgMigrations.CurrentDBVersionSeqNumWithoutPostgres()) + 53}, Run: func(databases *types.Databases) error { - legacyStore, err := legacy.New(databases.PkgRocksDB) - if err != nil { - return err - } - if err := move(databases.GormDB, databases.PostgresDB, legacyStore); err != nil { - return errors.Wrap(err, - "moving simple_access_scopes from rocksdb to postgres") - } - return nil + return migrateAll(databases.PkgRocksDB, databases.GormDB, databases.PostgresDB) }, } - batchSize = 10000 - schema = pkgSchema.SimpleAccessScopesSchema - log = loghelper.LogWrapper{} + batchSize = 1000 + permissionSetSchema = pkgSchema.PermissionSetsSchema + roleSchema = pkgSchema.RolesSchema + simpleAccessScopeSchema = pkgSchema.SimpleAccessScopesSchema + log = loghelper.LogWrapper{} + + accessScopeIDMapping = map[string]string{ + "denyall": "ffffffff-ffff-fff4-f5ff-fffffffffffe", + "unrestricted": "ffffffff-ffff-fff4-f5ff-ffffffffffff", + } + + permissionsetIDMapping = map[string]string{ + "admin": "ffffffff-ffff-fff4-f5ff-ffffffffffff", + "analyst": "ffffffff-ffff-fff4-f5ff-fffffffffffe", + "continuousintegration": "ffffffff-ffff-fff4-f5ff-fffffffffffd", + "none": "ffffffff-ffff-fff4-f5ff-fffffffffffc", + "scopemanager": "ffffffff-ffff-fff4-f5ff-fffffffffffb", + "sensorcreator": "ffffffff-ffff-fff4-f5ff-fffffffffffa", + "vulnmgmtapprover": "ffffffff-ffff-fff4-f5ff-fffffffffff9", + "vulnmgmtrequester": "ffffffff-ffff-fff4-f5ff-fffffffffff8", + "vulnreporter": "ffffffff-ffff-fff4-f5ff-fffffffffff7", + } ) -func move(gormDB *gorm.DB, postgresDB *pgxpool.Pool, legacyStore legacy.Store) error { +func migrateAll(rocksDatabase *rocksdb.RocksDB, gormDB *gorm.DB, postgresDB *pgxpool.Pool) error { + legacyAccessScopeStore, err := legacysimpleaccessscopes.New(rocksDatabase) + if err != nil { + return err + } + if err := migrateAccessScopes(gormDB, postgresDB, legacyAccessScopeStore); err != nil { + return errors.Wrap(err, + "moving simple_access_scopes from rocksdb to postgres") + } + legacyPermissionSetStore, err := legacypermissionsets.New(rocksDatabase) + if err != nil { + return err + } + if err := migratePermissionSets(gormDB, postgresDB, legacyPermissionSetStore); err != nil { + return errors.Wrap(err, + "moving permission_sets from rocksdb to postgres") + } + legacyRoleStore, err := legacyroles.New(rocksDatabase) + if err != nil { + return err + } + if err := migrateRoles(gormDB, postgresDB, legacyRoleStore); err != nil { + return errors.Wrap(err, + "moving roles from rocksdb to postgres") + } + return nil +} + +func convertAccessScopeID(accessScopeID string) string { + identifierSuffix := strings.TrimPrefix(accessScopeID, accessScopeIDPrefix) + replacement, found := accessScopeIDMapping[identifierSuffix] + if found { + return replacement + } + _, err := uuid.FromString(identifierSuffix) + if err != nil { + generatedID := uuid.NewV4().String() + accessScopeIDMapping[identifierSuffix] = generatedID + return generatedID + } + return identifierSuffix +} + +func migrateAccessScopes(gormDB *gorm.DB, postgresDB *pgxpool.Pool, legacyStore legacysimpleaccessscopes.Store) error { ctx := sac.WithAllAccess(context.Background()) - store := pgStore.New(postgresDB) - pkgSchema.ApplySchemaForTable(context.Background(), gormDB, schema.Table) + store := pgSimpleAccessScopeStore.New(postgresDB) + pkgSchema.ApplySchemaForTable(context.Background(), gormDB, simpleAccessScopeSchema.Table) + var simpleAccessScopes []*storage.SimpleAccessScope - err := walk(ctx, legacyStore, func(obj *storage.SimpleAccessScope) error { + err := walkAccessScopes(ctx, legacyStore, func(obj *storage.SimpleAccessScope) error { + accessScopeID := convertAccessScopeID(obj.GetId()) + obj.Id = accessScopeID simpleAccessScopes = append(simpleAccessScopes, obj) if len(simpleAccessScopes) == batchSize { if err := store.UpsertMany(ctx, simpleAccessScopes); err != nil { @@ -67,7 +140,126 @@ func move(gormDB *gorm.DB, postgresDB *pgxpool.Pool, legacyStore legacy.Store) e return nil } -func walk(ctx context.Context, s legacy.Store, fn func(obj *storage.SimpleAccessScope) error) error { +func convertPermissionSetID(permissionSetID string) string { + identifierSuffix := strings.TrimPrefix(permissionSetID, permissionSetIDPrefix) + replacement, found := permissionsetIDMapping[identifierSuffix] + if found { + return replacement + } + _, err := uuid.FromString(identifierSuffix) + if err != nil { + generatedID := uuid.NewV4().String() + permissionsetIDMapping[identifierSuffix] = generatedID + return generatedID + } + return identifierSuffix +} + +func migratePermissionSets(gormDB *gorm.DB, postgresDB *pgxpool.Pool, legacyStore legacypermissionsets.Store) error { + pkgSchema.ApplySchemaForTable(context.Background(), gormDB, permissionSetSchema.Table) + ctx := sac.WithAllAccess(context.Background()) + store := pgPermissionSetStore.New(postgresDB) + + var permissionSets []*storage.PermissionSet + err := walkPermissionSets(ctx, legacyStore, func(obj *storage.PermissionSet) error { + permissionSetID := convertPermissionSetID(obj.GetId()) + obj.Id = permissionSetID + permissionSets = append(permissionSets, obj) + if len(permissionSets) == batchSize { + if err := store.UpsertMany(ctx, permissionSets); err != nil { + log.WriteToStderrf("failed to persist permission_sets to store %v", err) + return err + } + permissionSets = permissionSets[:0] + } + return nil + }) + if err != nil { + return err + } + if len(permissionSets) > 0 { + if err = store.UpsertMany(ctx, permissionSets); err != nil { + log.WriteToStderrf("failed to persist permission_sets to store %v", err) + return err + } + } + return nil +} + +func getRoleAccessScopeID(role *storage.Role) (string, error) { + roleAccessScopeID := strings.TrimPrefix(role.GetAccessScopeId(), accessScopeIDPrefix) + if replacement, found := accessScopeIDMapping[roleAccessScopeID]; found { + roleAccessScopeID = replacement + } + _, accessIDParseErr := uuid.FromString(roleAccessScopeID) + if accessIDParseErr != nil { + log.WriteToStderrf("failed to convert role to postgres format, bad access scope ID. Role [%s], error %v", role.GetName(), accessIDParseErr) + return "", accessIDParseErr + } + return roleAccessScopeID, nil +} + +func getRolePermissionSetID(role *storage.Role) (string, error) { + rolePermissionSetID := strings.TrimPrefix(role.GetPermissionSetId(), permissionSetIDPrefix) + if replacement, found := permissionsetIDMapping[rolePermissionSetID]; found { + rolePermissionSetID = replacement + } + _, permissionSetIDParseErr := uuid.FromString(rolePermissionSetID) + if permissionSetIDParseErr != nil { + log.WriteToStderrf("failed to convert role to postgres format, bad permission set ID. Role [%s], error %v", role.GetName(), permissionSetIDParseErr) + return "", permissionSetIDParseErr + } + return rolePermissionSetID, nil +} + +func migrateRoles(gormDB *gorm.DB, postgresDB *pgxpool.Pool, legacyStore legacyroles.Store) error { + pkgSchema.ApplySchemaForTable(context.Background(), gormDB, roleSchema.Table) + ctx := sac.WithAllAccess(context.Background()) + store := pgRoleStore.New(postgresDB) + + var roles []*storage.Role + err := walkRoles(ctx, legacyStore, func(obj *storage.Role) error { + roleAccessScopeID, accessScopeConversionErr := getRoleAccessScopeID(obj) + if accessScopeConversionErr != nil { + return accessScopeConversionErr + } + obj.AccessScopeId = roleAccessScopeID + rolePermissionSetID, permissionSetConversionErr := getRolePermissionSetID(obj) + if permissionSetConversionErr != nil { + return permissionSetConversionErr + } + obj.PermissionSetId = rolePermissionSetID + roles = append(roles, obj) + if len(roles) == batchSize { + if err := store.UpsertMany(ctx, roles); err != nil { + log.WriteToStderrf("failed to persist roles to store %v", err) + return err + } + roles = roles[:0] + } + return nil + }) + if err != nil { + return err + } + if len(roles) > 0 { + if err = store.UpsertMany(ctx, roles); err != nil { + log.WriteToStderrf("failed to persist roles to store %v", err) + return err + } + } + return nil +} + +func walkAccessScopes(ctx context.Context, s legacysimpleaccessscopes.Store, fn func(obj *storage.SimpleAccessScope) error) error { + return s.Walk(ctx, fn) +} + +func walkPermissionSets(ctx context.Context, s legacypermissionsets.Store, fn func(obj *storage.PermissionSet) error) error { + return s.Walk(ctx, fn) +} + +func walkRoles(ctx context.Context, s legacyroles.Store, fn func(obj *storage.Role) error) error { return s.Walk(ctx, fn) } diff --git a/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/migration_test.go b/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/migration_test.go index 4860bf5a31bb1..dac3e5bced801 100644 --- a/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/migration_test.go +++ b/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/migration_test.go @@ -1,26 +1,71 @@ -// Code generated by pg-bindings generator. DO NOT EDIT. - //go:build sql_integration package n52ton53 +// Code generation from pg-bindings generator disabled. To re-enable, check the gen.go file in +// central/role/store/permissionset/postgres +// central/role/store/role/postgres +// central/role/store/simpleaccessscope/postgres + import ( "context" + "strings" "testing" "github.com/stackrox/rox/generated/storage" - legacy "github.com/stackrox/rox/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacy" - pgStore "github.com/stackrox/rox/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgres" + "github.com/stackrox/rox/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacypermissionsets" + "github.com/stackrox/rox/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacyroles" + "github.com/stackrox/rox/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/legacysimpleaccessscopes" + pgPermissionSetStore "github.com/stackrox/rox/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgrespermissionsets" + pgRoleStore "github.com/stackrox/rox/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgresroles" + pgSimpleAccessScopeStore "github.com/stackrox/rox/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgressimpleaccessscopes" pghelper "github.com/stackrox/rox/migrator/migrations/postgreshelper" - "github.com/stackrox/rox/pkg/env" "github.com/stackrox/rox/pkg/rocksdb" "github.com/stackrox/rox/pkg/sac" "github.com/stackrox/rox/pkg/testutils" "github.com/stackrox/rox/pkg/testutils/rocksdbtest" + "github.com/stackrox/rox/pkg/uuid" "github.com/stretchr/testify/suite" ) +const ( + datasetSize = 2500 + legacyBatchSize = 100 + + defaultDenyAllAccessScopeID = accessScopeIDPrefix + "denyall" + defaultDenyAllAccessScopeName = "Default DenyAll Access Scope" + defaultUnrestrictedAccessScopeID = accessScopeIDPrefix + "unrestricted" + defaultUnrestrictedAccessScopeName = "Default Unrestricted Access Scope" + prefixedNamedAccessScopeID = accessScopeIDPrefix + "prefixedAccessScopeID" + prefixedNamedAccessScopeName = "Prefixed Named Access Scope" + prefixedUUIDAccessScopeID = accessScopeIDPrefix + "47d9f01d-3def-4f0d-9777-916b5879aaf7" + prefixedUUIDAccessScopeName = "Prefixed UUID Access Scope" + prefixlessNamedAccessScopeID = "prefixlessAccessScopeID" + prefixlessNamedAccessScopeName = "Prefixless Named Access Scope" + prefixlessUUIDAccessScopeID = "07693a3d-ec29-4707-9ecf-e90fd0c2a338" + prefixlessUUIDAccessScopeName = "Prefixless UUID Access Scope" + + defaultAdminPermissionSetID = permissionSetIDPrefix + "admin" + defaultAdminPermissionSetName = "Default Admin Permission Set" + defaultAnalystPermissionSetID = permissionSetIDPrefix + "analyst" + defaultAnalystPermissionSetName = "Default Analyst Permission Set" + defaultNonePermissionSetID = permissionSetIDPrefix + "none" + defaultNonePermissionSetName = "Default None Permission Set" + prefixedNamedPermissionSetID = permissionSetIDPrefix + "prefixedPermissionSetID" + prefixedNamedPermissionSetName = "Prefixed Named Permission Set" + prefixedUUIDPermissionSetID = permissionSetIDPrefix + "b450b538-2abc-41ae-ae2e-938dc7af3689" + prefixedUUIDPermissionSetName = "Prefixed UUID Permission Set" + prefixlessNamedPermissionSetID = "prefixlessPermissionSetID" + prefixlessNamedPermissionSetName = "Prefixless Named Permission Set" + prefixlessUUIDPermissionSetID = "bc79bced-0fa5-45f6-9ae2-e054485ae6ff" + prefixlessUUIDPermissionSetName = "Prefixless UUID Permission Set" + + namePermission = "name" + uuidPermission = "uuid" + defaultPermission = "default" +) + func TestMigration(t *testing.T) { suite.Run(t, new(postgresMigrationSuite)) } @@ -58,22 +103,30 @@ func (s *postgresMigrationSuite) TearDownTest() { } func (s *postgresMigrationSuite) TestSimpleAccessScopeMigration() { - newStore := pgStore.New(s.postgresDB.Pool) - legacyStore, err := legacy.New(s.legacyDB) + newStore := pgSimpleAccessScopeStore.New(s.postgresDB.Pool) + legacyStore, err := legacysimpleaccessscopes.New(s.legacyDB) s.NoError(err) // Prepare data and write to legacy DB var simpleAccessScopes []*storage.SimpleAccessScope - for i := 0; i < 200; i++ { + var simpleAccessScopesBatch []*storage.SimpleAccessScope + batchID := 1 + for i := 0; i < datasetSize; i++ { simpleAccessScope := &storage.SimpleAccessScope{} s.NoError(testutils.FullInit(simpleAccessScope, testutils.UniqueInitializer(), testutils.JSONFieldsFilter)) simpleAccessScopes = append(simpleAccessScopes, simpleAccessScope) + simpleAccessScopesBatch = append(simpleAccessScopesBatch, simpleAccessScope) + if len(simpleAccessScopesBatch) >= legacyBatchSize { + s.NoError(legacyStore.UpsertMany(s.ctx, simpleAccessScopesBatch)) + simpleAccessScopesBatch = simpleAccessScopesBatch[:0] + batchID++ + } } - s.NoError(legacyStore.UpsertMany(s.ctx, simpleAccessScopes)) + s.NoError(legacyStore.UpsertMany(s.ctx, simpleAccessScopesBatch)) // Move - s.NoError(move(s.postgresDB.GetGormDB(), s.postgresDB.Pool, legacyStore)) + s.NoError(migrateAccessScopes(s.postgresDB.GetGormDB(), s.postgresDB.Pool, legacyStore)) // Verify count, err := newStore.Count(s.ctx) @@ -86,3 +139,574 @@ func (s *postgresMigrationSuite) TestSimpleAccessScopeMigration() { s.Equal(simpleAccessScope, fetched) } } + +func (s *postgresMigrationSuite) TestPermissionSetMigration() { + newStore := pgPermissionSetStore.New(s.postgresDB.Pool) + legacyStore, err := legacypermissionsets.New(s.legacyDB) + s.NoError(err) + + // Prepare data and write to legacy DB + var permissionSets []*storage.PermissionSet + var permissionSetsBatch []*storage.PermissionSet + batchID := 1 + for i := 0; i < datasetSize; i++ { + permissionSet := &storage.PermissionSet{} + s.NoError(testutils.FullInit(permissionSet, testutils.UniqueInitializer(), testutils.JSONFieldsFilter)) + permissionSets = append(permissionSets, permissionSet) + permissionSetsBatch = append(permissionSetsBatch, permissionSet) + if len(permissionSetsBatch) >= legacyBatchSize { + s.NoError(legacyStore.UpsertMany(s.ctx, permissionSetsBatch)) + permissionSetsBatch = permissionSetsBatch[:0] + batchID++ + } + } + + s.NoError(legacyStore.UpsertMany(s.ctx, permissionSetsBatch)) + + // Move + s.NoError(migratePermissionSets(s.postgresDB.GetGormDB(), s.postgresDB.Pool, legacyStore)) + + // Verify + count, err := newStore.Count(s.ctx) + s.NoError(err) + s.Equal(len(permissionSets), count) + for _, permissionSet := range permissionSets { + fetched, exists, err := newStore.Get(s.ctx, permissionSet.GetId()) + s.NoError(err) + s.True(exists) + s.Equal(permissionSet, fetched) + } +} + +func (s *postgresMigrationSuite) TestRoleMigration() { + newStore := pgRoleStore.New(s.postgresDB.Pool) + legacyStore, err := legacyroles.New(s.legacyDB) + s.NoError(err) + + // Prepare data and write to legacy DB + var roles []*storage.Role + for i := 0; i < datasetSize; i++ { + role := &storage.Role{} + s.NoError(testutils.FullInit(role, testutils.UniqueInitializer(), testutils.JSONFieldsFilter)) + roles = append(roles, role) + } + + s.NoError(legacyStore.UpsertMany(s.ctx, roles)) + + // Move + s.NoError(migrateRoles(s.postgresDB.GetGormDB(), s.postgresDB.Pool, legacyStore)) + + // Verify + count, err := newStore.Count(s.ctx) + s.NoError(err) + s.Equal(len(roles), count) + for _, role := range roles { + fetched, exists, err := newStore.Get(s.ctx, role.GetName()) + s.NoError(err) + s.True(exists) + s.Equal(role, fetched) + } +} + +func (s *postgresMigrationSuite) TestMigrateAll() { + newScopeStore := pgSimpleAccessScopeStore.New(s.postgresDB.Pool) + newPermissionStore := pgPermissionSetStore.New(s.postgresDB.Pool) + newRoleStore := pgRoleStore.New(s.postgresDB.Pool) + legacyScopeStore, scopeErr := legacysimpleaccessscopes.New(s.legacyDB) + s.NoError(scopeErr) + legacyPermissionStore, permissionSetErr := legacypermissionsets.New(s.legacyDB) + s.NoError(permissionSetErr) + legacyRoleStore, roleErr := legacyroles.New(s.legacyDB) + s.NoError(roleErr) + + // Prepare data and write to legacy DB + accessScopes := map[string]*storage.SimpleAccessScope{ + prefixedNamedAccessScopeName: { + Id: prefixedNamedAccessScopeID, + Name: prefixedNamedAccessScopeName, + Description: "Test access scope 1", + Rules: &storage.SimpleAccessScope_Rules{ + NamespaceLabelSelectors: []*storage.SetBasedLabelSelector{ + { + Requirements: []*storage.SetBasedLabelSelector_Requirement{ + { + Key: "k8s-app", + Op: storage.SetBasedLabelSelector_IN, + Values: []string{"kube-dns"}, + }, + }, + }, + }, + }, + }, + prefixlessNamedAccessScopeName: { + Id: prefixlessNamedAccessScopeID, + Name: prefixlessNamedAccessScopeName, + Description: "Test access scope 2", + Rules: &storage.SimpleAccessScope_Rules{ + NamespaceLabelSelectors: []*storage.SetBasedLabelSelector{ + { + Requirements: []*storage.SetBasedLabelSelector_Requirement{ + { + Key: "k8s-app", + Op: storage.SetBasedLabelSelector_NOT_IN, + Values: []string{"kube-dns"}, + }, + }, + }, + }, + }, + }, + defaultUnrestrictedAccessScopeName: { + Id: defaultUnrestrictedAccessScopeID, + Name: defaultUnrestrictedAccessScopeName, + Description: "Test access scope 3", + Rules: nil, + }, + defaultDenyAllAccessScopeName: { + Id: defaultDenyAllAccessScopeID, + Name: defaultDenyAllAccessScopeName, + Description: "Test access scope 4", + Rules: &storage.SimpleAccessScope_Rules{}, + }, + prefixedUUIDAccessScopeName: { + Id: prefixedUUIDAccessScopeID, + Name: prefixedUUIDAccessScopeName, + Description: "Test access scope 5", + Rules: &storage.SimpleAccessScope_Rules{ + IncludedClusters: []string{ + "3e86497c-1289-4752-9502-ae11b9f23027", + }, + }, + }, + prefixlessUUIDAccessScopeName: { + Id: prefixlessUUIDAccessScopeID, + Name: prefixlessUUIDAccessScopeName, + Description: "Test access scope 6", + Rules: &storage.SimpleAccessScope_Rules{ + IncludedNamespaces: []*storage.SimpleAccessScope_Rules_Namespace{ + { + ClusterName: "TestCluster", + NamespaceName: "TestNamespace", + }, + }, + }, + }, + } + accessScopeOldIDToNameMapping := make(map[string]string, len(accessScopes)) + accessScopeNameToNewIDMapping := make(map[string]string, len(accessScopes)) + scopesToInsert := make([]*storage.SimpleAccessScope, 0, len(accessScopes)) + for _, scope := range accessScopes { + accessScopeOldIDToNameMapping[scope.GetId()] = scope.GetName() + scopesToInsert = append(scopesToInsert, scope) + } + + permissionSets := map[string]*storage.PermissionSet{ + prefixedNamedPermissionSetName: { + Id: prefixedNamedPermissionSetID, + Name: prefixedNamedPermissionSetName, + Description: "Test permission set 1", + ResourceToAccess: map[string]storage.Access{ + namePermission: storage.Access_READ_WRITE_ACCESS, + }, + }, + prefixlessNamedPermissionSetName: { + Id: prefixlessNamedPermissionSetID, + Name: prefixlessNamedPermissionSetName, + Description: "Test permission set 2", + ResourceToAccess: map[string]storage.Access{ + namePermission: storage.Access_READ_ACCESS, + }, + }, + defaultAdminPermissionSetName: { + Id: defaultAdminPermissionSetID, + Name: defaultAdminPermissionSetName, + Description: "Test permission set 3", + ResourceToAccess: map[string]storage.Access{ + defaultPermission: storage.Access_READ_WRITE_ACCESS, + namePermission: storage.Access_READ_WRITE_ACCESS, + uuidPermission: storage.Access_READ_WRITE_ACCESS, + }, + }, + defaultAnalystPermissionSetName: { + Id: defaultAnalystPermissionSetID, + Name: defaultAnalystPermissionSetName, + Description: "Test permission set 4", + ResourceToAccess: map[string]storage.Access{ + defaultPermission: storage.Access_READ_ACCESS, + namePermission: storage.Access_READ_ACCESS, + uuidPermission: storage.Access_READ_ACCESS, + }, + }, + defaultNonePermissionSetName: { + Id: defaultNonePermissionSetID, + Name: defaultNonePermissionSetName, + Description: "Test permission set 5", + ResourceToAccess: nil, + }, + prefixedUUIDPermissionSetName: { + Id: prefixedUUIDPermissionSetID, + Name: prefixedUUIDPermissionSetName, + Description: "Test permission set 6", + ResourceToAccess: map[string]storage.Access{ + uuidPermission: storage.Access_READ_WRITE_ACCESS, + }, + }, + prefixlessUUIDPermissionSetName: { + Id: prefixlessUUIDPermissionSetID, + Name: prefixlessUUIDPermissionSetName, + Description: "Test permission set 7", + ResourceToAccess: map[string]storage.Access{ + uuidPermission: storage.Access_READ_ACCESS, + }, + }, + } + permissionSetOldIDToNameMapping := make(map[string]string, len(permissionSets)) + permissionSetNameToNewIDMapping := make(map[string]string, len(permissionSets)) + permissionSetsToInsert := make([]*storage.PermissionSet, 0, len(permissionSets)) + for _, permissionSet := range permissionSets { + permissionSetOldIDToNameMapping[permissionSet.GetId()] = permissionSet.GetName() + permissionSetsToInsert = append(permissionSetsToInsert, permissionSet) + } + + roles := []*storage.Role{ + { + Name: "R11", + Description: "", + PermissionSetId: prefixedNamedPermissionSetID, + AccessScopeId: prefixedNamedAccessScopeID, + }, + { + Name: "R12", + Description: "", + PermissionSetId: prefixedNamedPermissionSetID, + AccessScopeId: prefixlessNamedAccessScopeID, + }, + { + Name: "R13", + Description: "", + PermissionSetId: prefixedNamedPermissionSetID, + AccessScopeId: defaultDenyAllAccessScopeID, + }, + { + Name: "R14", + Description: "", + PermissionSetId: prefixedNamedPermissionSetID, + AccessScopeId: defaultUnrestrictedAccessScopeID, + }, + { + Name: "R15", + Description: "", + PermissionSetId: prefixedNamedPermissionSetID, + AccessScopeId: prefixedUUIDAccessScopeID, + }, + { + Name: "R16", + Description: "", + PermissionSetId: prefixedNamedPermissionSetID, + AccessScopeId: prefixlessUUIDAccessScopeID, + }, + { + Name: "R21", + Description: "", + PermissionSetId: prefixlessNamedPermissionSetID, + AccessScopeId: prefixedNamedAccessScopeID, + }, + { + Name: "R22", + Description: "", + PermissionSetId: prefixlessNamedPermissionSetID, + AccessScopeId: prefixlessNamedAccessScopeID, + }, + { + Name: "R23", + Description: "", + PermissionSetId: prefixlessNamedPermissionSetID, + AccessScopeId: defaultDenyAllAccessScopeID, + }, + { + Name: "R24", + Description: "", + PermissionSetId: prefixlessNamedPermissionSetID, + AccessScopeId: defaultUnrestrictedAccessScopeID, + }, + { + Name: "R25", + Description: "", + PermissionSetId: prefixlessNamedPermissionSetID, + AccessScopeId: prefixedUUIDAccessScopeID, + }, + { + Name: "R26", + Description: "", + PermissionSetId: prefixlessNamedPermissionSetID, + AccessScopeId: prefixlessUUIDAccessScopeID, + }, + { + Name: "R31", + Description: "", + PermissionSetId: defaultAdminPermissionSetID, + AccessScopeId: prefixedNamedAccessScopeID, + }, + { + Name: "R32", + Description: "", + PermissionSetId: defaultAdminPermissionSetID, + AccessScopeId: prefixlessNamedAccessScopeID, + }, + { + Name: "R33", + Description: "", + PermissionSetId: defaultAdminPermissionSetID, + AccessScopeId: defaultDenyAllAccessScopeID, + }, + { + Name: "R34", + Description: "", + PermissionSetId: defaultAdminPermissionSetID, + AccessScopeId: defaultUnrestrictedAccessScopeID, + }, + { + Name: "R35", + Description: "", + PermissionSetId: defaultAdminPermissionSetID, + AccessScopeId: prefixedUUIDAccessScopeID, + }, + { + Name: "R36", + Description: "", + PermissionSetId: defaultAdminPermissionSetID, + AccessScopeId: prefixlessUUIDAccessScopeID, + }, + { + Name: "R41", + Description: "", + PermissionSetId: defaultAnalystPermissionSetID, + AccessScopeId: prefixedNamedAccessScopeID, + }, + { + Name: "R42", + Description: "", + PermissionSetId: defaultAnalystPermissionSetID, + AccessScopeId: prefixlessNamedAccessScopeID, + }, + { + Name: "R43", + Description: "", + PermissionSetId: defaultAnalystPermissionSetID, + AccessScopeId: defaultDenyAllAccessScopeID, + }, + { + Name: "R44", + Description: "", + PermissionSetId: defaultAnalystPermissionSetID, + AccessScopeId: defaultUnrestrictedAccessScopeID, + }, + { + Name: "R45", + Description: "", + PermissionSetId: defaultAnalystPermissionSetID, + AccessScopeId: prefixedUUIDAccessScopeID, + }, + { + Name: "R46", + Description: "", + PermissionSetId: defaultAnalystPermissionSetID, + AccessScopeId: prefixlessUUIDAccessScopeID, + }, + { + Name: "R51", + Description: "", + PermissionSetId: defaultNonePermissionSetID, + AccessScopeId: prefixedNamedAccessScopeID, + }, + { + Name: "R52", + Description: "", + PermissionSetId: defaultNonePermissionSetID, + AccessScopeId: prefixlessNamedAccessScopeID, + }, + { + Name: "R53", + Description: "", + PermissionSetId: defaultNonePermissionSetID, + AccessScopeId: defaultDenyAllAccessScopeID, + }, + { + Name: "R54", + Description: "", + PermissionSetId: defaultNonePermissionSetID, + AccessScopeId: defaultUnrestrictedAccessScopeID, + }, + { + Name: "R55", + Description: "", + PermissionSetId: defaultNonePermissionSetID, + AccessScopeId: prefixedUUIDAccessScopeID, + }, + { + Name: "R56", + Description: "", + PermissionSetId: defaultNonePermissionSetID, + AccessScopeId: prefixlessUUIDAccessScopeID, + }, + { + Name: "R61", + Description: "", + PermissionSetId: prefixedUUIDPermissionSetID, + AccessScopeId: prefixedNamedAccessScopeID, + }, + { + Name: "R62", + Description: "", + PermissionSetId: prefixedUUIDPermissionSetID, + AccessScopeId: prefixlessNamedAccessScopeID, + }, + { + Name: "R63", + Description: "", + PermissionSetId: prefixedUUIDPermissionSetID, + AccessScopeId: defaultDenyAllAccessScopeID, + }, + { + Name: "R64", + Description: "", + PermissionSetId: prefixedUUIDPermissionSetID, + AccessScopeId: defaultUnrestrictedAccessScopeID, + }, + { + Name: "R65", + Description: "", + PermissionSetId: prefixedUUIDPermissionSetID, + AccessScopeId: prefixedUUIDAccessScopeID, + }, + { + Name: "R66", + Description: "", + PermissionSetId: prefixedUUIDPermissionSetID, + AccessScopeId: prefixlessUUIDAccessScopeID, + }, + { + Name: "R71", + Description: "", + PermissionSetId: prefixlessUUIDPermissionSetID, + AccessScopeId: prefixedNamedAccessScopeID, + }, + { + Name: "R72", + Description: "", + PermissionSetId: prefixlessUUIDPermissionSetID, + AccessScopeId: prefixlessNamedAccessScopeID, + }, + { + Name: "R73", + Description: "", + PermissionSetId: prefixlessUUIDPermissionSetID, + AccessScopeId: defaultDenyAllAccessScopeID, + }, + { + Name: "R74", + Description: "", + PermissionSetId: prefixlessUUIDPermissionSetID, + AccessScopeId: defaultUnrestrictedAccessScopeID, + }, + { + Name: "R75", + Description: "", + PermissionSetId: prefixlessUUIDPermissionSetID, + AccessScopeId: prefixedUUIDAccessScopeID, + }, + { + Name: "R76", + Description: "", + PermissionSetId: prefixlessUUIDPermissionSetID, + AccessScopeId: prefixlessUUIDAccessScopeID, + }, + } + + s.NoError(legacyScopeStore.UpsertMany(s.ctx, scopesToInsert)) + s.NoError(legacyPermissionStore.UpsertMany(s.ctx, permissionSetsToInsert)) + s.NoError(legacyRoleStore.UpsertMany(s.ctx, roles)) + + // Move + s.NoError(migrateAll(s.legacyDB, s.postgresDB.GetGormDB(), s.postgresDB.Pool)) + + // Verify + scopeCount, err := newScopeStore.Count(s.ctx) + s.NoError(err) + s.Equal(len(accessScopes), scopeCount) + newScopeIDs := make([]string, 0, len(accessScopes)) + scopeWalkErr := newScopeStore.Walk(s.ctx, func(obj *storage.SimpleAccessScope) error { + newScopeIDs = append(newScopeIDs, obj.GetId()) + return nil + }) + s.NoError(scopeWalkErr) + for _, scopeID := range newScopeIDs { + // Ensure the newly generated ID is a UUID + _, identifierParseErr := uuid.FromString(scopeID) + s.NoError(identifierParseErr) + // Check the migrated access scope matches the original one + fetched, exists, err := newScopeStore.Get(s.ctx, scopeID) + s.NoError(err) + s.True(exists) + if fetched != nil { + accessScopeNameToNewIDMapping[fetched.GetName()] = fetched.GetId() + } + if fetched.GetName() == prefixedUUIDAccessScopeName { + s.Equal(strings.TrimPrefix(prefixedUUIDAccessScopeID, accessScopeIDPrefix), scopeID) + } + if fetched.GetName() == prefixlessUUIDAccessScopeName { + s.Equal(prefixlessUUIDAccessScopeID, scopeID) + } + referenceScope := accessScopes[fetched.GetName()] + s.Equal(referenceScope.GetDescription(), fetched.GetDescription()) + s.Equal(referenceScope.GetRules(), fetched.GetRules()) + } + s.Equal(len(accessScopeOldIDToNameMapping), len(accessScopeNameToNewIDMapping)) + permissionSetCount, err := newPermissionStore.Count(s.ctx) + s.NoError(err) + s.Equal(len(permissionSets), permissionSetCount) + newPermissionSetIDs := make([]string, 0, len(permissionSets)) + permissionWalkErr := newPermissionStore.Walk(s.ctx, func(obj *storage.PermissionSet) error { + newPermissionSetIDs = append(newPermissionSetIDs, obj.GetId()) + return nil + }) + s.NoError(permissionWalkErr) + for _, permissionSetID := range newPermissionSetIDs { + // Check the new allocated ID is a UUID + _, identifierParseErr := uuid.FromString(permissionSetID) + s.NoError(identifierParseErr) + // Validate the retrieved permission set matches the initial one + fetched, exists, err := newPermissionStore.Get(s.ctx, permissionSetID) + s.NoError(err) + s.True(exists) + if fetched != nil { + permissionSetNameToNewIDMapping[fetched.GetName()] = fetched.GetId() + } + if fetched.GetName() == prefixedUUIDPermissionSetName { + s.Equal(strings.TrimPrefix(prefixedUUIDPermissionSetID, permissionSetIDPrefix), permissionSetID) + } + if fetched.GetName() == prefixlessUUIDPermissionSetName { + s.Equal(prefixlessUUIDPermissionSetID, permissionSetID) + } + referencePermissionSet := permissionSets[fetched.GetName()] + s.Equal(referencePermissionSet.GetDescription(), fetched.GetDescription()) + s.Equal(referencePermissionSet.GetResourceToAccess(), fetched.GetResourceToAccess()) + } + roleCount, err := newRoleStore.Count(s.ctx) + s.NoError(err) + s.Equal(len(roles), roleCount) + for _, role := range roles { + fetched, exists, err := newRoleStore.Get(s.ctx, role.GetName()) + s.NoError(err) + s.True(exists) + expectedRole := role.Clone() + // Map role permission set ID to new ID + permissionSetName := permissionSetOldIDToNameMapping[role.GetPermissionSetId()] + expectedRole.PermissionSetId = permissionSetNameToNewIDMapping[permissionSetName] + // Map role access scope ID to new ID + accessScopeName := accessScopeOldIDToNameMapping[role.GetAccessScopeId()] + expectedRole.AccessScopeId = accessScopeNameToNewIDMapping[accessScopeName] + s.Equal(expectedRole, fetched) + } +} diff --git a/migrator/migrations/n_37_to_n_38_postgres_permission_sets/postgres/postgres_plugin.go b/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgrespermissionsets/postgres_plugin.go similarity index 95% rename from migrator/migrations/n_37_to_n_38_postgres_permission_sets/postgres/postgres_plugin.go rename to migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgrespermissionsets/postgres_plugin.go index 4e8165c7fa8b6..63cefdea1f445 100644 --- a/migrator/migrations/n_37_to_n_38_postgres_permission_sets/postgres/postgres_plugin.go +++ b/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgrespermissionsets/postgres_plugin.go @@ -1,6 +1,4 @@ -// Code generated by pg-bindings generator. DO NOT EDIT. - -package postgres +package postgrespermissionsets import ( "context" @@ -18,6 +16,7 @@ import ( "github.com/stackrox/rox/pkg/search" "github.com/stackrox/rox/pkg/search/postgres" "github.com/stackrox/rox/pkg/sync" + "github.com/stackrox/rox/pkg/utils" "gorm.io/gorm" ) @@ -40,6 +39,7 @@ var ( schema = pkgSchema.PermissionSetsSchema ) +// Store is the interface for interactions with the database storage type Store interface { Count(ctx context.Context) (int, error) Exists(ctx context.Context, id string) (bool, error) @@ -79,10 +79,14 @@ func insertIntoPermissionSets(ctx context.Context, batch *pgx.Batch, obj *storag values := []interface{}{ // parent primary keys start - obj.GetId(), + pgutils.NilOrUUID(obj.GetId()), obj.GetName(), serialized, } + if pgutils.NilOrUUID(obj.GetId()) == nil { + utils.Should(errors.Errorf("Id is not a valid uuid -- %v", obj)) + return nil + } finalStr := "INSERT INTO permission_sets (Id, Name, serialized) VALUES($1, $2, $3) ON CONFLICT(Id) DO UPDATE SET Id = EXCLUDED.Id, Name = EXCLUDED.Name, serialized = EXCLUDED.serialized" batch.Queue(finalStr, values...) @@ -120,12 +124,16 @@ func (s *storeImpl) copyFromPermissionSets(ctx context.Context, tx pgx.Tx, objs inputRows = append(inputRows, []interface{}{ - obj.GetId(), + pgutils.NilOrUUID(obj.GetId()), obj.GetName(), serialized, }) + if pgutils.NilOrUUID(obj.GetId()) == nil { + utils.Should(errors.Errorf("Id is not a valid uuid -- %v", obj)) + continue + } // Add the id to be deleted. deletes = append(deletes, obj.GetId()) @@ -225,9 +233,8 @@ func (s *storeImpl) UpsertMany(ctx context.Context, objs []*storage.PermissionSe if len(objs) < batchAfter { return s.upsert(ctx, objs...) - } else { - return s.copyFrom(ctx, objs...) } + return s.copyFrom(ctx, objs...) }) } @@ -433,6 +440,7 @@ func dropTablePermissionSets(ctx context.Context, db *pgxpool.Pool) { } +// Destroy removes the access scope storage from the database func Destroy(ctx context.Context, db *pgxpool.Pool) { dropTablePermissionSets(ctx, db) } diff --git a/migrator/migrations/n_46_to_n_47_postgres_roles/postgres/postgres_plugin.go b/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgresroles/postgres_plugin.go similarity index 98% rename from migrator/migrations/n_46_to_n_47_postgres_roles/postgres/postgres_plugin.go rename to migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgresroles/postgres_plugin.go index dd370716dc756..bf174523e8d63 100644 --- a/migrator/migrations/n_46_to_n_47_postgres_roles/postgres/postgres_plugin.go +++ b/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgresroles/postgres_plugin.go @@ -1,6 +1,4 @@ -// Code generated by pg-bindings generator. DO NOT EDIT. - -package postgres +package postgresroles import ( "context" @@ -40,6 +38,7 @@ var ( schema = pkgSchema.RolesSchema ) +// Store is the interface for interactions with the database storage type Store interface { Count(ctx context.Context) (int, error) Exists(ctx context.Context, name string) (bool, error) @@ -220,9 +219,8 @@ func (s *storeImpl) UpsertMany(ctx context.Context, objs []*storage.Role) error if len(objs) < batchAfter { return s.upsert(ctx, objs...) - } else { - return s.copyFrom(ctx, objs...) } + return s.copyFrom(ctx, objs...) }) } @@ -428,6 +426,7 @@ func dropTableRoles(ctx context.Context, db *pgxpool.Pool) { } +// Destroy removes the access scope storage from the database func Destroy(ctx context.Context, db *pgxpool.Pool) { dropTableRoles(ctx, db) } diff --git a/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgres/postgres_plugin.go b/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgressimpleaccessscopes/postgres_plugin.go similarity index 95% rename from migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgres/postgres_plugin.go rename to migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgressimpleaccessscopes/postgres_plugin.go index 67365a2068d57..91982fe040dac 100644 --- a/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgres/postgres_plugin.go +++ b/migrator/migrations/n_52_to_n_53_postgres_simple_access_scopes/postgressimpleaccessscopes/postgres_plugin.go @@ -1,6 +1,4 @@ -// Code generated by pg-bindings generator. DO NOT EDIT. - -package postgres +package postgressimpleaccessscopes import ( "context" @@ -18,6 +16,7 @@ import ( "github.com/stackrox/rox/pkg/search" "github.com/stackrox/rox/pkg/search/postgres" "github.com/stackrox/rox/pkg/sync" + "github.com/stackrox/rox/pkg/utils" "gorm.io/gorm" ) @@ -40,6 +39,7 @@ var ( schema = pkgSchema.SimpleAccessScopesSchema ) +// Store is the interface for interactions with the database storage type Store interface { Count(ctx context.Context) (int, error) Exists(ctx context.Context, id string) (bool, error) @@ -79,10 +79,14 @@ func insertIntoSimpleAccessScopes(ctx context.Context, batch *pgx.Batch, obj *st values := []interface{}{ // parent primary keys start - obj.GetId(), + pgutils.NilOrUUID(obj.GetId()), obj.GetName(), serialized, } + if pgutils.NilOrUUID(obj.GetId()) == nil { + utils.Should(errors.Errorf("Id is not a valid uuid -- %v", obj)) + return nil + } finalStr := "INSERT INTO simple_access_scopes (Id, Name, serialized) VALUES($1, $2, $3) ON CONFLICT(Id) DO UPDATE SET Id = EXCLUDED.Id, Name = EXCLUDED.Name, serialized = EXCLUDED.serialized" batch.Queue(finalStr, values...) @@ -120,12 +124,16 @@ func (s *storeImpl) copyFromSimpleAccessScopes(ctx context.Context, tx pgx.Tx, o inputRows = append(inputRows, []interface{}{ - obj.GetId(), + pgutils.NilOrUUID(obj.GetId()), obj.GetName(), serialized, }) + if pgutils.NilOrUUID(obj.GetId()) == nil { + utils.Should(errors.Errorf("Id is not a valid uuid -- %v", obj)) + continue + } // Add the id to be deleted. deletes = append(deletes, obj.GetId()) @@ -225,9 +233,8 @@ func (s *storeImpl) UpsertMany(ctx context.Context, objs []*storage.SimpleAccess if len(objs) < batchAfter { return s.upsert(ctx, objs...) - } else { - return s.copyFrom(ctx, objs...) } + return s.copyFrom(ctx, objs...) }) } @@ -433,6 +440,7 @@ func dropTableSimpleAccessScopes(ctx context.Context, db *pgxpool.Pool) { } +// Destroy removes the access scope storage from the database func Destroy(ctx context.Context, db *pgxpool.Pool) { dropTableSimpleAccessScopes(ctx, db) } diff --git a/pkg/postgres/schema/permission_sets.go b/pkg/postgres/schema/permission_sets.go index 444fd4dcb0631..ee9f08c7cde54 100644 --- a/pkg/postgres/schema/permission_sets.go +++ b/pkg/postgres/schema/permission_sets.go @@ -35,7 +35,7 @@ const ( // PermissionSets holds the Gorm model for Postgres table `permission_sets`. type PermissionSets struct { - Id string `gorm:"column:id;type:varchar;primaryKey"` + Id string `gorm:"column:id;type:uuid;primaryKey"` Name string `gorm:"column:name;type:varchar;unique"` Serialized []byte `gorm:"column:serialized;type:bytea"` } diff --git a/pkg/postgres/schema/simple_access_scopes.go b/pkg/postgres/schema/simple_access_scopes.go index 3eec9975a30eb..f51dacb5c3fda 100644 --- a/pkg/postgres/schema/simple_access_scopes.go +++ b/pkg/postgres/schema/simple_access_scopes.go @@ -35,7 +35,7 @@ const ( // SimpleAccessScopes holds the Gorm model for Postgres table `simple_access_scopes`. type SimpleAccessScopes struct { - Id string `gorm:"column:id;type:varchar;primaryKey"` + Id string `gorm:"column:id;type:uuid;primaryKey"` Name string `gorm:"column:name;type:varchar;unique"` Serialized []byte `gorm:"column:serialized;type:bytea"` } diff --git a/proto/storage/role.proto b/proto/storage/role.proto index 0af7a713154e3..c48d0c9a2a0f8 100644 --- a/proto/storage/role.proto +++ b/proto/storage/role.proto @@ -20,8 +20,8 @@ message Role { string description = 5; // The associated PermissionSet and AccessScope for this Role. - string permission_set_id = 6; - string access_scope_id = 7; + string permission_set_id = 6 [(gogoproto.moretags) = 'sql:"type(uuid)"']; + string access_scope_id = 7 [(gogoproto.moretags) = 'sql:"type(uuid)"']; // Minimum (not default!) access level for every resource. Can be extended // below by explicit permissions but not shrunk. @@ -42,7 +42,7 @@ enum Access { // This encodes a set of permissions for StackRox resources. message PermissionSet { // id is generated and cannot be changed. - string id = 1 [(gogoproto.moretags) = 'sql:"pk"']; + string id = 1 [(gogoproto.moretags) = 'sql:"pk,type(uuid)"']; // `name` and `description` are provided by the user and can be changed. string name = 2 [(gogoproto.moretags) = 'sql:"unique"']; @@ -72,7 +72,7 @@ message SimpleAccessScope { } // `id` is generated and cannot be changed. - string id = 1 [(gogoproto.moretags) = 'sql:"pk"']; + string id = 1 [(gogoproto.moretags) = 'sql:"pk,type(uuid)"']; // `name` and `description` are provided by the user and can be changed. string name = 2 [(gogoproto.moretags) = 'sql:"unique"']; diff --git a/qa-tests-backend/src/test/groovy/BaseSpecification.groovy b/qa-tests-backend/src/test/groovy/BaseSpecification.groovy index e17770182cdd4..4c29328e66b70 100644 --- a/qa-tests-backend/src/test/groovy/BaseSpecification.groovy +++ b/qa-tests-backend/src/test/groovy/BaseSpecification.groovy @@ -43,7 +43,9 @@ class BaseSpecification extends Specification { static final String RUN_ID - public static final String UNRESTRICTED_SCOPE_ID = "io.stackrox.authz.accessscope.unrestricted" + public static final String UNRESTRICTED_SCOPE_ID = isPostgresRun() ? + "ffffffff-ffff-fff4-f5ff-ffffffffffff" : + "io.stackrox.authz.accessscope.unrestricted" static { String idStr diff --git a/qa-tests-backend/src/test/groovy/SACTest.groovy b/qa-tests-backend/src/test/groovy/SACTest.groovy index 0cef58bc93ce0..8af952974d5bf 100644 --- a/qa-tests-backend/src/test/groovy/SACTest.groovy +++ b/qa-tests-backend/src/test/groovy/SACTest.groovy @@ -74,7 +74,9 @@ class SACTest extends BaseSpecification { static final private Integer WAIT_FOR_RISK_RETRIES = isRaceBuild() ? 300 : ((Env.mustGetOrchestratorType() == OrchestratorTypes.OPENSHIFT) ? 80 : 50) - static final private String DENY_ALL = 'io.stackrox.authz.accessscope.denyall' + static final private String DENY_ALL = isPostgresRun() ? + "ffffffff-ffff-fff4-f5ff-fffffffffffe" : + 'io.stackrox.authz.accessscope.denyall' @Shared private Map allResourcesAccess diff --git a/ui/apps/platform/cypress/integration/accessControl/accessControlPermissionSets.test.js b/ui/apps/platform/cypress/integration/accessControl/accessControlPermissionSets.test.js index 3133b35d8f8d2..ebfaaffaa9a87 100644 --- a/ui/apps/platform/cypress/integration/accessControl/accessControlPermissionSets.test.js +++ b/ui/apps/platform/cypress/integration/accessControl/accessControlPermissionSets.test.js @@ -6,6 +6,7 @@ import { import withAuth from '../../helpers/basicAuth'; import { getRegExpForTitleWithBranding } from '../../helpers/title'; +import { hasFeatureFlag } from '../../helpers/features'; const h1 = 'Access Control'; const h2 = 'Permission sets'; @@ -102,7 +103,14 @@ describe('Access Control Permission sets', () => { }); it('direct link to default Admin has all read and write access', () => { - visitPermissionSet('io.stackrox.authz.permissionset.admin'); + /* + * TODO: ROX-13585 - remove the pre-postgres constants once the migration to postgres + * is completed and the support for BoltDB, RocksDB and Bleve is dropped. + */ + const targetID = hasFeatureFlag('ROX_POSTGRES_DATASTORE') + ? 'ffffffff-ffff-fff4-f5ff-ffffffffffff' + : 'io.stackrox.authz.permissionset.admin'; + visitPermissionSet(targetID); cy.get(selectors.form.inputName).should('have.value', 'Admin'); @@ -141,7 +149,14 @@ describe('Access Control Permission sets', () => { // TODO: ROX-12750 Rename DebugLogs to Administration it('direct link to default Analyst has all (but DebugLogs) read and no write access', () => { - visitPermissionSet('io.stackrox.authz.permissionset.analyst'); + /* + * TODO: ROX-13585 - remove the pre-postgres constants once the migration to postgres + * is completed and the support for BoltDB, RocksDB and Bleve is dropped. + */ + const targetID = hasFeatureFlag('ROX_POSTGRES_DATASTORE') + ? 'ffffffff-ffff-fff4-f5ff-fffffffffffe' + : 'io.stackrox.authz.permissionset.analyst'; + visitPermissionSet(targetID); cy.get(selectors.form.inputName).should('have.value', 'Analyst'); @@ -192,7 +207,14 @@ describe('Access Control Permission sets', () => { }); it('direct link to default Continuous Integration has limited read and write accesss', () => { - visitPermissionSet('io.stackrox.authz.permissionset.continuousintegration'); + /* + * TODO: ROX-13585 - remove the pre-postgres constants once the migration to postgres + * is completed and the support for BoltDB, RocksDB and Bleve is dropped. + */ + const targetID = hasFeatureFlag('ROX_POSTGRES_DATASTORE') + ? 'ffffffff-ffff-fff4-f5ff-fffffffffffd' + : 'io.stackrox.authz.permissionset.continuousintegration'; + visitPermissionSet(targetID); cy.get(selectors.form.inputName).should('have.value', 'Continuous Integration'); @@ -262,7 +284,14 @@ describe('Access Control Permission sets', () => { }); it('direct link to default None has no read nor write access', () => { - visitPermissionSet('io.stackrox.authz.permissionset.none'); + /* + * TODO: ROX-13585 - remove the pre-postgres constants once the migration to postgres + * is completed and the support for BoltDB, RocksDB and Bleve is dropped. + */ + const targetID = hasFeatureFlag('ROX_POSTGRES_DATASTORE') + ? 'ffffffff-ffff-fff4-f5ff-fffffffffffc' + : 'io.stackrox.authz.permissionset.none'; + visitPermissionSet(targetID); cy.get(selectors.form.inputName).should('have.value', 'None'); @@ -297,7 +326,14 @@ describe('Access Control Permission sets', () => { }); it('direct link to default Sensor Creator has limited read and write access', () => { - visitPermissionSet('io.stackrox.authz.permissionset.sensorcreator'); + /* + * TODO: ROX-13585 - remove the pre-postgres constants once the migration to postgres + * is completed and the support for BoltDB, RocksDB and Bleve is dropped. + */ + const targetID = hasFeatureFlag('ROX_POSTGRES_DATASTORE') + ? 'ffffffff-ffff-fff4-f5ff-fffffffffffa' + : 'io.stackrox.authz.permissionset.sensorcreator'; + visitPermissionSet(targetID); cy.get(selectors.form.inputName).should('have.value', 'Sensor Creator'); diff --git a/ui/apps/platform/src/Containers/AccessControl/AccessScopes/AccessScopeForm.tsx b/ui/apps/platform/src/Containers/AccessControl/AccessScopes/AccessScopeForm.tsx index 15c1fb78452f7..b1277ad8ab353 100644 --- a/ui/apps/platform/src/Containers/AccessControl/AccessScopes/AccessScopeForm.tsx +++ b/ui/apps/platform/src/Containers/AccessControl/AccessScopes/AccessScopeForm.tsx @@ -18,7 +18,7 @@ import { LabelSelector, LabelSelectorsKey, computeEffectiveAccessScopeClusters, - defaultAccessScopeIds, + getIsUnrestrictedAccessScopeId, } from 'services/AccessScopesService'; import { @@ -85,9 +85,9 @@ function AccessScopeForm({ hasAction, alertSubmit, formik }: AccessScopeFormProp * before its first requirement or value has been added. */ const isValidRules = - values.id !== defaultAccessScopeIds.Unrestricted && getIsValidRules(values.rules); + !getIsUnrestrictedAccessScopeId(values.id) && getIsValidRules(values.rules); useEffect(() => { - if (values.id === defaultAccessScopeIds.Unrestricted) { + if (getIsUnrestrictedAccessScopeId(values.id)) { return; } setCounterComputing((counterPrev) => counterPrev + 1); @@ -195,7 +195,7 @@ function AccessScopeForm({ hasAction, alertSubmit, formik }: AccessScopeFormProp /> {alertCompute} - {values.id !== defaultAccessScopeIds.Unrestricted && ( + {!getIsUnrestrictedAccessScopeId(values.id) && ( ([]); const [alertAccessScopes, setAlertAccessScopes] = useState(null); + const { isFeatureFlagEnabled } = useFeatureFlags(); + + function getDefaultAccessScopeID() { + if (isFeatureFlagEnabled('ROX_POSTGRES_DATASTORE')) { + return defaultAccessScopeIds.UnrestrictedPostgres; + } + return defaultAccessScopeIds.Unrestricted; + } + + const roleNew: Role = { + name: '', + resourceToAccess: {}, + description: '', + permissionSetId: '', + accessScopeId: getDefaultAccessScopeID(), + }; + useEffect(() => { // The primary request has unclosable alert. setCounterFetching((counterPrev) => counterPrev + 1); diff --git a/ui/apps/platform/src/services/AccessScopesService.ts b/ui/apps/platform/src/services/AccessScopesService.ts index 39cc4a71aefc5..4a8773b755715 100644 --- a/ui/apps/platform/src/services/AccessScopesService.ts +++ b/ui/apps/platform/src/services/AccessScopesService.ts @@ -3,15 +3,28 @@ import { Empty } from './types'; const accessScopessUrl = '/v1/simpleaccessscopes'; +/* + * TODO: ROX-13585 - remove the pre-postgres constants once the migration to postgres + * is completed and the support for BoltDB, RocksDB and Bleve is dropped. + */ export const defaultAccessScopeIds = { Unrestricted: 'io.stackrox.authz.accessscope.unrestricted', + UnrestrictedPostgres: 'ffffffff-ffff-fff4-f5ff-ffffffffffff', DenyAll: 'io.stackrox.authz.accessscope.denyall', + DenyAllPostgres: 'ffffffff-ffff-fff4-f5ff-fffffffffffe', }; export function getIsDefaultAccessScopeId(id: string): boolean { return Object.values(defaultAccessScopeIds).includes(id); } +export function getIsUnrestrictedAccessScopeId(id: string): boolean { + return ( + id === defaultAccessScopeIds.Unrestricted || + id === defaultAccessScopeIds.UnrestrictedPostgres + ); +} + export type SimpleAccessScopeNamespace = { clusterName: string; namespaceName: string;