Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion db/seed/RbacGroup.csv
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
Id;CreatedAt;UpdatedAt;Name;Description
91E26750-E58E-43F6-AB8E-EBA2C8EC7019;2000-01-01;2000-01-01;ce - users;Members of Cloud Engineering
BA0AA734-206D-454E-AC95-14855B6901E4;2026-07-23T09:15:35.803168;2026-07-23T09:15:35.803174;CloudEngineers;Group: CloudEngineers
899F8F9E-3F7E-4EF3-A2CD-2E1DDA78E40A;2026-07-23T09:15:35.803179;2026-07-23T09:15:35.803180;BatchCapabilityCreators;Group: BatchCapabilityCreators
7D3D7498-9075-4D1B-B6C1-AF6E95788C3B;2026-07-23T09:15:35.803184;2026-07-23T09:15:35.803185;ServiceCatalogueReaders;Group: ServiceCatalogueReaders
3 changes: 2 additions & 1 deletion db/seed/RbacGroupMember.csv
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
Id;GroupId;UserId;CreatedAt
72C7137D-6EA9-48E7-B505-66D068D272D9;91E26750-E58E-43F6-AB8E-EBA2C8EC7019;emcla@dfds.com;2000-01-01
7BADF960-B926-4BDC-A4BF-8B0CB444E292;BA0AA734-206D-454E-AC95-14855B6901E4;andfris@dfds.com;2026-07-23T09:15:35.803265
DEF609DD-40B7-4DEC-A430-0208C49555DB;BA0AA734-206D-454E-AC95-14855B6901E4;emcla@dfds.com;2026-07-23T09:15:35.803272
221 changes: 141 additions & 80 deletions db/seed/RbacPermissionGrants.csv

Large diffs are not rendered by default.

11 changes: 7 additions & 4 deletions db/seed/RbacRole.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
Id;OwnerId;CreatedAt;UpdatedAt;Name;Description;Type
36202DFB-D106-440D-8B99-F11BC8D77C9C;0000DFD5-0000-0000-0000-00000000000A;2025-11-04T08:45:52.056886;2025-11-04T08:45:52.056909;Owner;Full access to all resources;Global
2C561A6D-90F4-4649-80B3-76A854A64EA2;0000DFD5-0000-0000-0000-00000000000A;2025-11-04T08:45:52.056913;2025-11-04T08:45:52.056914;Contributor;Can modify existing resources;Global
22DAB91B-C2D8-4840-A173-1416EF1B882D;0000DFD5-0000-0000-0000-00000000000A;2025-11-04T08:45:52.056917;2025-11-04T08:45:52.056917;Reader;Read-only access;Global
F67CACC9-8DD4-4481-AC15-00B5DD83B046;0000DFD5-0000-0000-0000-00000000000A;2025-11-04T08:45:52.056920;2025-11-04T08:45:52.056921;Guest;Very limited access;Global
36202DFB-D106-440D-8B99-F11BC8D77C9C;0000DFD5-0000-0000-0000-00000000000A;2026-07-23T09:15:35.801873;2026-07-23T09:15:35.801901;Owner;Role: Owner;Global
2C561A6D-90F4-4649-80B3-76A854A64EA2;0000DFD5-0000-0000-0000-00000000000A;2026-07-23T09:15:35.801908;2026-07-23T09:15:35.801909;Contributor;Role: Contributor;Global
22DAB91B-C2D8-4840-A173-1416EF1B882D;0000DFD5-0000-0000-0000-00000000000A;2026-07-23T09:15:35.801913;2026-07-23T09:15:35.801914;Reader;Role: Reader;Global
F67CACC9-8DD4-4481-AC15-00B5DD83B046;0000DFD5-0000-0000-0000-00000000000A;2026-07-23T09:15:35.801917;2026-07-23T09:15:35.801918;Guest;Role: Guest;Global
5E32EE6A-1A73-4ACF-9C61-90E4D0D59261;0000DFD5-0000-0000-0000-00000000000A;2026-07-23T09:15:35.801921;2026-07-23T09:15:35.801922;CloudEngineer;Role: CloudEngineer;Global
6A2EE52C-6A9B-4A2A-B9C8-5851DD2D9A6F;0000DFD5-0000-0000-0000-00000000000A;2026-07-23T09:15:35.801925;2026-07-23T09:15:35.801926;BatchCapabilityCreator;Role: BatchCapabilityCreator;Global
A983CF2E-772E-437D-B9D8-5DDF769339D3;0000DFD5-0000-0000-0000-00000000000A;2026-07-23T09:15:35.801929;2026-07-23T09:15:35.801930;ServiceCatalogueReader;Role: ServiceCatalogueReader;Global
14 changes: 6 additions & 8 deletions db/seed/RbacRoleGrants.csv
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
Id;RoleId;CreatedAt;AssignedEntityType;AssignedEntityId;Type;Resource
FCC8821B-D9E1-4E0D-9D86-1F80965FBA87;36202DFB-D106-440D-8B99-F11BC8D77C9C;2000-01-01;User;andfris@dfds.com;Capability;cloudengineering-xxx
FCC8821B-D9E1-4E0D-9D86-1F80965FBA79;22DAB91B-C2D8-4840-A173-1416EF1B882D;2000-01-01;User;andfris@dfds.com;Capability;cool-beans-xxx
FCC8821B-D9E1-4E0D-9D86-1F80965FBA86;22DAB91B-C2D8-4840-A173-1416EF1B882D;2000-01-01;User;emcla@dfds.com;Capability;cloudengineering-xxx
FCC8821B-D9E1-4E0D-9D86-1F80965FBA88;22DAB91B-C2D8-4840-A173-1416EF1B882D;2000-01-01;User;emcla@dfds.com;Global;
FCC8821B-D9E1-4E0D-9D86-1F80965FBA89;36202DFB-D106-440D-8B99-F11BC8D77C9C;2000-01-01;User;owner@bar.com;Capability;bar
FCC8821B-D9E1-4E0D-9D86-1F80965FBA90;2C561A6D-90F4-4649-80B3-76A854A64EA2;2000-01-01;User;contributor@bar.com;Capability;bar
FCC8821B-D9E1-4E0D-9D86-1F80965FBA91;22DAB91B-C2D8-4840-A173-1416EF1B882D;2000-01-01;User;reader@bar.com;Capability;bar
FCC8821B-D9E1-4E0D-9D86-1F80965FBA92;36202DFB-D106-440D-8B99-F11BC8D77C9C;2000-01-01;User;other@foo.com;Capability;foo
E02D91E6-DE3C-4C55-BC0A-EDABD1492197;5E32EE6A-1A73-4ACF-9C61-90E4D0D59261;2026-07-23T09:15:35.803819;Group;BA0AA734-206D-454E-AC95-14855B6901E4;Global;
4CE54588-72CB-4B27-93D3-7F842B9C91AF;6A2EE52C-6A9B-4A2A-B9C8-5851DD2D9A6F;2026-07-23T09:15:35.803831;Group;899F8F9E-3F7E-4EF3-A2CD-2E1DDA78E40A;Global;
059F294D-4FD4-4836-9B11-9A7E8FA125C7;A983CF2E-772E-437D-B9D8-5DDF769339D3;2026-07-23T09:15:35.803837;Group;7D3D7498-9075-4D1B-B6C1-AF6E95788C3B;Global;
F1F3A53C-3D8E-4D54-BF66-7FB67209B701;36202DFB-D106-440D-8B99-F11BC8D77C9C;2026-07-23T09:15:35.803840;User;owner@bar.com;Capability;bar
706A6EB8-4378-4F66-9D37-BC84601D57F0;2C561A6D-90F4-4649-80B3-76A854A64EA2;2026-07-23T09:15:35.803843;User;contributor@bar.com;Capability;bar
8D0D4C50-2336-4C1C-91D8-7654577F52B3;22DAB91B-C2D8-4840-A173-1416EF1B882D;2026-07-23T09:15:35.803846;User;reader@bar.com;Capability;bar
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ public async Task InitializeAsync()
application.ReplaceService<IMembershipApplicationQuery>(
new StubMembershipApplicationQuery(_aMembershipApplication)
);
/*
application.ReplaceService<IRbacPermissionGrantRepository>(
new StubRbacPermissionGrantRepository(
permissions: new[]
Expand All @@ -40,7 +39,6 @@ public async Task InitializeAsync()
}
)
);
*/
application.ReplaceService<IRbacRoleGrantRepository>(new StubRbacRoleGrantRepository());
application.ReplaceService<IPermissionQuery>(new StubPermissionQuery());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ public bool CanUnsetCapabilityTags(PortalUser portalUser)
return _authorized;
}

public bool CanBatchCreateCapabilities(PortalUser portalUser, UserId userId)
public bool CanBatchCreateCapabilities(PortalUser portalUser)
{
return _authorized;
}
Expand Down
98 changes: 87 additions & 11 deletions src/SelfService/Application/RbacApplicationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,6 @@ IRbacRoleRepository roleRepository
_cache = new RbacCache();
}

/*
[Note 2025-09-18 by andfris]
The permission checks in this service are commented out for now, as they interfere with bootstrapping
and with the Cloud Engineer role which is supposed to have blanket permissions.
*/

public async Task<PermittedResponse> IsUserPermitted(string user, List<Permission> permissions, string objectId)
{
var resp = new PermittedResponse();
Expand Down Expand Up @@ -178,7 +172,8 @@ public async Task<List<RbacPermissionGrant>> GetPermissionGrantsForUser(string u
user,
() =>
_permissionGrantRepository.GetAllWithPredicate(p =>
p.AssignedEntityType == AssignedEntityType.User && p.AssignedEntityId == user
p.AssignedEntityType == AssignedEntityType.User
&& string.Equals(p.AssignedEntityId, user, StringComparison.OrdinalIgnoreCase)
)
);
}
Expand All @@ -190,7 +185,8 @@ public async Task<List<RbacRoleGrant>> GetRoleGrantsForUser(string user)
user,
() =>
_roleGrantRepository.GetAllWithPredicate(p =>
p.AssignedEntityType == AssignedEntityType.User && p.AssignedEntityId == user
p.AssignedEntityType == AssignedEntityType.User
&& string.Equals(p.AssignedEntityId, user, StringComparison.OrdinalIgnoreCase)
)
);
}
Expand All @@ -211,7 +207,8 @@ public async Task<List<RbacPermissionGrant>> GetPermissionGrantsForGroup(string
groupId,
() =>
_permissionGrantRepository.GetAllWithPredicate(p =>
p.AssignedEntityType == AssignedEntityType.Group && p.AssignedEntityId == groupId
p.AssignedEntityType == AssignedEntityType.Group
&& string.Equals(p.AssignedEntityId, groupId, StringComparison.OrdinalIgnoreCase)
)
);
}
Expand All @@ -223,7 +220,8 @@ public async Task<List<RbacPermissionGrant>> GetPermissionGrantsForRole(string r
roleId,
() =>
_permissionGrantRepository.GetAllWithPredicate(p =>
p.AssignedEntityType == AssignedEntityType.Role && p.AssignedEntityId == roleId
p.AssignedEntityType == AssignedEntityType.Role
&& string.Equals(p.AssignedEntityId, roleId, StringComparison.OrdinalIgnoreCase)
)
);
}
Expand Down Expand Up @@ -272,7 +270,8 @@ public async Task<List<RbacRoleGrant>> GetRoleGrantsForGroup(string groupId)
groupId,
() =>
_roleGrantRepository.GetAllWithPredicate(p =>
p.AssignedEntityType == AssignedEntityType.Group && p.AssignedEntityId == groupId
p.AssignedEntityType == AssignedEntityType.Group
&& string.Equals(p.AssignedEntityId, groupId, StringComparison.OrdinalIgnoreCase)
)
);
}
Expand Down Expand Up @@ -838,6 +837,8 @@ public class Permission
public RbacNamespace Namespace { get; set; } = RbacNamespace.Default;
public RbacAccessType AccessType { get; set; } = RbacAccessType.Capability;

// Canonical catalog of known RBAC permissions exposed by the application.
// The database stores the actual permission grants (who/what has which permission and scope).
public static List<Permission> BootstrapPermissions()
{
var permissions = new List<Permission>
Expand Down Expand Up @@ -938,12 +939,87 @@ public static List<Permission> BootstrapPermissions()
new(RbacNamespace.Rbac, "create", "Manage RBAC", RbacAccessType.Global),
new(RbacNamespace.Rbac, "update", "Manage RBAC", RbacAccessType.Global),
new(RbacNamespace.Rbac, "delete", "Manage RBAC", RbacAccessType.Global),
new(RbacNamespace.ServiceCatalogue, "read", "Read service catalogue resources", RbacAccessType.Global),
new(
RbacNamespace.SystemLegacy,
"read",
"Read legacy system data (e.g. AAD-AWS sync capability list)",
RbacAccessType.Global
),
new(
RbacNamespace.SystemAdmin,
"view-deleted-capabilities",
"View deleted capabilities",
RbacAccessType.Global
),
new(RbacNamespace.SystemAdmin, "unset-capability-tags", "Unset capability tags", RbacAccessType.Global),
new(RbacNamespace.SystemAdmin, "create-demo-recording", "Create demo recordings", RbacAccessType.Global),
new(RbacNamespace.SystemAdmin, "update-demo-recording", "Update demo recordings", RbacAccessType.Global),
new(RbacNamespace.SystemAdmin, "delete-demo-recording", "Delete demo recordings", RbacAccessType.Global),
new(
RbacNamespace.SystemAdmin,
"manage-permission-matrix",
"Manage permission matrix",
RbacAccessType.Global
),
new(
RbacNamespace.SystemAdmin,
"synchronize-aws-ecr-and-database-ecr",
"Synchronize AWS ECR and database ECR",
RbacAccessType.Global
),
new(
RbacNamespace.SystemAdmin,
"bypass-membership-approvals",
"Bypass membership approvals",
RbacAccessType.Global
),
new(
RbacNamespace.SystemAdmin,
"manage-self-assessment-options",
"Manage self-assessment options",
RbacAccessType.Global
),
new(RbacNamespace.SystemAdmin, "create-release-notes", "Create release notes", RbacAccessType.Global),
new(RbacNamespace.SystemAdmin, "update-release-note", "Update release note", RbacAccessType.Global),
new(
RbacNamespace.SystemAdmin,
"toggle-release-note-is-active",
"Toggle release note active state",
RbacAccessType.Global
),
new(
RbacNamespace.SystemAdmin,
"list-draft-release-notes",
"List draft release notes",
RbacAccessType.Global
),
new(RbacNamespace.SystemAdmin, "remove-release-note", "Remove release note", RbacAccessType.Global),
new(RbacNamespace.SystemAdmin, "create-event", "Create events", RbacAccessType.Global),
new(RbacNamespace.SystemAdmin, "update-event", "Update events", RbacAccessType.Global),
new(RbacNamespace.SystemAdmin, "delete-event", "Delete events", RbacAccessType.Global),
new(RbacNamespace.SystemAdmin, "create-news-item", "Create news items", RbacAccessType.Global),
new(RbacNamespace.SystemAdmin, "update-news-item", "Update news items", RbacAccessType.Global),
new(RbacNamespace.SystemAdmin, "delete-news-item", "Delete news items", RbacAccessType.Global),
new(RbacNamespace.SystemAdmin, "get-user-emails", "Get user emails", RbacAccessType.Global),
new(
RbacNamespace.CapabilityManagement,
"batch-create-capabilities",
"Create capabilities in batch as administrator",
RbacAccessType.Global
),
new(
RbacNamespace.SystemAdmin,
"delete-membership-application-as-admin",
"Delete membership applications as administrator",
RbacAccessType.Global
),
new(
RbacNamespace.SystemAdmin,
"retry-creating-message-contract",
"Retry failed message contract creation as administrator",
RbacAccessType.Global
),
};

return permissions;
Expand Down
10 changes: 9 additions & 1 deletion src/SelfService/Domain/Models/RbacNamespace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace SelfService.Domain.Models;
[JsonConverter(typeof(RbacNamespaceJsonConverter))]
public class RbacNamespace : ValueObject
{
// topics, capability-management, capability-membership-management, tags-and-metadata, aws, finout, azure, rbac, system-legacy
// topics, capability-management, capability-membership-management, tags-and-metadata, aws, finout, azure, rbac, service-catalogue, system-admin, system-legacy
public static readonly RbacNamespace Topics = new("topics");
public static readonly RbacNamespace TopicsPublic = new("topics-public");
public static readonly RbacNamespace CapabilityManagement = new("capability-management");
Expand All @@ -16,6 +16,8 @@ public class RbacNamespace : ValueObject
public static readonly RbacNamespace Finout = new("finout");
public static readonly RbacNamespace Azure = new("azure");
public static readonly RbacNamespace Rbac = new("rbac");
public static readonly RbacNamespace ServiceCatalogue = new("service-catalogue");
public static readonly RbacNamespace SystemAdmin = new("system-admin");
public static readonly RbacNamespace SystemLegacy = new("system-legacy");

// allow non-optional values. Cannot be created and has no permissions.
Expand Down Expand Up @@ -79,6 +81,12 @@ public static bool TryParse(string input, out RbacNamespace rbacNamespace)
case "rbac":
rbacNamespace = Rbac;
break;
case "service-catalogue":
rbacNamespace = ServiceCatalogue;
break;
case "system-admin":
rbacNamespace = SystemAdmin;
break;
case "system-legacy":
rbacNamespace = SystemLegacy;
break;
Expand Down
Loading
Loading