Skip to content

feat(dynamodb): cross-account table and stream access through ARNs - #2532

Merged
vieiralucas merged 6 commits into
mainfrom
feat/dynamodb-cross-account
Sep 14, 2026
Merged

vieiralucas merged 6 commits into
mainfrom
feat/dynamodb-cross-account

Conversation

@vieiralucas

@vieiralucas vieiralucas commented Sep 14, 2026

Copy link
Copy Markdown
Member

Summary

DynamoDB table ARNs naming another account now reach that account's table, the way AWS cross-account access with resource-based policies works. Before this, resolve_table_name dropped the ARN's account and region, so a request always acted on the caller's own table of the same name.

  • Supported cross-account operations (the AWS list): GetItem, PutItem, UpdateItem, DeleteItem, Query, Scan, BatchGetItem, BatchWriteItem, TransactGetItems, TransactWriteItems, DescribeTable, UpdateTable, DeleteTable, ListTagsOfResource, TagResource, UntagResource, and the Streams DescribeStream, GetShardIterator, GetRecords. A single-table request is served in the owner's account.
  • Batches and transactions resolve each table's owner account, so one request can mix tables from several accounts, including same-named tables. A transaction looks up, validates, snapshots, reverts and appends stream records per (account, table), so it stays atomic across accounts. Duplicate-item detection covers both accounts, and the idempotency token stays with the caller.
  • Not found: any other operation (PartiQL, backups, PITR, TTL, Kinesis streaming, resource-policy operations, imports/exports, ...) never finds another account's table, and it is never switched into that account. An ARN naming a region other than the request's is not found for any operation. Each error uses the code the operation declares (ResourceNotFoundException, TableNotFoundException, BackupNotFoundException, ...). ListBackups/ListExports/ListImports treat the table only as a filter, so a foreign table matches nothing; ListBackups now compares a table ARN filter as a whole ARN.
  • IAM: the table authorized is the one the handler serves (the owner's table for cross-account operations). The dispatch evaluator already combines identity and resource policies with AND across accounts, so a cross-account caller needs both the table's (or stream's) resource policy and their own identity policy. dynamodb:LeadingKeys / dynamodb:Attributes for batches and transactions count only entries sent to that account's table.

Test plan

  • Unit: ARN scope parsing, per-operation reference checks and error codes, owner resolution; cross-account item ops, batches, transactions (commit, cross-account revert, condition cancel, name vs own-ARN duplicate), unsupported ops and other regions, list filters with backups in both accounts; Streams read in another account; condition keys for same-named tables in two accounts
  • e2e dynamodb_cross_account.rs (strict IAM + SigV4, three accounts): denied without a resource policy; allowed with one for GetItem/PutItem/DescribeTable/Query/cross-account BatchWriteItem + BatchGetItem/TransactWriteItems; DeleteItem not granted is denied; an unnamed account is denied; a user without an identity policy is denied; unsupported ops and another region find no table; stream reads need the stream's own policy
  • cargo test -p fakecloud-dynamodb (506), e2e dynamodb, dynamodb_streams, iam_enforcement_dynamodb, iam_enforcement_abac, multi_account, dynamodb_persistence
  • Conformance probe: dynamodb 2163/2163
  • Docs: services/dynamodb.md (ARN bullet rewritten), reference/security.md, reference/limitations.md (DynamoDB policies and ABAC were missing). No SDK or introspection surface change.

Summary by cubic

Adds cross-account DynamoDB table and stream access through ARNs, matching AWS's resource-policy model. Table ARNs naming another account now reach that account's table for the supported operations, instead of being resolved to the caller's own table of the same name.

New Features

  • Supported operations: GetItem, PutItem, UpdateItem, DeleteItem, Query, Scan, BatchGetItem, BatchWriteItem, TransactGetItems, TransactWriteItems, DescribeTable, UpdateTable, DeleteTable, tagging operations, and stream reads (DescribeStream, GetShardIterator, GetRecords). Single-table requests are served in the owner's account.
  • Batches and transactions resolve each table's owner account, so one request can mix tables from several accounts, including same-named tables. Transactions remain atomic across accounts.
  • Operations without cross-account support (PartiQL, backups, TTL, resource-policy operations, etc.) and ARNs naming another region return the operation's declared not-found error. ListBackups/ListExports/ListImports treat the table as a filter, so foreign tables match nothing.
  • With IAM enforcement, cross-account access requires both the caller's identity policy and the table's (or stream's) resource policy. dynamodb:LeadingKeys and dynamodb:Attributes for batches and transactions count only entries sent to that account's table.

Written for commit 851a54d. Summary will update on new commits.

Review in cubic

- A table ARN naming another account reaches that account's table for the
  operations AWS supports cross-account: item operations, Query, Scan,
  batches, transactions, DescribeTable/UpdateTable/DeleteTable, tagging,
  and the Streams DescribeStream/GetShardIterator/GetRecords
- Batches and transactions resolve each table's owner account; a
  transaction snapshots and reverts per account, so it stays atomic
- Other operations do not find another account's table, and an ARN naming
  another region is not found for any operation
- IAM authorizes the table the handler serves, so the table's resource
  policy combines with the caller's identity policy cross-account
- Unit and two-account strict-mode e2e tests; docs
…e's account

A batch or transaction can name same-named tables in two accounts; each
table's dynamodb:LeadingKeys and dynamodb:Attributes now come only from the
entries sent to that account's table.
ListBackups, ListExports and ListImports take a table only as a filter and
model no not-found error, so another account's or region's table matches
nothing instead of failing the call.
…ount

The owner-account switch now applies only to operations with cross-account
support. ListBackups's TableName filter naming another account's table no
longer switches the listing into that account.
A TableName ARN naming another account's or region's table no longer
matches the caller's same-named table's backups.
@vieiralucas
vieiralucas merged commit 47c9257 into main Sep 14, 2026
157 checks passed
@vieiralucas
vieiralucas deleted the feat/dynamodb-cross-account branch September 14, 2026 20:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant