S3 Vector Bucket Security
Who may call the S3 Vectors API, and how to grant access with a vector bucket policy. Vector bucket policies use the same policy evaluation as S3 Tables Security, with s3vectors: actions.
Authentication
Requests are signed with SigV4 for the service s3vectors, with an identity from the S3 configuration (-s3.config, see S3 Credentials). An unknown access key is refused with 403 AccessDenied: authentication failed.
On a SeaweedFS without identities, every request is accepted whatever its access key, and weed-vector needs no credentials (see S3 Vector Bucket#quick-start). Configure identities for anything beyond a trial.
Who can do what
Access comes from two places: the actions listed for the identity in the S3 configuration, and the bucket's policy.
| Caller | Access |
|---|---|
An identity with the Admin action in the admin account: the identity named admin, or one configured with "account": {"id": "admin"} |
Everything on every vector bucket. Bucket policies do not apply to it, not even a Deny. |
Any other identity with the Admin action, or with s3vectors:* |
Can create vector buckets and use every vector bucket, unless a bucket policy denies it. |
An identity with specific actions such as s3vectors:QueryVectors |
Those operations on every vector bucket, unless a bucket policy denies them. s3vectors:CreateVectorBucket lets it create buckets. |
An identity with actions scoped to one bucket, such as s3vectors:QueryVectors:team-a or s3vectors:*:team-a |
Those operations on that bucket and its indexes only, unless its policy denies them. A scoped action never lets it create a bucket. |
| The bucket's owner: the account that created it | Everything on that bucket, unless its policy denies it. An identity without an account is its own account; every identity in the creating account owns the bucket. |
| Any other identity | Only what the bucket's policy allows. |
Identity actions look like this in the -s3.config file:
{
"identities": [
{"name": "search", "credentials": [{"accessKey": "search", "secretKey": "search-secret"}],
"actions": ["s3vectors:GetVectors", "s3vectors:QueryVectors"]}
]
}
search can then call GetVectors and QueryVectors on every vector bucket, and nothing else.
- The
Read,WriteandListactions do not grant anything on vector buckets. An identity with only those gotAccessDeniedExceptionfor every vector operation, includingCreateVectorBucket. ListVectorBucketsreturns only the buckets on which the caller hass3vectors:ListVectorBucketsors3vectors:GetVectorBucket, scoped ones included: an identity withs3vectors:*:team-bliststeam-b. Thesearchidentity above can query every bucket but lists none.
Vector bucket policies
Attach a policy with PutVectorBucketPolicy. The caller needs s3vectors:PutVectorBucketPolicy: an admin identity has it, and so does an identity the bucket's current policy grants it.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {"AWS": "reader"},
"Action": [
"s3vectors:GetVectorBucket",
"s3vectors:ListIndexes",
"s3vectors:GetIndex",
"s3vectors:GetVectors",
"s3vectors:ListVectors",
"s3vectors:QueryVectors"
],
"Resource": [
"arn:aws:s3vectors:us-east-1:000000000000:bucket/team-a",
"arn:aws:s3vectors:us-east-1:000000000000:bucket/team-a/index/*"
]
}
]
}
s3v.put_vector_bucket_policy(vectorBucketName="team-a", policy=json.dumps(policy))
With this policy, identity reader can list the bucket, its indexes and their vectors, and query them; PutVectors and DeleteIndex still get AccessDeniedException.
- Principal: the caller's account, as
{"AWS": "reader"}or a list, or"*"for every authenticated identity. An identity's account is its name when it has noaccountin the S3 configuration, and itsaccount.idotherwise. A statement that names an identity with anaccountby its name does not match it, not even aDeny. - Action:
s3vectors:followed by the operation name, e.g.s3vectors:QueryVectors, ors3vectors:*. Each operation of the S3 Vectors API checks the action of the same name. ACreateVectorBucketorCreateIndexwithtagsalso needss3vectors:TagResource. - Resource: the bucket ARN, an index ARN, or a wildcard such as
arn:aws:s3vectors:us-east-1:000000000000:bucket/team-a/index/*. ARNs always use regionus-east-1and account000000000000. - Deny wins: a matching
Denyoverrides anyAllow, the owner's access and the identity's own actions. Only an identity with theAdminaction in theadminaccount is exempt.
Example: let every identity query one index, but shut out writer entirely:
{
"Version": "2012-10-17",
"Statement": [
{"Effect": "Allow", "Principal": "*", "Action": "s3vectors:QueryVectors",
"Resource": "arn:aws:s3vectors:us-east-1:000000000000:bucket/team-a/index/idx"},
{"Effect": "Deny", "Principal": {"AWS": "writer"}, "Action": "s3vectors:*", "Resource": "*"}
]
}
An identity with no vector grants of its own can then call QueryVectors on idx, but not GetVectors; writer gets AccessDeniedException even for QueryVectors.
GetVectorBucketPolicy returns the document as it was stored; with no policy it returns NotFoundException. DeleteVectorBucketPolicy removes it, and with it every access the policy granted.
Tag conditions
Tag conditions are on master since #12351 and not yet in a release: 4.52 rejects any Condition in a vector bucket policy with ValidationException.
A statement in a vector bucket policy can have a Condition on the S3 Vectors API#tags of the bucket or index, or on the tags a request sets:
| Condition key | Compared with |
|---|---|
aws:ResourceTag/<key> |
The bucket's tag on a bucket request. On a request that names an index, the index's own tag. |
s3vectors:VectorBucketTag/<key> |
The bucket's tag, on bucket and index requests alike. |
aws:RequestTag/<key> |
The tag that TagResource or CreateIndex sets. |
aws:TagKeys |
The keys that TagResource or CreateIndex sets, or that UntagResource removes. |
Example, on bucket team-a tagged env=prod, whose index idx is tagged stage=live:
{
"Version": "2012-10-17",
"Statement": [
{"Effect": "Allow", "Principal": {"AWS": "reader"}, "Action": "s3vectors:GetIndex",
"Resource": "arn:aws:s3vectors:us-east-1:000000000000:bucket/team-a/index/*",
"Condition": {"StringEquals": {"aws:ResourceTag/stage": "live"}}},
{"Effect": "Allow", "Principal": {"AWS": "reader"}, "Action": "s3vectors:QueryVectors",
"Resource": "arn:aws:s3vectors:us-east-1:000000000000:bucket/team-a/index/*",
"Condition": {"StringEquals": {"s3vectors:VectorBucketTag/env": "prod"}}},
{"Effect": "Allow", "Principal": {"AWS": "writer"}, "Action": "s3vectors:TagResource",
"Resource": "arn:aws:s3vectors:us-east-1:000000000000:bucket/team-a/index/*",
"Condition": {"StringEquals": {"aws:RequestTag/team": "search"},
"ForAllValues:StringEquals": {"aws:TagKeys": ["team"]}}}
]
}
readercan callGetIndexonidx. On an index withoutstage=liveit getsAccessDeniedException.readercan query every index in the bucket. Once the bucket is retaggedenv=dev, its next query getsAccessDeniedException.writercan tag an index with{"team": "search"}. Tagging with{"team": "other"}, or with{"team": "search", "env": "dev"}, getsAccessDeniedException.
A Deny with a tag condition protects the resources carrying the tag. This statement keeps every index tagged protected=true from being deleted, by any identity except the admin described above:
{"Effect": "Deny", "Principal": "*", "Action": "s3vectors:DeleteIndex",
"Resource": "arn:aws:s3vectors:us-east-1:000000000000:bucket/team-a/index/*",
"Condition": {"StringEquals": {"aws:ResourceTag/protected": "true"}}}
- Conditions apply in bucket policies only. The actions of an identity in the S3 configuration have no conditions.
CreateVectorBucketcannot be limited by tags, because a new bucket has no policy yet.- A tag that is not set matches no value. A statement that allows
CreateIndexonly withaws:RequestTag/team=searchalso refuses aCreateIndexwithout tags. - A tag change applies from the next request.
- The operators are the ones in S3 Policy Conditions#supported-condition-operators, including the
ForAllValues:andForAnyValue:forms. TheIfExistsforms are rejected. - Condition keys are case-sensitive:
aws:resourcetag/envis rejected.
The engine's identity
weed-vector reads and writes every index's files with the identity passed in its --storage-option flags, whoever called the API. Authorization happens in the gateway before the engine is called. In our tests the engine used an identity with the Admin action. On a SeaweedFS without identities it needs none.
Rejected policies
PutVectorBucketPolicy refuses, with ValidationException, a policy that it could not enforce:
| Policy content | Message |
|---|---|
An action of another service, e.g. s3tables:GetTable or s3:GetObject |
action "s3:GetObject" is not enforceable in a vector bucket policy |
A resource ARN of another service, e.g. arn:aws:s3tables:... |
resource "arn:aws:s3tables:..." is not enforceable in a vector bucket policy |
NotAction |
NotAction is not supported |
NotResource |
NotResource is not supported |
A condition on a key other than those under 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 |
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.
Introduction
- Quick Start with weed mini
- Simplest S3 Bucket and User Setup
- Components
- Blob Store Architecture
- Getting Started
- Production Setup
- A typical step‐by‐step example
- Benchmarks
- FAQ
- Applications
API
Configuration
- Replication
- Store file with a Time To Live
- Failover Master Server
- Erasure coding for warm storage
- EC Bitrot Detection
- Server Startup via Systemd
- Environment Variables
Filer
- Filer Setup
- Directories and Files
- File Operations Quick Reference
- Data Structure for Large Files
- Filer Data Encryption
- Filer Commands and Operations
- Filer JWT Use
- TUS Resumable Uploads
Filer Stores
- Filer Cassandra Setup
- Filer Redis Setup
- Super Large Directories
- Path-Specific Filer Store
- Choosing a Filer Store
- Customize Filer Store
Management
Advanced Filer Configurations
- Migrate to Filer Store
- Migrate Between Filer Stores
- Add New Filer Store
- Filer Store Replication
- Filer Active Active cross cluster continuous synchronization
- Filer as a Key-Large-Value Store
- Path Specific Configuration
- Filer Change Data Capture
- Filer Operation Serialization
FUSE Mount
- Mount on Windows
- FIO benchmark
- fstab and systemd mount
- POSIX Compliance
- Distributed POSIX Locks
- P2P reading in weed mount
- Mount over the Internet
WebDAV
SFTP Server
Cloud Drive
- Cloud Drive Benefits
- Cloud Drive Architecture
- Configure Remote Storage
- Azure Blob Storage Authentication
- Mount Remote Storage
- Cache Remote Storage
- Cloud Drive Quick Setup
- Gateway to Remote Object Storage
AWS S3 API
- Amazon S3 API
- Supported APIs vs Minio
- S3 Lifecycle
- S3 Lifecycle vs Volume TTL
- S3 Conditional Operations
- S3 CORS
- S3 Object Lock and Retention
- S3 Object Versioning
- S3 RenameObject
- S3 API Benchmark
- S3 API FAQ
- S3 Bucket Quota
- S3 Rate Limiting
- S3 API Audit log
- S3 Nginx Proxy
- Docker Compose for S3
- Image Gateway
S3 Table Bucket
- S3 Table Bucket
- S3 Table Bucket Commands
- S3 Tables Security
- SeaweedFS Iceberg Catalog
- Iceberg REST Catalog API
- Iceberg Table Maintenance
- SeaweedFS Lance Catalog
- Lance Maintenance Worker
S3 Vector Bucket
Iceberg Integrations
- Spark Iceberg Integration
- Trino Iceberg Integration
- Dremio Iceberg Integration
- DuckDB Iceberg Integration
- Doris Iceberg Integration
- RisingWave Iceberg Integration
- Lakekeeper Iceberg Integration
- OLake Go Iceberg Integration
Lance Integrations
S3 Authentication & IAM
- S3 Configuration - Start Here
- S3 Credentials (
-s3.config) - OIDC Integration (
-s3.iam.config) - Kubernetes ServiceAccount Authentication (IRSA-style)
- S3 Policy Variables
- S3 Policy Conditions
- S3 Bucket Policies
- Amazon IAM API
- AWS IAM CLI
- weed shell - Shell IAM Commands
Server-Side Encryption
S3 Client Tools
- AWS CLI with SeaweedFS
- s3cmd with SeaweedFS
- rclone with SeaweedFS
- restic with SeaweedFS
- nodejs with Seaweed S3
Machine Learning
HDFS
- Hadoop Compatible File System
- run Spark on SeaweedFS
- run HBase on SeaweedFS
- Run Trino on SeaweedFS
- Hadoop Benchmark
- HDFS via S3 connector
Replication and Backup
- Async Replication to another Filer [Deprecated]
- Async Backup
- Async Filer Metadata Backup
- Async Replication to Cloud [Deprecated]
- Kubernetes Backups and Recovery with K8up
Metadata Change Events
Messaging
- Structured Data Lake with SMQ and SQL
- Seaweed Message Queue
- SQL Queries on Message Queue
- SQL Quick Reference
- PostgreSQL-compatible Server weed db
- Pub-Sub to SMQ to SQL
- Kafka to Kafka Gateway to SMQ to SQL
Use Cases
Operations
- System Metrics
- weed shell
- Data Backup
- Deployment to Kubernetes and Minikube
- Helm Chart Recipes
- Deployment with seaweed-up
Rust Volume Server
Advanced
- Large File Handling
- Optimization
- Optimization for Many Small Buckets
- Volume Management
- Tiered Storage
- Cloud Tier
- Cloud Monitoring
- Load Command Line Options from a file
- SRV Service Discovery
- Volume Files Structure
Security
- Security Overview
- Security Configuration
- Cryptography and FIPS Compliance
- Run Blob Storage on Public Internet