Bucket policy examples
Copy-ready bucket policy JSON for the Quake AI S3-compatible gateway. Substitute $tenant (your OpenStack project ID), $bucket (bucket name), TENANT_ID, BUCKET_NAME, and USER_NAME before you apply a policy with aws s3api put-bucket-policy.
For procedural steps (create credentials, upload objects, grant ACLs), see the object storage how-to guides.
Anonymous URL shape#
Anonymous URLs against the Quake AI S3 gateway use the tenant-prefixed shape:
https://object.<region>.rumble.cloud/<tenant>:<bucket>/<key>The plain https://object.<region>.rumble.cloud/<bucket>/<key> URL that vanilla AWS S3 uses returns 404 Not Found against Quake AI's multi-tenant Swift-backed S3 gateway because the gateway routes by tenant prefix.
Find your tenant ID#
The tenant ID is your OpenStack project ID:
openstack token issue -f value -c project_idOr, if you have the project name:
openstack project show -f value -c id "$OS_PROJECT_NAME"Worked example#
Given tenant 77e78aa9c0e04ed0b9d1a3f0626a8c4d, bucket my-public-bucket, key hello.txt, region us-east-1:
https://object.us-east-1.rumble.cloud/77e78aa9c0e04ed0b9d1a3f0626a8c4d:my-public-bucket/hello.txtVerify with curl (no credentials):
curl -sI "https://object.us-east-1.rumble.cloud/77e78aa9c0e04ed0b9d1a3f0626a8c4d:my-public-bucket/hello.txt"A 200 OK confirms the policy is applied and the URL shape is correct. A 404 Not Found usually means the <tenant>: prefix is missing; a 403 Forbidden usually means the policy is not applied or does not match the requested object.
Public read#
Lets unauthenticated clients fetch any object in the bucket with HTTP GET.
{
"Version": "2012-10-17",
"Statement":[
{
"Sid": "PublicReadGetObject",
"Principal": "*",
"Effect":"Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3::$tenant:$bucket/*"
]
}
]
}Apply:
aws s3api put-bucket-policy \
--bucket my-bucket \
--policy file://public-read-policy.json \
--endpoint-url "$S3_ENDPOINT"Restricted public read (prefix)#
Same anonymous GET access, scoped to one prefix. Replace the * after the bucket name with the prefix (for example arn:aws:s3::$tenant:$bucket/public/*).
{
"Version": "2012-10-17",
"Statement":[
{
"Sid": "PublicReadGetObject",
"Principal": "*",
"Effect":"Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3::$tenant:$bucket/*"
]
}
]
}IP whitelist#
Deny access except from one IP address#
Denies requests whose source IP is not 1.2.3.4/32. Replace the CIDR and YourBucket with your values.
{
"Version": "2012-10-17",
"Id": "IpWhitelist",
"Statement": [
{
"Sid": "IpAllow",
"Effect": "Deny",
"Principal": "*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp":"1.2.3.4/32"
}
},
"Resource": [
"arn:aws:s3:::YourBucket",
"arn:aws:s3:::YourBucket/*"
]
}
]
}Allow public read only from one IP range#
Allows anonymous s3:GetObject requests only from the specified IP or CIDR range. Uses Principal: "*", so anonymous URLs need the tenant-prefixed shape in Anonymous URL shape.
{
"Id": "SourceIP",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SourceIP",
"Action": "s3:GetObject",
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::YourBucket",
"arn:aws:s3:::YourBucket/*"
],
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"1.2.3.4/32"
]
}
},
"Principal": "*"
}
]
}Read-only principal#
Applies to authenticated principal arn:aws:iam::TENANT_ID:user/USER_NAME. The user accesses the bucket with their own S3 credentials, not anonymous URLs.
{
"Version": "2012-10-17",
"Id": "ReadOnlyPolicy",
"Statement": [
{
"Sid": "AllowGet",
"Effect": "Allow",
"Principal": {
"AWS": ["arn:aws:iam::TENANT_ID:user/USER_NAME"]
},
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3::TENANT_ID:BUCKET_NAME",
"arn:aws:s3::TENANT_ID:BUCKET_NAME/*"
]
},
{
"Sid": "DenyPut",
"Effect": "Deny",
"Principal": {
"AWS": ["arn:aws:iam::TENANT_ID:user/USER_NAME"]
},
"Action": [
"s3:DeleteBucketPolicy",
"s3:DeleteBucket",
"s3:DeleteBucketWebsite",
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:DeleteReplicationConfiguration",
"s3:PutAccelerateConfiguration",
"s3:PutBucketAcl",
"s3:PutBucketCORS",
"s3:PutBucketLogging",
"s3:PutBucketNotification",
"s3:PutBucketPolicy",
"s3:PutBucketRequestPayment",
"s3:PutBucketTagging",
"s3:PutBucketVersioning",
"s3:PutBucketWebsite",
"s3:PutLifecycleConfiguration",
"s3:PutObjectAcl",
"s3:PutObject",
"s3:PutObjectVersionAcl",
"s3:PutReplicationConfiguration",
"s3:RestoreObject"
],
"Resource": [
"arn:aws:s3::TENANT_ID:BUCKET_NAME",
"arn:aws:s3::TENANT_ID:BUCKET_NAME/*"
]
}
]
}User-reversible read-only principal#
Remove any lifecycle policies before you apply this policy, unless you want them to keep running. Keeps PutBucketPolicy and DeleteBucketPolicy in the Allow statement so the named principal can reverse the policy.
{
"Version": "2012-10-17",
"Id": "ReadOnlyPolicy",
"Statement": [
{
"Sid": "AllowGet",
"Effect": "Allow",
"Principal": {
"AWS": ["arn:aws:iam::TENANT_ID:user/USER_NAME"]
},
"Action": [
"s3:DeleteBucketPolicy",
"s3:PutBucketPolicy",
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3::TENANT_ID:BUCKET_NAME",
"arn:aws:s3::TENANT_ID:BUCKET_NAME/*"
]
},
{
"Sid": "DenyPut",
"Effect": "Deny",
"Principal": {
"AWS": ["arn:aws:iam::TENANT_ID:user/USER_NAME"]
},
"Action": [
"s3:DeleteBucket",
"s3:DeleteBucketWebsite",
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:DeleteReplicationConfiguration",
"s3:PutAccelerateConfiguration",
"s3:PutBucketAcl",
"s3:PutBucketCORS",
"s3:PutBucketLogging",
"s3:PutBucketNotification",
"s3:PutBucketRequestPayment",
"s3:PutBucketTagging",
"s3:PutBucketVersioning",
"s3:PutBucketWebsite",
"s3:PutLifecycleConfiguration",
"s3:PutObjectAcl",
"s3:PutObject",
"s3:PutObjectVersionAcl",
"s3:PutReplicationConfiguration",
"s3:RestoreObject"
],
"Resource": [
"arn:aws:s3::TENANT_ID:BUCKET_NAME",
"arn:aws:s3::TENANT_ID:BUCKET_NAME/*"
]
}
]
}