From 85178cdcd0af4e2646bdda3e2f916de42992a7d9 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Wed, 4 Nov 2026 08:14:29 -0800 Subject: [PATCH] S3 Tables and Vector Bucket security: policy condition validation and fail-safe stored policies --- S3-Tables-Security.md | 17 +++++++++++++++++ S3-Vector-Bucket-Security.md | 9 +++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/S3-Tables-Security.md b/S3-Tables-Security.md index 58b05bb..488e073 100644 --- a/S3-Tables-Security.md +++ b/S3-Tables-Security.md @@ -36,6 +36,23 @@ A policy document consists of a list of statements: - **Resource**: The resource ARN (supports wildcards). - **Condition**: (Optional) extra conditions for the rule. +### Policy validation + +`PutTableBucketPolicy` and `PutTablePolicy` refuse a policy with a condition that could not be enforced, answering `400 InvalidRequest`: + +| Policy content | Message | +|----------------|---------| +| An unsupported condition operator, e.g. `StringEqualsIfExists` | `condition operator "StringEqualsIfExists" is not supported` | +| An operator with no keys, e.g. `"StringEquals": {}` | `condition StringEquals needs at least one key` | +| A condition key the server never supplies, e.g. `aws:SourceIp` | `condition key "aws:SourceIp" is not supported in a table policy` | +| A value the operator cannot read: `null`, an object, an empty list, `NaN` or `±Inf`; a non-number for `Numeric*`, a non-RFC 3339 time for `Date*`, anything but `true`/`false` for `Bool` and `Null`, a non-IP/CIDR for `IpAddress` | `condition NumericLessThan on "..." needs values NumericLessThan can read (...)` | +| An Allow whose `Condition` is `null` | `an Allow statement's Condition must not be null` | +| A `Condition` written twice in one statement, or under two spellings (`Condition` and `condition`) | `a statement's Condition must be under one key, spelled Condition` | + +Supported condition keys: `s3tables:namespace`, `s3tables:tableName`, `s3tables:tableBucketName`, `s3tables:SSEAlgorithm`, `s3tables:KMSKeyArn`, `s3tables:StorageClass`, `aws:TagKeys`, and the tag keys `aws:RequestTag/`, `aws:ResourceTag/`, `s3tables:TableBucketTag/`, `s3vectors:VectorBucketTag/`. + +Policies stored by an earlier version that contain such a condition fail safe: an Allow statement with one never grants, and a Deny statement with one always applies. The server logs a warning naming the resource ARN. + --- ## Supported Actions diff --git a/S3-Vector-Bucket-Security.md b/S3-Vector-Bucket-Security.md index efeba5e..5d788b0 100644 --- a/S3-Vector-Bucket-Security.md +++ b/S3-Vector-Bucket-Security.md @@ -161,5 +161,10 @@ A `Deny` with a tag condition protects the resources carrying the tag. This stat | `NotResource` | `NotResource is not supported` | | A condition on a key other than those under [Tag conditions](#tag-conditions), e.g. `aws:SourceIp` | `condition key "aws:SourceIp" is not supported in a vector bucket policy` | | An unsupported condition operator, e.g. `StringEqualsIfExists` | `condition operator "StringEqualsIfExists" is not supported` | -| A condition value that is `null`, an object or an empty list | `condition StringEquals on "aws:ResourceTag/env" needs a string, number or boolean, or a non-empty list of them` | -| A condition field not spelled `Condition`, e.g. `condition` | `condition must be spelled Condition` | +| An operator with no keys, e.g. `"StringEquals": {}` | `condition StringEquals needs at least one key` | +| A value the operator cannot read: `null`, an object, an empty list, `NaN` or `±Inf`; a non-number for `Numeric*`, a non-RFC 3339 time for `Date*`, anything but `true`/`false` for `Bool` and `Null`, a non-IP/CIDR for `IpAddress` | `condition StringEquals on "aws:ResourceTag/env" needs values StringEquals can read (...)` | +| An Allow whose `Condition` is `null` | `an Allow statement's Condition must not be null` | +| `Statement`, `Effect` or `Condition` not spelled exactly that, e.g. `condition` | `condition must be spelled Condition` | +| A `Condition` written twice in one statement | `a statement's Condition must be under one key` | + +Policies stored by an earlier version that contain an unusable condition fail safe: an Allow statement with one never grants, and a Deny statement with one always applies.