Skip to content

SP136: expose subsystem RBAC access via GET/PUT .../access - #1523

Open
ikethecoder wants to merge 1 commit into
hotfix/aps-4799-m0-carryoverfrom
task/sp136-subsystem-rbac-access
Open

SP136: expose subsystem RBAC access via GET/PUT .../access#1523
ikethecoder wants to merge 1 commit into
hotfix/aps-4799-m0-carryoverfrom
task/sp136-subsystem-rbac-access

Conversation

@ikethecoder

@ikethecoder ikethecoder commented Aug 5, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds GET /organizations/{org}/subsystems/{name}/access and PUT /organizations/{org}/subsystems/{name}/access to OrgSubsystemController, so a subsystem's RBAC role assignments (System Owner, Technical Lead, Access Manager) can be viewed and changed directly.
  • No new backend logic was needed: the write path (SysGroupAccessService.createOrUpdateGroupAccess('subsystem', ...)) and read path (GroupAccessService.getGroupMembership(clientId)) already existed and are already exercised internally (at gateway-registration time, and for catalog access enrichment respectively) — this just exposes them as a dedicated route, mirroring the existing GET/PUT /organizations/{org}/access pattern.
  • No provisioner changes — this is entirely a portal-to-Keycloak (UMA2 group/policy) concern, same as the existing org-level /access routes.

Test plan

  • New cypress spec e2e/cypress/tests/99-sp136/01-subsystem-access.ts demonstrates the fix: registers a subsystem gateway (which auto-grants the acting user all three roles), confirms GET .../access returns that membership, then PUT .../access to replace membership with a second user holding only tech-lead, and confirms the change via a follow-up GET.
  • Verified the new test fails with 404 against the unfixed controller (temporarily reverted just the controller change, rebuilt, reran) and passes once the fix is restored.
  • Regression: e2e/cypress/tests/21-sdx-api/v1/01-subsystems.ts (11 passing) and e2e/cypress/tests/19-api-v3/02-organization.ts (9 passing) both green against the fixed branch.
  • tsc --noEmit clean on src/.

🤖 Generated with Claude Code

Add GET/PUT /organizations/{org}/subsystems/{name}/access to
OrgSubsystemController, wiring existing but previously unreachable
group-membership logic (GroupAccessService.getGroupMembership /
SysGroupAccessService.createOrUpdateGroupAccess) to a dedicated route,
so subsystem RBAC (system-owner, tech-lead, access-manager) can be
viewed and changed after the initial grant made at gateway registration.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@rustyjux rustyjux left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.
Couple comments to consider:

  1. No activity logging, not sure when this will be implemented
  2. Probably just a weird edge case, but any chance someone would configure subsystem access before registering the gateway (which would overwrite the configured access)?

*/
@Put('/{name}/access')
@OperationId('putSubsystemAccess')
@Security('jwt', ['System.Manage'])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please confirm the intended authorization boundary for changing subsystem membership? The existing organization access PUT uses GroupAccess.Manage, while this RBAC mutation uses System.Manage. Is System.Manage intentionally sufficient to grant or revoke the system-owner, tech-lead, and access-manager roles?

public async putAccess(
@Path() org: string,
@Path() name: string,
@Body() body: { members: GroupMember[] },

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could the accepted role names be validated before this full-membership sync? GroupMember.roles is a string[], while SysGroupAccessService only processes the predefined system roles. An unrecognized or misspelled role is therefore ignored while absent recognized roles are synchronized as empty, which can revoke current assignments. Would rejecting unknown role names protect against accidental destructive updates?

envConfig.clientSecret
);

await sysGroupAccessService.createOrUpdateGroupAccess(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you clarify whether subsystem access changes should produce activity or audit records? The existing organization-access PUT uses the returned granted/revoked diff to call logOrganizationAccessChanges, while the diff from this RBAC update is discarded. If that omission is intentional, some context here would be helpful.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createOrUpdateGroupAccess performs a full membership sync, but silently drops emails that cannot be resolved in Keycloak. As a result, a request containing an unknown email returns 204 while revoking the existing members for all three roles.

Could we validate that every requested member resolves before starting the sync, and return 400 if any do not?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants