Controlling access to MinIO AIStor Tables
MinIO AIStor Tables uses standard MinIO AIStor policy-based access control (PBAC) to define authorized actions on warehouses, namespaces, tables, and views. For more information about PBAC in MinIO AIStor, see Access Control with Policy Management
MinIO AIStor Tables policies use the s3tables: action namespace and the arn:aws:s3tables::: ARN scheme.
Because MinIO AIStor uses Warehouse terminology where AWS S3 Tables uses TableBucket, the warehouse-level action names support both spellings as equivalent aliases.
For example, s3tables:CreateWarehouse and s3tables:CreateTableBucket are interchangeable.
Access keys (service accounts) created through the Console or mc carry an embedded session policy that is evaluated together with the parent identity’s policy using an implicit deny.
The embedded policy is captured at the moment the access key is created and does not update when you later edit the parent user’s policy.
Use this order of operations:
- Create the user (or identity).
- Attach the MinIO AIStor Tables policy to that user.
- Then generate the access key for the user.
If you edit a user’s policy after an access key already exists, the existing key keeps its original (now stale) embedded policy and continues to be denied the new permissions. To fix an existing key, delete and recreate it so it inherits the current policy.
Resource reference
ARN patterns
MinIO AIStor Tables uses ARN patterns to identify resources in policies:
| ARN Pattern | Scope |
|---|---|
arn:aws:s3tables:::bucket/{warehouse} |
Specific warehouse |
arn:aws:s3tables:::bucket/* |
All warehouses |
arn:aws:s3tables:::bucket/{warehouse}/table/{uuid} |
Specific table in a warehouse |
arn:aws:s3tables:::bucket/{warehouse}/table/* |
All tables in a warehouse |
arn:aws:s3tables:::bucket/{warehouse}/view/{uuid} |
Specific view |
arn:aws:s3tables:::bucket/{warehouse}/view/* |
All views in a warehouse |
In a table or view ARN, the final segment is the resource’s stable UUID, not its name.
Use * in place of the UUID to match all tables or all views in the warehouse, or supply a specific UUID to scope a policy to one resource.
See Find a table’s UUID for how to look up a UUID.
There is no single ARN that covers both tables and views.
A warehouse-level policy that lists only .../table/* does not grant access to views, and vice versa.
To cover everything in a warehouse, list all three ARNs:
arn:aws:s3tables:::bucket/{warehouse}
arn:aws:s3tables:::bucket/{warehouse}/table/*
arn:aws:s3tables:::bucket/{warehouse}/view/*
The bare warehouse ARN is required for warehouse- and namespace-level actions such as s3tables:GetWarehouse, s3tables:ListNamespaces, and s3tables:ListTables.
Condition keys
Condition keys provide additional context for policy evaluation:
| Key | Description |
|---|---|
s3tables:namespace |
Filter by namespace name. |
s3tables:tableName |
Filter by table name. |
s3tables:viewName |
Filter by view name. |
s3tables:KMSKeyArn |
Filter by KMS key ARN for encryption operations. |
s3tables:SSEAlgorithm |
Filter by server-side encryption algorithm (AES256 or aws:kms). |
You can use standard condition operators such as StringEquals, StringLike, or StringNotEquals.
Scope to a specific table or view
There are two ways to restrict a policy to a specific table or view:
-
By name, using condition keys. Use a wildcard resource ARN (
.../table/*or.../view/*) and filter with thes3tables:namespace,s3tables:tableName, ors3tables:viewNamecondition keys. This approach is easy to read because it uses human-readable names, but the policy follows the name: if you rename the table, the policy no longer applies. -
By UUID, in the resource ARN. Put the resource UUID directly in the ARN (
.../table/{uuid}). This requires no condition evaluation and is the most precise option. Because the UUID is assigned at creation time and never changes, a UUID-based policy continues to apply across renames. The table or view must already exist before you can write a UUID-based policy. See Find a table’s UUID.
Actions
Actions control access to specific API operations.
Warehouse actions:
POST: Create a new warehouse.s3tables:CreateTableBucketis an equivalent alias for AWS S3 Tables compatibility (TableBucketis the AWS term for a warehouse).
DELETE: Delete a warehouse.
GET: Get warehouse details.
GET: List all warehouses.
Namespace actions:
POST: Create a new namespace.
DELETE: Delete a namespace.
GET: Get namespace details.HEAD: Check if namespace exists.
GET: List namespaces in a warehouse.
POST: Update namespace properties.
Table actions:
POST: Create a new table.
POST: Register an existing table.
DELETE: Delete a table.
GET: Get table metadata.
HEAD: Check if table exists.
GET: List tables in a namespace.
POST: Rename a table.
- Read table data.
- Write table data.
POST: Commit table updates (Iceberg commits) with/{warehouse}/namespaces/{namespace}/tables/{table}.POST: Commit multi-table transaction with/{warehouse}/transactions/commit.
- Retrieve a table’s current Iceberg metadata file location.
- Update (commit) a table’s metadata-location pointer.
Encryption actions:
- Get the encryption configuration for a warehouse.
- Set the encryption configuration for a warehouse.
- Delete the encryption configuration for a warehouse.
- Get the encryption configuration for a table.
- Set the encryption configuration for a table.
View actions
A CREATE OR REPLACE TABLE statement must first check whether a view of the same name already exists before it can replace the object.
That check requires s3tables: view permissions on the warehouse (.../view/*), in addition to the table permissions.
A plain CREATE TABLE or CREATE TABLE IF NOT EXISTS statement does not perform this check and needs only table permissions.
If users run CREATE OR REPLACE TABLE and receive access-denied errors, add s3tables:ListViews and s3tables:GetView for the .../view/* resource to their policy.
POST: Create a new view.
DELETE: Delete a view.
GET: Get view metadata.
HEAD: Check if view exists.
GET: List views in a namespace.
GET: Rename a view.
POST: Commit view updates.
Catalog actions
GET: Get catalog configuration.
- Access table metrics (MinIO extension).
Wildcard action
The wildcard action allows specifying all actions without listing each individually.
- Wildcard for all MinIO AIStor Table actions.
Policy examples
These examples demonstrate common access control patterns for MinIO AIStor Tables.
Read-only warehouse access
Grants read-only access to every namespace, table, and view in a warehouse, allowing users to query metadata, schemas, and data without making modifications.
Because the resource list includes both .../table/* and .../view/*, this policy covers tables and views.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadOnlyWarehouseAccess",
"Effect": "Allow",
"Action": [
"s3tables:GetWarehouse",
"s3tables:ListNamespaces",
"s3tables:GetNamespace",
"s3tables:ListTables",
"s3tables:GetTable",
"s3tables:GetTableData",
"s3tables:GetTableMetadataLocation",
"s3tables:ListViews",
"s3tables:GetView"
],
"Resource": [
"arn:aws:s3tables:::bucket/analytics",
"arn:aws:s3tables:::bucket/analytics/table/*",
"arn:aws:s3tables:::bucket/analytics/view/*"
]
}
]
}
Permissions granted:
- View warehouse metadata.
- List and view namespaces.
- List and view table and view schemas.
- Read table metadata, snapshots, and data.
Read-write access
Grants full read-write access to a warehouse, allowing users to create, modify, and delete namespaces, tables, and views.
The .../view/* resource and the view actions ensure that statements such as CREATE OR REPLACE TABLE succeed.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadWriteWarehouseAccess",
"Effect": "Allow",
"Action": [
"s3tables:GetWarehouse",
"s3tables:ListNamespaces",
"s3tables:CreateNamespace",
"s3tables:GetNamespace",
"s3tables:DeleteNamespace",
"s3tables:ListTables",
"s3tables:CreateTable",
"s3tables:GetTable",
"s3tables:GetTableData",
"s3tables:PutTableData",
"s3tables:UpdateTable",
"s3tables:UpdateTableMetadataLocation",
"s3tables:DeleteTable",
"s3tables:RenameTable",
"s3tables:ListViews",
"s3tables:CreateView",
"s3tables:GetView",
"s3tables:UpdateView",
"s3tables:DeleteView"
],
"Resource": [
"arn:aws:s3tables:::bucket/analytics",
"arn:aws:s3tables:::bucket/analytics/table/*",
"arn:aws:s3tables:::bucket/analytics/view/*"
]
}
]
}
Permissions granted:
- All read-only permissions.
- Create, update, and delete namespaces.
- Create, update, delete, and rename tables and views.
- Commit data changes to tables.
Namespace isolation
Restrict access to a single namespace within a warehouse, enabling multi-tenant scenarios where different teams share a warehouse.
The s3tables:namespace condition key scopes the wildcard resources to the sales namespace only.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "FullNamespaceAccess",
"Effect": "Allow",
"Action": [
"s3tables:*"
],
"Resource": [
"arn:aws:s3tables:::bucket/analytics",
"arn:aws:s3tables:::bucket/analytics/table/*",
"arn:aws:s3tables:::bucket/analytics/view/*"
],
"Condition": {
"StringEquals": {
"s3tables:namespace": "sales"
}
}
}
]
}
Permissions granted:
- Full access to only the
salesnamespace. - Create, read, update, and delete tables and views in the
salesnamespace.
Table access by name
Grant access to a single table identified by namespace and table name.
This policy uses the s3tables:namespace and s3tables:tableName condition keys against the .../table/* resource, so it always targets the events table in the analytics namespace.
If the table is renamed, this policy stops applying.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "TableAccessByName",
"Effect": "Allow",
"Action": [
"s3tables:GetTable",
"s3tables:GetTableData",
"s3tables:PutTableData",
"s3tables:UpdateTable"
],
"Resource": "arn:aws:s3tables:::bucket/analytics/table/*",
"Condition": {
"StringEquals": {
"s3tables:namespace": "analytics",
"s3tables:tableName": "events"
}
}
}
]
}
Table access by UUID
Grant access to a single table identified by its UUID.
Because the UUID never changes, this policy keeps applying even if the table is renamed.
Replace the example UUID with the value from mc table show ... --json.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "TableAccessByUUID",
"Effect": "Allow",
"Action": [
"s3tables:GetTable",
"s3tables:GetTableData",
"s3tables:PutTableData",
"s3tables:UpdateTable"
],
"Resource": "arn:aws:s3tables:::bucket/analytics/table/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
]
}
Warehouse administrator
Grant full administrative control over a warehouse and all of its tables and views with the s3tables:* wildcard action.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "WarehouseAdminAccess",
"Effect": "Allow",
"Action": "s3tables:*",
"Resource": [
"arn:aws:s3tables:::bucket/analytics",
"arn:aws:s3tables:::bucket/analytics/table/*",
"arn:aws:s3tables:::bucket/analytics/view/*"
]
}
]
}
Require SSE-S3 encryption
Deny any warehouse or table encryption configuration that does not use SSE-S3 (AES256).
This enforces server-side encryption by rejecting requests that specify a different algorithm.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RequireSSES3",
"Effect": "Deny",
"Action": [
"s3tables:PutWarehouseEncryption",
"s3tables:PutTableEncryption"
],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"s3tables:SSEAlgorithm": "AES256"
}
}
}
]
}
This deny statement overrides any allow statement, so users can only set encryption when they specify AES256 as the algorithm.
Implicit S3 action grants
MinIO AIStor Tables data actions implicitly grant the corresponding S3 actions needed to read and write the underlying Iceberg data and metadata files. You do not need to grant these S3 actions manually for normal table data access.
| MinIO AIStor Tables action | Implicitly grants S3 actions |
|---|---|
s3tables:GetTableData |
s3:GetObject, s3:ListMultipartUploadParts |
s3tables:PutTableData |
s3:PutObject, s3:AbortMultipartUpload, s3:ListBucket |
s3tables:DeleteTable |
s3:DeleteObject (to support DROP TABLE ... PURGE) |
These implicit grants apply only to paths within the table’s data directory. Standard S3 bucket permissions are still required to access objects outside of table data paths.
Policy examples for direct S3 access
The following sections show how to grant S3 API access for objects that fall outside table data paths.
Because the data actions in the preceding table already cover normal table read, write, and delete, you only need these explicit s3: permissions when applications access objects outside the table’s data directory.
Table data access (S3)
Grant S3 API access to objects in warehouse storage that are not covered by the implicit grants, such as objects outside table data paths. MinIO AIStor Tables stores both catalog metadata and table data in S3-compatible storage.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::analytics/*",
"arn:aws:s3:::analytics"
]
}
]
}
Permissions granted:
- Read objects (data files, metadata files).
- Write new objects (data files, manifests).
- Delete objects (for table maintenance).
- List bucket contents.
Important considerations:
- This policy is distinct from MinIO AIStor Tables catalog permissions.
- Normal table read, write, and delete do not require these explicit
s3:permissions, because thes3tables:data actions grant them implicitly within the table’s data directory. Grant theses3:permissions only for objects outside table data paths. - The bucket name in the S3 ARN should match the warehouse name.
- Data file paths follow the pattern:
s3://{warehouse}/{namespace}/{table}/data/. - Metadata file paths follow:
s3://{warehouse}/.aistor-tables/{namespace}/{table}/metadata/.
Combine policies
Applications that also need direct S3 access to objects outside table data paths can combine catalog permissions with explicit s3: permissions in a single policy.
For normal table data access, the catalog s3tables: data actions already grant the required S3 actions implicitly, so a separate s3: statement is not needed.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CatalogOperations",
"Effect": "Allow",
"Action": [
"s3tables:GetWarehouse",
"s3tables:ListNamespaces",
"s3tables:GetNamespace",
"s3tables:ListTables",
"s3tables:GetTable",
"s3tables:UpdateTable"
],
"Resource": [
"arn:aws:s3tables:::bucket/analytics",
"arn:aws:s3tables:::bucket/analytics/table/*"
]
},
{
"Sid": "DataPlaneAccess",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::analytics/*",
"arn:aws:s3:::analytics"
]
}
]
}
This combined policy allows the following actions:
- Read table metadata and schemas from the catalog.
- Commit new snapshots after writes.
- Read and write data files in S3 storage.
AIStor Table Sharing (Delta Sharing) administration
Administering AIStor Table Sharing (Delta Sharing) uses the admin:DeltaSharing* admin actions to create and manage shares and tokens.
These admin actions are separate from the s3tables: catalog actions and from the data-plane s3: actions that recipients need to read the underlying objects.
The admin:DeltaSharing* actions must be granted with a Resource field.
A share also reads the shared objects through the S3 API, so the policy must include real s3: actions on the buckets being shared.
Use concrete S3 action names such as s3:GetObject and s3:ListBucket.
Wildcard forms like s3:*Object are not expanded — they must match a real S3 action name or they are silently ignored, leaving the share unable to read data.
The following policy grants full AIStor Table Sharing administration and read access to every bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DeltaSharingAdmin",
"Effect": "Allow",
"Action": [
"admin:DeltaSharing"
],
"Resource": [
"arn:aws:s3:::*"
]
},
{
"Sid": "DeltaSharingDataAccess",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
To restrict which buckets can be shared, narrow the Resource lists to the specific buckets:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DeltaSharingAdmin",
"Effect": "Allow",
"Action": [
"admin:DeltaSharing"
],
"Resource": [
"arn:aws:s3:::hr-data",
"arn:aws:s3:::hr-data/*"
]
},
{
"Sid": "DeltaSharingDataAccess",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::hr-data",
"arn:aws:s3:::hr-data/*"
]
}
]
}
For more information about configuring sharing, see Controlling access to shared tables.
Find a table’s UUID
UUID-based table and view ARNs (arn:aws:s3tables:::bucket/{warehouse}/table/{uuid}) require the table’s UUID.
The UUID is assigned when the table is created and remains stable across renames, which is what makes UUID-based ARNs durable.
There is no mc table info command for this; info is an alias of mc table show.
Run mc table show with the --json global flag and read the table_uuid field from the output:
mc table show myaistor analytics prod sales_data --json
The JSON output includes a table_uuid field with the value you need:
{
"status": "success",
"table": "sales_data",
"namespace": "prod",
"warehouse": "analytics",
"location": "s3://analytics/...",
"format_version": 2,
"table_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
In the default (non-JSON) output, the same value appears on the Table UUID: line.
Plug the value into a /table/{uuid} ARN to scope a policy to that specific table:
arn:aws:s3tables:::bucket/analytics/table/a1b2c3d4-e5f6-7890-abcd-ef1234567890
For a view, use the corresponding /view/{uuid} ARN.