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.

Create the user and policy before generating the access key

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:

  1. Create the user (or identity).
  2. Attach the MinIO AIStor Tables policy to that user.
  3. 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.

Tables and views are separate resource types

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 the s3tables:namespace, s3tables:tableName, or s3tables:viewName condition 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:

# s3tables:CreateWarehouse action
  • POST: Create a new warehouse.
  • s3tables:CreateTableBucket is an equivalent alias for AWS S3 Tables compatibility (TableBucket is the AWS term for a warehouse).
# s3tables:DeleteWarehouse action
  • DELETE: Delete a warehouse.
# s3tables:GetWarehouse action
  • GET: Get warehouse details.
# s3tables:ListWarehouses action
  • GET: List all warehouses.

Namespace actions:

# s3tables:CreateNamespace action
  • POST: Create a new namespace.
# s3tables:DeleteNamespace action
  • DELETE: Delete a namespace.
# s3tables:GetNamespace action
  • GET: Get namespace details.
  • HEAD: Check if namespace exists.
# s3tables:ListNamespaces action
  • GET: List namespaces in a warehouse.
# s3tables:UpdateNamespaceProperties action
  • POST: Update namespace properties.

Table actions:

# s3tables:CreateTable action
  • POST: Create a new table.
# s3tables:CreateTable action
  • POST: Register an existing table.
# s3tables:DeleteTable action
  • DELETE: Delete a table.
# s3tables:GetTable action
  • GET: Get table metadata.
# s3tables:GetTable action
  • HEAD: Check if table exists.
# s3tables:ListTables action
  • GET: List tables in a namespace.
# s3tables:RenameTable action
  • POST: Rename a table.
# s3tables:GetTableData action
  • Read table data.
# s3tables:PutTableData action
  • Write table data.
# s3tables:UpdateTable action
  • POST: Commit table updates (Iceberg commits) with /{warehouse}/namespaces/{namespace}/tables/{table}.
  • POST: Commit multi-table transaction with /{warehouse}/transactions/commit.
# s3tables:GetTableMetadataLocation action
  • Retrieve a table’s current Iceberg metadata file location.
# s3tables:UpdateTableMetadataLocation action
  • Update (commit) a table’s metadata-location pointer.

Encryption actions:

# s3tables:GetWarehouseEncryption action
  • Get the encryption configuration for a warehouse.
# s3tables:PutWarehouseEncryption action
  • Set the encryption configuration for a warehouse.
# s3tables:DeleteWarehouseEncryption action
  • Delete the encryption configuration for a warehouse.
# s3tables:GetTableEncryption action
  • Get the encryption configuration for a table.
# s3tables:PutTableEncryption action
  • Set the encryption configuration for a table.

View actions

CREATE OR REPLACE TABLE requires view permissions

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.

# s3tables:CreateView action
  • POST: Create a new view.
# s3tables:DeleteView action
  • DELETE: Delete a view.
# s3tables:GetView action
  • GET: Get view metadata.
# s3tables:GetView action
  • HEAD: Check if view exists.
# s3tables:ListViews action
  • GET: List views in a namespace.
# s3tables:RenameView action
  • GET: Rename a view.
# s3tables:UpdateView action
  • POST: Commit view updates.

Catalog actions

# s3tables:GetConfig action
  • GET: Get catalog configuration.
# s3tables:TableMetrics action
  • Access table metrics (MinIO extension).

Wildcard action

The wildcard action allows specifying all actions without listing each individually.

# s3tables:* action
  • 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 sales namespace.
  • Create, read, update, and delete tables and views in the sales namespace.

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 the s3tables: data actions grant them implicitly within the table’s data directory. Grant these s3: 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.

Delta Sharing admin actions require a Resource and concrete S3 actions

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.