Casey Bodley [Sun, 25 Feb 2024 15:04:44 +0000 (10:04 -0500)]
rgw: make user email matching case-insensitive
handle user emails the same way we do account account emails. store
RGWUserInfo::user_email exactly as the user specified it, but convert
the object name to lower-case for case-insensitive matching
Casey Bodley [Thu, 22 Feb 2024 18:16:00 +0000 (13:16 -0500)]
rgw/iam: Policy takes optional tenant name
the iam policy parser takes a tenant string to reject Resource ARNs that
specify resources in other tenants, and prevent wildcards from applying
to other tenants
this is problematic for account users, because cross-account access requires
an identity policy that covers another account's resource. it's the
cross-policy evaluation rules that prevent that from granting access to
things it shouldn't. so for account users, pass a null tenant string to
allow all resource arns
for resource policies, this restriction is unnecessary in the first
place, because the resource policy can only match itself as the resource
Casey Bodley [Wed, 21 Feb 2024 23:51:44 +0000 (18:51 -0500)]
rgw/auth: replace uses of verify_bucket_owner_or_policy()
all of the s3 actions that we call verify_bucket_owner_or_policy() for
are already covered by rgw::IAM::op_to_perm(), which maps actions to
acl permissions like RGW_PERM_READ, RGW_PERM_WRITE_ACP etc
that means we can call verify_bucket_permission() as most other bucket
ops do, and rely on its call to verify_bucket_permission_no_policy() to
find the owner's acl grant
i also hadn't implemented the cross-account rules for
verify_bucket_owner_or_policy() yet, and didn't want to
Casey Bodley [Wed, 21 Feb 2024 20:55:09 +0000 (15:55 -0500)]
rgw/auth: RoleApplier matches account principals
account principals of the form ``arn:aws:iam::123456789012:root``
or ``123456789012`` delegate authority to the account, which means that
it applies to all of the account's users and roles
Casey Bodley [Sun, 18 Feb 2024 14:16:06 +0000 (09:16 -0500)]
rgw/iam: fix DeleteRolePolicyResponse
should only be written on success
was misspelled as DeleteRolePoliciesResponse which boto doesn't like:
botocore.parsers.ResponseParserError: Unable to parse response (junk after document element: line 1, column 159), invalid XML received. Further retries may su
cceed:
b'<DeleteRolePoliciesResponse><ResponseMetadata><RequestId>tx0000082c62511b240fd3d-0065d20f66-4129-a2</RequestId></ResponseMetadata></DeleteRolePoliciesResponse><?xml version="1.0" encoding="UTF-8"?><ErrorResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/"><Error><Code>NoSuchEntity</Code><Message>The requested PolicyName was not found</Message><RequestId>tx0000082c62511b240fd3d-0065d20f66-4129-a2</RequestId><HostId>4129-a2-a</HostId></Error></ErrorResponse>'
Casey Bodley [Mon, 19 Feb 2024 22:31:55 +0000 (17:31 -0500)]
rgw: forward_to_master() passes rgw_owner for effective uid header
when s3 requests get forwarded to the master zone in multisite, we sign
them as the multisite system user because we need to extend the s3
protocol. for example, CreateBucket requests issues by a system user
include an extra response body that encodes the RGWBucketInfo. this way,
the secondary zone can recreate exactly the same bucket that the master
zone did
these forwarded requests include a header like "rgwx-uid: myuserid" to
request that the system user impersonate the given uid. this isn't
necessary for authorization, because the system user overrides
permission checks already. but it's important for resource ownership -
the result of a forwarded CreateBucket request should be a bucket owned
by "myuserid", not the system user
because this "rgwx-uid" header is concerned with ownership, we pass the
string encoding of rgw_owner instead of rgw_user. on the receiving side,
we parse this header in SysReqApplier and override get_aclowner() to
expose it
Casey Bodley [Sat, 17 Feb 2024 22:53:21 +0000 (17:53 -0500)]
rgw/iam: only RGWDeleteRole returns ERR_DELETE_CONFLICT
metadata sync calls RadosRole::delete_obj() after the role is deleted on
the metadata master zone. the role was verified to be empty there, so
metadata sync needs to delete the role anyway
only the iam DeleteRole api should require policies to be removed first
Casey Bodley [Tue, 6 Feb 2024 14:32:27 +0000 (09:32 -0500)]
rgw/sal: remove virtual class RGWOIDCProvider
class RGWOIDCProvider was doing a lot of different things, so i've split
out its responsibilities:
* move data members and encoding into new struct RGWOIDCProviderInfo,
and add ceph-dencoder hooks for regression testing
* remove RGWOIDCProvider class and add load/store/delete/list functions
to the sal::Driver interface
* rgw_rest_oidc_provider.cc handles most of the parameter validation,
ARN parsing, and json formatting
Casey Bodley [Mon, 5 Feb 2024 22:49:42 +0000 (17:49 -0500)]
rgw/iam: refactor OIDC ops
rearrange the RGWRESTOp subclasses so that the base RGWRestOIDCProvider
can provide a simple verify_permission() that works the same for all
derived ops
Casey Bodley [Sat, 20 Jan 2024 20:16:00 +0000 (15:16 -0500)]
rgw/role: separate dump_iam_role() for iam api
create a new dump_iam_role() for iam api responses that dumps the subset
of role information presented by the apis
RGWRoleInfo::dump() and decode_json() are used by metadata sync to
transfer role metadata between zones, so must contain all information
about the role
Casey Bodley [Mon, 15 Jan 2024 01:36:28 +0000 (20:36 -0500)]
rgw/iam: role apis override init_processing/verify_permission
replace get_params() with init_processing() override which runs before
verify_permission(). use this to validate request parameters and load
the existing role if necessary. simplify verify_permission() by
forwarding to RGWRESTOp::verify_permission() which calls check_caps()
simplify inheritence hierarchy by taking cap perm and iam action as
constructor arguments
Casey Bodley [Tue, 2 Jan 2024 22:11:03 +0000 (17:11 -0500)]
rgw/auth: Identity::is_identity() takes one Principal
take a single Principal instead flat_set<Principal>, and iterate over
calls to is_identity() instead
why?
* it simplifies the logic of each is_identity() function because they
can use early returns to avoid visiting all of the cases
* Statement::eval_principal() no longer has to allocate a flat_set
with a single element when the Identity is a role
* rgw::auth::Identity no longer depends on rgw::iam's choice of
container type
Casey Bodley [Thu, 11 Jan 2024 22:10:06 +0000 (17:10 -0500)]
rgw/rest: wrap iam/sns/sts Error responses with ErrorResponse
all iam/sns/sts requests wrap the s3 <Error> xml response in another
<ErrorResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
without this, boto3 fails to fully parse error responses, leading to
generic Unknown ClientError exceptions of the form:
botocore.exceptions.ClientError: An error occurred (Unknown) when calling the PutUserPolicy operation: Unknown
with the ErrorResponse part, boto3 throws more specific exceptions that
include the error Code and Message:
botocore.errorfactory.NoSuchEntityException: An error occurred (NoSuchEntity) when calling the PutUserPolicy operation: No such UserName in the account