Bucket and group access policies

The StorageGRID Webscale system implements a subset of the S3 REST API policy language that you can use to control access to buckets and objects within those buckets.

Overview

StorageGRID Webscale uses the Amazon Web Services (AWS) policy language syntax to allow S3 tenants to create access policies to their data. Access policies for the S3 API are written in JSON. There are two kinds of access policies supported by StorageGRID Webscale:
  • Bucket policies, which are configured using the GET Bucket policy, PUT Bucket policy, and DELETE Bucket policy S3 API operations. Bucket policies are attached to buckets, so they are configured to control access by users in the bucket owner account or other accounts to the bucket and the objects in it. A bucket policy applies to only one bucket and possibly multiple groups.
  • Group policies, which are configured using the Tenant Management Interface or Tenant Management API. Group policies are attached to a group in the account, so they are configured to allow that group to access specific resources owned by that account. A group policy applies to only one group and possibly multiple buckets.
StorageGRID Webscale bucket and group policies follow a specific grammar defined by Amazon. Inside each policy is an array of policy statements, and each statement contains the following elements:
  • Statement ID (Sid) (optional)
  • Effect
  • Principal/NotPrincipal
  • Resource/NotResource
  • Action/NotAction
  • Condition (optional)

Policy statements are built using this structure to specify permissions: Grant <Effect> to allow/deny <Principal> to perform <Action> on <Resource> when <Condition> applies.

Each policy element is used for a specific function:

Element Description
Sid The Sid element is optional. The Sid is only intended as a description for the user. It is stored but not interpreted by the StorageGRID Webscale system.
Effect Use the Effect element to establish whether the specified operations are allowed or denied. You must identify operations you allow (or deny) on buckets or objects using the supported Action element keywords.
Principal/NotPrincipal

You can allow users, groups, and accounts to access specific resources and perform specific actions. If no S3 signature is included in the request, anonymous access is allowed by specifying the wildcard character (*) as the principal. By default, only the account root has access to resources owned by the account.

You only need to specify the Principal element in a bucket policy. For group policies, the group to which the policy is attached is the implicit Principal element.

Resource/NotResource The Resource element identifies buckets and objects. You can allow or deny permissions to buckets and objects using the uniform resource name (URN) to identify the resource.
Action/NotAction The Action and Effect elements are the two components of permissions. When a group requests a resource, they are either granted or denied access to the resource. Access is denied unless you specifically assign permissions, but you can use explicit deny to override a permission granted by another policy.
Condition The Condition element is optional. Conditions allow you to build expressions to determine when a policy should be applied.
In the Action element, you can use the wildcard character (*) to specify all operations, or a subset of operations. For example, this Action matches permissions such as s3:GetObject, s3:PutObject, and s3:DeleteObject.
s3:*Object

In the Resource element, you can use the wildcard characters (*) and (?). While the asterisk (*) matches 0 or more characters, the question mark (?) matches any single character.

In the Principal element, wildcard characters are not supported except to set anonymous access, which grants permission to everyone. For example, you set the wildcard (*) as the Principal value.

"Principal":"*"

In the following example, the statement is using the Effect, Principal, Action, and Resource elements. This example shows a complete bucket policy statement that uses the Effect "Allow" to give the Principals, the admin group federated-group/admin and the finance group federated-group/finance, permissions to perform the Action s3:ListBucket on the bucket named "mybucket" and the Action s3:GetObject on all objects inside that bucket.

{
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "SGWS": [
          "urn:sgws:identity::27233906934684427525:federated-group/admin",
          "urn:sgws:identity::27233906934684427525:federated-group/finance"
        ]
      },
      "Action": [
        "s3:ListBucket",
        "s3:GetObject"
      ],
      "Resource": [
        "urn:sgws:s3:::mybucket",
        "urn:sgws:s3:::mybucket/*"
      ]
    }
  ]
}

The bucket policy has a size limit of 20,480 bytes, and the group policy has a size limit of 5,120 bytes.

Consistency control settings for policies

By default, any updates you make to group policies are eventually consistent. Once a group policy becomes consistent, the changes can take an additional 15 minutes to take effect, because of policy caching.

By default, any updates you make to bucket policies are also eventually consistent. However, as required, you can change the consistency guarantees for bucket policy updates. For example, you might want a change to a bucket policy to become effective as soon as possible for security reasons.

In this case, you can either set the Consistency-Control header in the PUT Bucket policy request, or you can use the PUT Bucket consistency request. When changing the consistency control for this request, you must use the value all, which provides the highest guarantee of read-after-write consistency. If you specify any other consistency control value in a header for the PUT Bucket consistency request, the request will be rejected. If you specify any other value for a PUT Bucket policy request, the value will be ignored. Once a bucket policy becomes consistent, the changes can take an additional 8 seconds to take effect, because of policy caching.
Note: If you set the consistency level to all to force a new bucket policy to become effective sooner, be sure to set the bucket-level control back to its original value when you are done. Otherwise, all future bucket requests will use the all setting.

Using the URN in policy statements

In policy statements, the URN is used in Principal and Resource elements as follows.
  • Use this syntax to specify the S3 resource URN:
    urn:sgws:s3:::bucket_name
    urn:sgws:s3:::bucket_name/object_key
  • Use this syntax to specify the identity resource URN (users and groups):
    urn:sgws:identity::account_id:root
    urn:sgws:identity::account_id:user/user_name
    urn:sgws:identity::account_id:group/group_name
    urn:sgws:identity::account_id:federated-user/user_name
    urn:sgws:identity::account_id:federated-group/group_name
Other considerations:
  • You can use the asterisk (*) as a wildcard to match zero or more characters inside the object key.
  • International characters, which can be specified in the object key, should be encoded using JSON UTF-8 or using JSON \u escape sequences. Percent-encoding, as outlined in RFC 2141 URN Syntax, is not supported.

    The HTTP request body for the PUT Bucket policy operation must be encoded with charset=UTF-8.

Specifying resources in a policy

In policy statements, you can use the Resource element to specify the bucket or object for which permissions are allowed/denied.
  • Each policy statement requires a Resource element. In a policy, resources are denoted by the element "Resource," or alternatively, "NotResource" for exclusion.
  • You specify resources with an S3 resource URN.

    For example:

    "Resource": "urn:sgws:s3:::mybucket/*"
  • You can also use policy variables inside the object key.
    Example:
    "Resource": "urn:sgws:s3:::mybucket/home/${sgws:username}/*"

    See Specifying variables in a policy for a list of available policy variables.

  • The resource value can specify a bucket that does not yet exist when a group policy is created.

Specifying principals in a policy

Use the Principal element to identity the user, group, or tenant account that is allowed/denied access to the resource by the policy statement.
  • When building a group policy statement, no Principal element is specified because the group is understood to be the principal.
  • Each policy statement must include a Principal element (unless it is a group policy). In a policy, principals are denoted by the element "Principal," or alternatively "NotPrincipal" for exclusion.
  • Account-based identities must be specified using an ID or a URN:
    "Principal": { "SGWS": "account_id"}
    "Principal": { "SGWS": "identity_urn" }
    
  • This example uses the tenant account ID 27233906934684427525, which includes the account root and all users in the account:
     "Principal": { "SGWS": "27233906934684427525" }
  • You can specify just the account root:
    "Principal": { "SGWS": "urn:sgws:identity::27233906934684427525:root" }
  • You can specify a specific federated user ("Bob"):
    "Principal": { "SGWS": "urn:sgws:identity::27233906934684427525:federated-user/Bob" }
  • You can specify a specific federated group ("Managers"):
    "Principal": { "SGWS": "urn:sgws:identity::27233906934684427525:federated-group/Managers"  }
  • You can specify an anonymous principal:
    "Principal": "*"
  • If the username Bob was deleted upon leaving the organization, and then later on, another Bob joins the organization and was assigned the same username Bob, he could have unintentionally inherited the permissions granted to the previous Bob. To avoid such ambiguity, the user UUID can be used instead of the username. For example:
    urn:sgws:identity::27233906934684427525:user-uuid/de305d54-75b4-431b-adb2-eb6b9e546013
  • The principal value can specify a group/user name that does not yet exist when a bucket policy is created.

Specifying permissions in a policy

In a policy, the Action element is used to allow/deny permissions to a resource. There are a set of permissions that you can specify in a policy, which are denoted by the element "Action," or alternatively, "NotAction" for exclusion. Each of these elements maps to specific S3 REST API operations.

Table 1. Permissions applicable to buckets
Permissions S3 REST API operations
s3:CreateBucket PUT Bucket
s3:DeleteBucket DELETE Bucket
s3:DeleteBucketMetadataNotification DELETE Bucket metadata notification configuration
s3:DeleteBucketPolicy DELETE Bucket policy
s3:GetBucketAcl GET Bucket ACL
s3:GetBucketConsistency GET Bucket Consistency
s3:GetBucketLastAccessTime GET Bucket Last Access Time
s3:GetBucketLocation GET Bucket location
s3:GetBucketMetadataNotification GET Bucket metadata notification configuration
s3:GetBucketNotification GET Bucket notification
s3:GetBucketPolicy GET Bucket policy
s3:GetBucketReplication GET Bucket replication
s3:GetBucketVersioning GET Bucket versioning
s3:ListAllMyBuckets GET Service, GET Storage Usage
s3:ListBucket GET Bucket (List Objects), HEAD Bucket
s3:ListBucketMultipartUploads List Multipart Uploads
s3:ListBucketVersions GET Bucket versions
s3:PutBucketConsistency PUT Bucket Consistency
s3:PutBucketLastAccessTime PUT Bucket Last Access Time
s3:PutBucketMetadataNotification PUT Bucket metadata notification configuration
s3:PutBucketNotification PUT Bucket notification
s3:PutBucketPolicy PUT Bucket policy
s3:PutBucketReplication PUT Bucket replication
s3:PutBucketVersioning PUT Bucket versioning
Table 2. Permissions applicable to objects
Permissions S3 REST API operations
s3:AbortMultipartUpload Abort Multipart Upload
s3:DeleteObject DELETE Object, DELETE Multiple Objects
s3:DeleteObjectTagging DELETE Object Tagging
s3:DeleteObjectVersionTagging DELETE Object Tagging (a specific version of the object)
s3:DeleteObjectVersion DELETE Object (a specific version of the object)
s3:GetObject GET Object, HEAD Object
s3:GetObjectAcl GET Object ACL
s3:GetObjectTagging GET Object Tagging
s3:GetObjectVersionTagging GET Object Tagging (a specific version of the object)
s3:GetObjectVersion GET Object (a specific version of the object)
s3:ListMultipartUploadParts List Parts
s3:PutObject PUT Object, PUT Object - Copy, Initiate Multipart Upload, Complete Multipart Upload, uploading parts (Upload Part and Upload Part - Copy)
s3:PutObjectTagging PUT Object Tagging
s3:PutObjectVersionTagging PUT Object Tagging (a specific version of the object)
s3:PutOverwriteObject PUT Object, PUT Object - Copy, Complete Multipart Upload

Using the PutOverwriteObject permission

The PutOverwriteObject permission applies to operations that create or update objects (for example, PUT new objects or PUT Copy to update metadata). The setting of this permission determines whether the client can overwrite an object's data or metadata. Possible settings include Allow (client can overwrite an object) or Deny (client cannot overwrite an object). The default setting is Allow. When this permission is not present, the effect is the same as if Allow were set.

When set to Deny, this permission works as follows.

Important: If the current S3 policy allows overwrite, and the PutOverwriteObject permission is set to Deny, the client cannot overwrite an object's data or metadata. In addition, if the grid option Prevent Client Modify is set to Enabled, that setting overrides the setting of the PutOverwriteObject permission.

For an example using the PutOverwriteObject permission, see Example: PutOverwriteObject permission.

Specifying conditions in a policy

You can use conditions to allow policies to take effect based on request values.

Condition operators are categorized as follows:
  • String
  • Numeric
  • Boolean
  • IP address
  • Null check

Conditions use key-value pairs for evaluation. A Condition element can contain multiple conditions, and each condition can contain multiple key-value pairs. The condition block uses the following format:

Condition: {
     condition_type: {
          condition_key: condition_values

In the following example, the IpAddress condition uses the SourceIp condition key.


  "Condition": {
    "IpAddress": {
      "sgws:SourceIp": "54.240.143.0/24"
		...
},
		...
Table 3. Supported condition operators
Condition operators Description
StringEquals Compares a key to a string value based on exact equality (case sensitive).
StringNotEquals Compares a key to a string value based on exact non-equality (case sensitive).
StringEqualsIgnoreCase Compares a key to a string value based on exact equality (ignores case).
StringNotEqualsIgnoreCase Compares a key to a string value based on exact non-equality (ignores case).
StringLike Compares a key to a string value and provides access if there is an exact match (case sensitive). Can include * and ? wildcard characters.
StringNotLike Compares a key to a string value and provides access to all except the specified string (case sensitive). Can include * and ? wildcard characters.
NumericEquals Compares a key to a numeric value and provides access if there is an exact match.
NumericNotEquals Compares a key to a numeric value and provides access to all except the specified value.
NumericGreaterThan Compares a key to a numeric value and provides access if there is a "greater than" matching.
NumericGreaterThanEquals Compares a key to a numeric value and provides access if there is a "greater than or equals" matching.
NumericLessThan Compares a key to a numeric value and provides access if there is a "less than" matching.
NumericLessThanEquals Compares a key to a numeric value and provides access if there is a "less than or equals" matching.
Bool Compares a key to a Boolean value and provides access based on a "true or false" matching.
IpAddress Compares a key to a numeric value and provides access if there is a match to an IP or range of IP addresses.
NotIpAddress Compares a key to a numeric value and provides access to all addresses except the specified IP or range of IP addresses.
Null Checks if a condition key is present in the current request context.
Table 4. Supported condition keys
Category Applicable condition keys Description
IP operators sgws:SourceIp Will compare to the IP address from which the request was sent. Can be used for bucket or object operations.
Resource/Identity sgws:username Will compare to the sender's username from which the request was sent. Can be used for bucket or object operations.
S3:ListBucket

and

S3:ListBucketVersions permissions

s3:delimiter Will compare to the delimiter parameter specified in a GET Bucket or GET Bucket Object versions request.
s3:max-keys Will compare to the max-keys parameter specified in a GET Bucket or GET Bucket Object versions request.
s3:prefix Will compare to the prefix parameter specified in a GET Bucket or GET Bucket Object versions request.

Specifying variables in a policy

You can use variables in policies to populate policy information when it is available. You can use policy variables in the Resource element and in string comparisons in the Condition element.

In this example, the variable ${sgws:username} is part of the Resource element:

"Resource": "urn:sgws:s3:::bucket-name/home/${sgws:username}/*"

In this example, the variable ${sgws:username} is part of the condition value in the condition block:


  "Condition": {
    "StringLike": {
      "s3:prefix": "${sgws:username}/*"
		...
},
		...
Variable Description
${sgws:SourceIp} Uses the SourceIp key as the provided variable.
${sgws:username} Uses the username key as the provided variable.
${s3:prefix} Uses the service-specific prefix key as the provided variable.
${s3:max-keys} Uses the service-specific max-keys key as the provided variable.
${*} Special character. Uses the character as a literal * character.
${?} Special character. Uses the character as a literal ? character.
${$} Special character. Uses the character as a literal $ character.

Creating policies requiring special handling

Sometimes a policy can grant permissions that are dangerous for security or dangerous for continued operations, such as locking out the root user of the account. The StorageGRID Webscale S3 REST API implementation is less restrictive during policy validation than Amazon, but equally strict during policy evaluation.

Policy description Policy type Amazon behavior StorageGRID behavior
Deny self any permissions to the root account Bucket Valid and enforced, but root user account retains permission for all S3 bucket policy operations Same
Deny self any permissions to user/group Group Valid and enforced Same
Allow a foreign account group any permission Bucket Invalid principal Valid, but permissions for all S3 bucket policy operations return a 405 Method Not Allowed error when allowed by a policy
Allow a foreign account root or user any permission Bucket Valid, but permissions for all S3 bucket policy operations return a 405 Method Not Allowed error when allowed by a policy Same
Allow everyone permissions to all actions Bucket Valid, but permissions for all S3 bucket policy operations return a 405 Method Not Allowed error for the foreign account root and users Same
Deny everyone permissions to all actions Bucket Valid and enforced, but root user account retains permission for all S3 bucket policy operations Same
Principal is a non-existent user or group Bucket Invalid principal Valid
Resource is a non-existent S3 bucket Group Valid Same
Principal is a local group Bucket Invalid principal Valid
Policy grants a non-owner account (including anonymous accounts) permissions to PUT objects Bucket Valid. Objects are owned by the creator account, and the bucket policy does not apply. The creator account must grant access permissions for the object using object ACLs. Valid. Objects are owned by the bucket owner account. Bucket policy applies.