Skip to content

Backport/tentacle 20.2.4 cobaltcore storage/keystone project reader - #46

Merged
s0nea merged 4 commits into
tentacle-20.2.4-cobaltcore-storagefrom
backport/tentacle-20.2.4-cobaltcore-storage/keystone-project-reader
Nov 4, 2026
Merged

s0nea merged 4 commits into
tentacle-20.2.4-cobaltcore-storagefrom
backport/tentacle-20.2.4-cobaltcore-storage/keystone-project-reader

Conversation

@supriti

@supriti supriti commented Oct 30, 2026 •

Copy link
Copy Markdown

Closes cobaltcore-dev/cloud-storage#573

Backport file

  • release-management/backports/<uuid>.md added (or updated) by this PR
  • id in frontmatter matches the filename stem
  • provenance.upstream_prs set (or provenance.type: other with an other: block)

Stage-B risk (filled per release-management/backports/RISK-RUBRIC.md)

  • blast — cosmetic / availability / data-loss
  • conflict — clean / trivial / substantive
  • coverage — strong / partial / weak
  • Risk-notes paragraph in the prose section (required for high band)

Merge

Land this via just merge-backport PR=<N> — do not click the green merge button.
The just recipe constructs the merge commit's Backport-Id trailer.

@supriti

supriti commented Oct 30, 2026

Copy link
Copy Markdown
Author

DNM unless #41 is in. This change is developed on top of #41

Backport of ceph#70372 (Keystone project reader role + implicit-deny role) to tentacle-20.2.4-cobaltcore-storage.

Refs cobaltcore-dev/cloud-storage#566

Depends on #41

This branch is stacked on #41 (Keystone role/userid in IAM policy). Until #41 is merged, the diff also shows #41's commits and metadata file. Merge #41 first. This PR then shrinks to its own changes with no rebase needed:

  • rgw/keystone: add project-scoped reader role
  • rgw/keystone: add implicit-deny role
  • rgw/keystone: collapse per-role permission flags into one token tier
  • release-management/backports/01a18d83-9554-7c5f-8407-f6a30b7f3c9f.md

To see only this PR's changes now:
backport/tentacle-20.2.4-cobaltcore-storage/keystone-iam-policy...backport/tentacle-20.2.4-cobaltcore-storage/keystone-project-reader

Notes

  • Tentacle lacks some newer upstream code, so STS, SNS topics and the new unit test needed small adaptations. Everything else matches upstream.
  • Tested on tentacle with unit tests and live tests against RGW and Keystone.

The existing rgw_keystone_accepted_reader_roles is system-scoped: it
grants read access across all Keystone projects and only takes effect
when the role is also listed in rgw_keystone_accepted_admin_roles.

This commit adds rgw_keystone_accepted_project_reader_roles for a
project-scoped reader, mirroring Swift's project_reader_roles. When the
listed role is the only granting role on a token, the identity is capped
to read-only within its Keystone project: perm_mask is set to
RGW_PERM_READ | RGW_PERM_READ_ACP, read object data and inspect bucket
configuration (ACLs, policy, versioning, location,..). Writes are denied.

This cap is a floor, not a hard ceiling: a bucket or IAM policy naming
the user (keystone:userid / keystone:role) can still grant specific writes.
CreateBucket and Swift account-metadata writes, which bypass the per-bucket
ACL check, are refused up front for a capped Keystone identity.

Like an admin role, a project-reader role admits the user on its own; it
need not also appear in rgw_keystone_accepted_roles. The most permissive
accepted role wins, so a user that also holds a plain accepted role (e.g.
member) or admin receives full control.

Every Keystone user in a project maps to the same RGW owner: the
project account (acct_user = project id), so a reader reads and lists
every bucket the project owns through the normal owner-scoped paths, and
cannot reach another project (a different owner). This scoping is by
ownership and holds regardless of rgw_keystone_implicit_tenants, which
only controls the bucket-name namespace (per-project vs. global);
implicit_tenants=true is recommended.

Because the reader is itself the project owner, owner-scoped grant paths
(bucket mdsearch, SNS topics) go through a new verify_owner_permission()
helper so ownership alone does not lift the cap. STS AssumeRole is a
separate case: it would swap in a role identity that carries no perm_mask,
so it is refused outright for a capped identity.

Also rename is_reader to is_system_reader and add is_project_reader to
tell the two role types apart.

Add unit tests.

Fixes: https://tracker.ceph.com/issues/81098
On-behalf-of: SAP <supriti.singh@clyso.com>
Signed-off-by: Supriti Singh <supriti.singh@clyso.com>
(cherry picked from commit 87252a5)
Building on the project-scoped reader, add
rgw_keystone_implicit_deny_roles: a Keystone role that authenticates a
user but grants no implicit permissions.

When such a role is the only granting role on a token,
effective_perm_mask() returns RGW_PERM_NONE, so the user is
authenticated but denied every operation by default (implicit deny).
Access must then come from an explicit bucket or IAM policy naming the
user (keystone:userid / keystone:role), and applies only to the buckets
and objects the policy names.

Like the reader, an implicit-deny role admits the user on its own (it
need not also be in rgw_keystone_accepted_roles), and the most permissive
accepted role still wins: admin, a project-reader, or another accepted
role such as member takes precedence over the implicit-deny cap.

Add the is_implicit_deny role flag and the config list, extend
effective_perm_mask, and add unit tests.

Fixes: https://tracker.ceph.com/issues/81098
On-behalf-of: SAP <supriti.singh@clyso.com>
Signed-off-by: Supriti Singh <supriti.singh@clyso.com>
(cherry picked from commit ba0c6ad)
Simplify how roles map to permissions by introducing an optional
permission value (perm_tier) in the TokenEnvelope. Compute it once while
updating the roles, instead of keeping several per-role flags and
resolving them later in Role::perm_mask() / effective_perm_mask().

update_roles() now derives the token's permission mask directly:

  nullopt        no accepted role -> token rejected
  RGW_PERM_NONE  implicit-deny
  READ|READ_ACP  project-reader
  FULL_CONTROL   plain accepted or admin

The most permissive role wins. admitted() replaces the duplicate role
checks in both auth engines and the admin check uses the is_admin flag;
only admin and system-reader stay as per-role flags.

Fixes: https://tracker.ceph.com/issues/81098
On-behalf-of: SAP <supriti.singh@clyso.com>
Signed-off-by: Supriti Singh <supriti.singh@clyso.com>
(cherry picked from commit dcc1de7)
Signed-off-by: Supriti Singh <supriti.singh@clyso.com>
@s0nea
s0nea force-pushed the backport/tentacle-20.2.4-cobaltcore-storage/keystone-project-reader branch from d6b2caf to e483fa1 Compare November 4, 2026 08:05
@s0nea
s0nea merged commit 6fc4e94 into tentacle-20.2.4-cobaltcore-storage Nov 4, 2026
4 checks passed
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.

2 participants