Whitelist ownership grants via allow policies
Replace the deny-based restriction on granting OWNER with role-scoped allow policies so authorization fails closed: admins may create and update memberships only when the assigned role is not OWNER, and the absence of a target role no longer implies permission. To keep console UI gating accurate without loosening the base grants, the permission field gains an optional typed options argument (PermissionOptionsInput) that forwards target_role into the dry-run authorization. Only the two role-related console calls (create user, update membership) pass it; the OWNER option stays hidden for admins via the existing assignable-roles helper. Add a non-regression test that an admin cannot promote a member to OWNER while still being able to change members between non-owner roles.
This commit is contained in:
@@ -265,6 +265,9 @@ var IAMAdminPolicy = policy.NewPolicy(
|
||||
WithSID("membership-admin-access").
|
||||
When(policy.Equals("principal.organization_id", "resource.organization_id")),
|
||||
|
||||
// Can update memberships, but neither of an existing owner (resource.role)
|
||||
// nor to grant ownership (resource.target_role); only owner can grant
|
||||
// ownership.
|
||||
policy.Allow(
|
||||
ActionMembershipUpdate,
|
||||
).
|
||||
@@ -272,13 +275,13 @@ var IAMAdminPolicy = policy.NewPolicy(
|
||||
When(
|
||||
policy.Equals("principal.organization_id", "resource.organization_id"),
|
||||
policy.NotEquals("resource.role", "OWNER"),
|
||||
policy.NotEquals("resource.target_role", "OWNER"),
|
||||
),
|
||||
|
||||
// Can view membership profiles (scoped to own organization)
|
||||
// Can view and manage membership profiles (scoped to own organization)
|
||||
policy.Allow(
|
||||
ActionMembershipProfileGet,
|
||||
ActionMembershipProfileList,
|
||||
ActionMembershipProfileCreate,
|
||||
ActionMembershipProfileUpdate,
|
||||
ActionMembershipProfileDelete,
|
||||
ActionMembershipProfileActivate,
|
||||
@@ -287,6 +290,15 @@ var IAMAdminPolicy = policy.NewPolicy(
|
||||
WithSID("membership-profile-admin-access").
|
||||
When(policy.Equals("principal.organization_id", "resource.organization_id")),
|
||||
|
||||
// Can create members, but not with the OWNER role (resource.target_role);
|
||||
// only owner can grant ownership.
|
||||
policy.Allow(ActionMembershipProfileCreate).
|
||||
WithSID("membership-profile-admin-create").
|
||||
When(
|
||||
policy.Equals("principal.organization_id", "resource.organization_id"),
|
||||
policy.NotEquals("resource.target_role", "OWNER"),
|
||||
),
|
||||
|
||||
// Can view identities of members in the same organization
|
||||
policy.Allow(ActionIdentityGet).
|
||||
WithSID("view-member-identity").
|
||||
@@ -313,15 +325,6 @@ var IAMAdminPolicy = policy.NewPolicy(
|
||||
policy.Deny(ActionMembershipDelete).
|
||||
WithSID("deny-remove-member"),
|
||||
|
||||
// Cannot grant ownership, whether by creating an OWNER member or promoting an
|
||||
// existing member to OWNER (only owner can grant ownership)
|
||||
policy.Deny(ActionMembershipProfileCreate).
|
||||
WithSID("deny-create-owner").
|
||||
When(policy.Equals("resource.target_role", "OWNER")),
|
||||
policy.Deny(ActionMembershipUpdate).
|
||||
WithSID("deny-promote-owner").
|
||||
When(policy.Equals("resource.target_role", "OWNER")),
|
||||
|
||||
// Cannot manage SAML configurations (only owner can)
|
||||
policy.Deny(
|
||||
ActionSAMLConfigurationCreate,
|
||||
|
||||
Reference in New Issue
Block a user