RGW ARN naming conventions considerations in multi tenant scenarios

Updated -

Disclaimer: Links contained herein to external website(s) are provided for convenience only. Red Hat has not reviewed the links and is not responsible for the content or its availability. The inclusion of any link to an external website does not imply endorsement by Red Hat of the website or their entities, products or services. You agree that Red Hat is not responsible or liable for any loss or expenses that may result due to your use of (or reliance on) the external site or content.

Amazon Resource Name (ARN) format

The following are the general formats for ARNs. The specific formats depend on the resource.
Be aware that:

  • RGW uses tenant instead of the AWS name account ID
  • the ARNs for some resources omit the Region, the tenant, or both the Region and the tenant.

    arn:partition:service:region:tenant:resource-id
    arn:partition:service:region:tenant:resource-type/resource-id
    arn:partition:service:region:tenant:resource-type:resource-id
    

    refer to the AWS documentation for the detailed explanation of the items that form the ARN.

Evaluating the tenant definition

The AWS documentation is not clear enough on the accepted characters being accepted. One might consider logical separation of for example the source system and the tenant name by adding special characters for separation like $.
The RGW internally uses special characters for handling logic within the code, and even accepting reserved characters as tenant name one should avoid the use of special characters to not conflict and or break deployments.

Recommendations for naming are to comply with ARN resource-id defined naming conventions as listed below.

Note: tenant name is unique and case-insensitive

  • names must be between 3(min) and 64(max) characters long
  • names can consist only of letters, numbers, dots(.), and hyphens(-)
  • names must not be formatted as an IP address (example, 127.0.0.1)
  • names must not start with the prefix xn-- (punycode)

tenant valid examples

arn:aws:s3::ldap.tenant1
arn:aws:s3::ad-tenant1

tenant invalid examples

arn:aws:s3::ldap$tenant1
arn:aws:s3::ldap%tenant1

Note: policies owned by a tenant cannot grant access to a resource owned by another tenant

Evaluating the resource-id definition

Resource ARNs can be formed similar as a unix style path. Objects can includes slashes (/) as well a wildcard character (*). Resources may not include a double point (:)

resource-id valid examples

arn:aws:s3::ldap.tenant1:bucket/file
arn:aws:s3::ldap.tenant1:bucket/subdirectory/file.txt
arn:aws:s3::ldap.tenant1:bucket/*

resource-id invalid examples

arn:aws:s3::ldap.tenant1:bucket/file:group.txt
arn:aws:s3::ldap.tenant1:bucket*

Paths in ARNs

Resource ARNs can include a path including slashes (/) wildcard character namely an asterisk (*) as well as a question mark (?) to represent any single character. You can use multiple wildcard characters in each segment but a wildcard cannot span segments.

example to identify all objects in a bucket

this example identifies all objects within bucket of tenant ldap-tenant1

arn:aws:s3::ldap.tenant1:bucket/*
example to identify objects by partial name

this example identifies all objects within bucket of tenant ldap.tenant1 starting with reports

arn:aws:s3::ldap.tenant1:buckets/reports*
example combining wildcard types question mark (?) and an asterix (*)

this example identifes all objects within bucket of tenant ldap.tenant1 with a year (YYYY) syntax 20?? and all extenions

arn:aws:s3::ldap.tenant1:buckets/reports-20??-*

the wildcard characters can be used multiple times to be more or less specific accordingly
this example matching the same files but for all year (YYYY) syntax report files and containing sa (eq sales)

arn:aws:s3::ldap.tenant1:buckets/reports-????-sa???-.*
example combining wildcards types in multiple segments

this example identifies all objects within bucket of tenant ldap.tenant1 with a folder structure matchin 20?? and starting with reports

arn:aws:s3::ldap.tenant1:buckets/20??/reports-*

combining wildcard characters within a segment is possible as seen in example combining wildcard types

Using rgw-policy-check to verify your policy

Red Hat provides a tool called rgw-policy-check to verify your policy in case it you are not sure on the syntax validity.
The tool expects a tenant (-t) and accepts one or multiple policies through stdin or files.

example usage for rgw-policy-check with stdin input

Our policy intends to limit the actions:

  • Action
    • s3:ListBucket
    • s3:GetObject
    • s3:GetObjectVersion

to grant access to reports of the sales department that are stored in the bucket at and named like:

  • Resource
    • bucket/YYYY/reports-sales.*

for everyone

  • Principal *

as long as the Client is from a corporate Network segment

  • aws:SourceIp
    • 10.0.0.1/24
    • 10.0.0.2/24

The policy compiles as follows and is written in json syntax

{
  "Version": "2012-10-17",
  "Id": "S3PolicyTest",
  "Statement": [
    {
      "Sid": "publicAccess",
      "Effect": "Allow",
      "Principal": "*",
      "Action": [
        "s3:ListBucket",
        "s3:GetObject",
        "s3:GetObjectVersion"
      ],
      "Resource": [
        "arn:aws:s3::ldap.tenant1:/bucket/20??/reports*"
      ],
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "10.0.0.1/24",
            "10.0.0.2/24"
          ]
        }
      }
    }
  ]
}

now calling the tool on your Red Hat Ceph Cluster to validate the policy, you need to specify the tenant (-t) as specified in the policy in Resource

$ rgw-ceph-policy -t ldap.tenant1 
{
  "Version": "2012-10-17",
  "Id": "S3PolicyTest",
  "Statement": [
    {
      "Sid": "publicAccess",
      "Effect": "Allow",
      "Principal": "*",
      "Action": [
        "s3:ListBucket",
        "s3:GetObject",
        "s3:GetObjectVersion"
      ],
      "Resource": [
        "arn:aws:s3::ldap.tenant1:/bucket/20??/reports*"
      ],
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "10.0.0.1/24",
            "10.0.0.2/24"
          ]
        }
      }
    }
  ]
}
[CTRL+D]
$ echo $?
0

the exit code 0 as well as no stderr output indicate that the policy is valid and accepted.

invalid policy reported by rgw-policy-check

using the same policy but adding an invalid Resource specification will report the character offset and the rgw-policy-check will exit with code 1

$ rgw-ceph-policy -t ldap::tenant1 
{
  "Version": "2012-10-17",
  "Id": "S3PolicyTest",
  "Statement": [
    {
      "Sid": "publicAccess",
      "Effect": "Allow",
      "Principal": "*",
      "Action": [
        "s3:ListBucket",
        "s3:GetObject",
        "s3:GetObjectVersion"
      ],
      "Resource": [
        "arn:aws:s3::ldap::tenant1:/bucket/20??/reports*"
      ],
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "10.0.0.1/24",
            "10.0.0.2/24"
          ]
        }
      }
    }
  ]
}
[CTRL+D]
(stdin): At character offset 337, `arn:aws:s3::ldap::tenant1:/bucket/20??/reports*` is not a valid ARN. Resource ARNs should have a format like `arn:aws:s3::tenant:resource' or `arn:aws:s3:::resource`.

$ echo $?
1

example usage for rgw-policy-check with multiple files input

when checking multiple policies stdin might not be sufficient and rgw-policy-check can iterate over a list of files validating and reporting syntax correctness accordingly.

$ rgw-policy-check -t ldap.tenant1 /tmp/policies*

$ echo $?
0

rgw-policy-check will report broken policies accordingly

$ rgw-policy-check -t ldap.tenant1 /tmp/policies*
/tmp/policies1.txt: At character offset 337, `arn:aws:s3::ldap::tenant1:/bucket/20??/reports*` is not a valid ARN. Resource ARNs should have a format like `arn:aws:s3::tenant:resource' or `arn:aws:s3:::resource`.
/tmp/policies3.txt: At character offset 337, `arn:aws:s3::ldap::tenant1:/bucket/20??/reports*` is not a valid ARN. Resource ARNs should have a format like `arn:aws:s3::tenant:resource' or `arn:aws:s3:::resource`.
/tmp/policies4.txt: At character offset 336, Policy owned by tenant `ldap.tenant1` cannot grant access to resource owned by tenant `ldap.tenant2`.

$ echo $?
1

Comments