aws-dynamodb-restore-pitr-read

dynamodb:RestoreTableToPointInTime creates a new table from PITR; reading it requires separate GetItem/Scan/Query permission on the restored table ARN (CONDITIONAL path).

derived aws emits CanReadData

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'principal': None} HasPermission {'table': None}

where

node_type(?table) == NoSQLDatabase ?table.provider_type in ['AWS::DynamoDB::Table', 'AWS::DynamoDB::GlobalTable'] ?principal has EFFECTIVE dynamodb:RestoreTableToPointInTime on ?table ARN ?table.properties.PointInTimeRecoveryStatus == 'ENABLED'

emit

source typeIdentity
target typeNoSQLDatabase
source?principal
target?table
permissionsdynamodb:RestoreTableToPointInTime
conditionsiam_permission scp_or_org_policy service_state
state logicCONDITIONAL(iam_permission) when dynamodb:RestoreTableToPointInTime is confirmed EFFECTIVE on the source table ARN AND PITR is enabled. RestoreTableToPointInTime creates a NEW table but does NOT automatically grant the restoring principal read access to the NEW table's ARN. The principal must have a SEPARATE, confirmed EFFECTIVE permission (dynamodb:GetItem, dynamodb:Query, or dynamodb:Scan) on the newly-restored table's ARN to read items. This typically requires a wildcard permission (e.g., dynamodb:GetItem on arn:aws:dynamodb:*:*:table/* or arn:aws:dynamodb:region:account:table/restored-*) or an explicit grant on the new table. Emit as CONDITIONAL(iam_permission); upgrade to ACTIVE only when an aws-dynamodb-read-data edge is confirmed on the restored table ARN. CONDITIONAL(service_state) when PITR is disabled. BLOCKED by an SCP or permission-boundary deny on RestoreTableToPointInTime.

Narrative

{principal.name} can restore a point-in-time copy of {table.name} (dynamodb:RestoreTableToPointInTime), creating a new table with full historical item data. Reading the new table requires a separate GetItem/Scan/Query permission on the restored table ARN.

Raw rule rules/derived/aws/dynamodb.yaml

id: aws-dynamodb-restore-pitr-read
emits: CanReadData
description: dynamodb:RestoreTableToPointInTime creates a new table from PITR; reading it requires separate
  GetItem/Scan/Query permission on the restored table ARN (CONDITIONAL path).
match:
- - principal: null
  - HasPermission
  - table: null
where:
- node_type(?table) == NoSQLDatabase
- ?table.provider_type in ['AWS::DynamoDB::Table', 'AWS::DynamoDB::GlobalTable']
- ?principal has EFFECTIVE dynamodb:RestoreTableToPointInTime on ?table ARN
- ?table.properties.PointInTimeRecoveryStatus == 'ENABLED'
emit:
  source_type: Identity
  target_type: NoSQLDatabase
  source: ?principal
  target: ?table
  permissions:
  - dynamodb:RestoreTableToPointInTime
  conditions:
  - iam_permission
  - scp_or_org_policy
  - service_state
  state_logic: CONDITIONAL(iam_permission) when dynamodb:RestoreTableToPointInTime is confirmed EFFECTIVE
    on the source table ARN AND PITR is enabled. RestoreTableToPointInTime creates a NEW table but does
    NOT automatically grant the restoring principal read access to the NEW table's ARN. The principal
    must have a SEPARATE, confirmed EFFECTIVE permission (dynamodb:GetItem, dynamodb:Query, or dynamodb:Scan)
    on the newly-restored table's ARN to read items. This typically requires a wildcard permission (e.g.,
    dynamodb:GetItem on arn:aws:dynamodb:*:*:table/* or arn:aws:dynamodb:region:account:table/restored-*)
    or an explicit grant on the new table. Emit as CONDITIONAL(iam_permission); upgrade to ACTIVE only
    when an aws-dynamodb-read-data edge is confirmed on the restored table ARN. CONDITIONAL(service_state)
    when PITR is disabled. BLOCKED by an SCP or permission-boundary deny on RestoreTableToPointInTime.
  confidence: min(contributing_confidences) * 0.85
  derived_from:
  - ?principal HasPermission ?table (dynamodb:RestoreTableToPointInTime effective permission)
  - ?table PointInTimeRecoveryStatus == ENABLED
  - aws-dynamodb-read-data (separate edge required on restored table ARN)
  false_positive_note: "PITR must be enabled on the SOURCE table. RestoreTableToPointInTime is a single\
    \ action that creates the target table as part of its operation \u2014 no separate dynamodb:CreateTable\
    \ permission is required per AWS Service Authorization Reference. The restored table is created in\
    \ the SAME ACCOUNT as the calling principal \u2014 DynamoDB does not support cross-account restore\
    \ directly (unlike Redshift). CRITICAL: the principal MUST HAVE a confirmed EFFECTIVE GetItem/Scan/Query\
    \ permission on the NEW restored table's ARN to read it; restore access alone does not grant read\
    \ capability. This is not a false positive IF the principal has a wildcard dynamodb:GetItem on arn:aws:dynamodb:*:*:table/*\
    \ or equivalent, but CONDITIONAL(iam_permission) otherwise. The SSE key of the source table is inherited\
    \ by the restored table \u2014 additional CONDITIONAL(key_permission) applies if the source table\
    \ uses a CMK the principal cannot decrypt. Subsequent read access on the restored table is captured\
    \ separately by aws-dynamodb-read-data; do not treat restore access as implied read access."
  narrative: '{principal.name} can restore a point-in-time copy of {table.name} (dynamodb:RestoreTableToPointInTime),
    creating a new table with full historical item data. Reading the new table requires a separate GetItem/Scan/Query
    permission on the restored table ARN.'
move · open · esc close