aws-qldb-sendcommand-read-data
qldb:SendCommand on an ALLOW_ALL-mode ledger allows the caller to run arbitrary PartiQL SELECT statements against all tables, yielding full data-plane read of all committed document revisions.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?ledger) ==
NoSQLDatabase
?ledger.provider_type == 'AWS::QLDB::Ledger'
effective_action(?principal, ?ledger) includes 'qldb:SendCommand'
(?ledger.properties.permissionsMode == 'ALLOW_ALL') OR (?ledger.properties.permissionsMode == 'STANDARD' AND effective_action(?principal, ?ledger) includes 'qldb:UpdateLedgerPermissionsMode')
emit
| source type | Identity |
|---|---|
| target type | NoSQLDatabase |
| source | ?principal |
| target | ?ledger |
| permissions | qldb:SendCommand |
| conditions | iam_permission key_permission |
| state logic | if ?ledger.properties.permissionsMode == 'ALLOW_ALL' AND effective_action(?principal, ?ledger) includes 'qldb:SendCommand': if ?ledger.encryptionDescription.kmsKeyArn is a customer-managed key (not 'AWS_OWNED_KMS_KEY'): CONDITIONAL(key_permission) — the QLDB service (qldb.amazonaws.com, not the IAM caller) must have kms:Decrypt on the CMK via a KMS grant in the key policy. This is a service-level permission fact collected from the KMS key policy, not an IAM caller permission. Emit ACTIVE when the KMS grant for qldb.amazonaws.com is confirmed; emit CONDITIONAL(key_permission) when unknown. else: ACTIVE. if ?ledger.properties.permissionsMode == 'STANDARD' AND effective_action(?principal, ?ledger) includes 'qldb:SendCommand' AND effective_action(?principal, ?ledger) includes 'qldb:UpdateLedgerPermissionsMode': CONDITIONAL(service_state) — principal can downgrade to ALLOW_ALL then read all data; downgrade must happen first. else: do not emit. |
Narrative
{principal.name} can initiate a QLDB session (qldb:SendCommand) on {ledger.name}, which is in ALLOW_ALL permissions mode, and run arbitrary PartiQL SELECT statements against all tables without any table-level IAM grants. This yields full data-plane read of all committed document revisions in the ledger journal.
Raw rule rules/derived/aws/qldb.yaml
id: aws-qldb-sendcommand-read-data
emits: CanReadData
description: qldb:SendCommand on an ALLOW_ALL-mode ledger allows the caller to run arbitrary PartiQL SELECT
statements against all tables, yielding full data-plane read of all committed document revisions.
match:
- - principal: null
- HasPermission
- ledger: null
where:
- node_type(?ledger) == NoSQLDatabase
- ?ledger.provider_type == 'AWS::QLDB::Ledger'
- effective_action(?principal, ?ledger) includes 'qldb:SendCommand'
- (?ledger.properties.permissionsMode == 'ALLOW_ALL') OR (?ledger.properties.permissionsMode == 'STANDARD'
AND effective_action(?principal, ?ledger) includes 'qldb:UpdateLedgerPermissionsMode')
emit:
source_type: Identity
target_type: NoSQLDatabase
source: ?principal
target: ?ledger
permissions:
- qldb:SendCommand
conditions:
- iam_permission
- key_permission
state_logic: "if ?ledger.properties.permissionsMode == 'ALLOW_ALL'\n AND effective_action(?principal,\
\ ?ledger) includes 'qldb:SendCommand':\n if ?ledger.encryptionDescription.kmsKeyArn is a customer-managed\
\ key\n (not 'AWS_OWNED_KMS_KEY'): CONDITIONAL(key_permission) \u2014 the QLDB service\n (qldb.amazonaws.com,\
\ not the IAM caller) must have kms:Decrypt on the CMK\n via a KMS grant in the key policy. This\
\ is a service-level permission fact\n collected from the KMS key policy, not an IAM caller permission.\
\ Emit ACTIVE\n when the KMS grant for qldb.amazonaws.com is confirmed; emit CONDITIONAL(key_permission)\n\
\ when unknown.\n else: ACTIVE.\nif ?ledger.properties.permissionsMode == 'STANDARD'\n AND effective_action(?principal,\
\ ?ledger) includes 'qldb:SendCommand'\n AND effective_action(?principal, ?ledger) includes 'qldb:UpdateLedgerPermissionsMode':\n\
\ CONDITIONAL(service_state) \u2014 principal can downgrade to ALLOW_ALL\n then read all data; downgrade\
\ must happen first.\nelse: do not emit."
confidence: contributing_confidence * 0.95
derived_from:
- <HasPermission edge for qldb:SendCommand on ?ledger>
false_positive_note: "Do NOT emit ACTIVE when permissionsMode is STANDARD and the principal lacks qldb:UpdateLedgerPermissionsMode\
\ \u2014 SendCommand alone on a STANDARD ledger only opens a session; subsequent SELECT calls are\
\ IAM-denied at the table level. Always verify permissionsMode from DescribeLedger output. Do NOT\
\ emit when qldb:SendCommand is scoped by a resource ARN that does not cover this ledger. When the\
\ ledger uses a customer-managed KMS key (encryptionDescription.kmsKeyArn != 'AWS_OWNED_KMS_KEY'),\
\ emit CONDITIONAL(key_permission). The KMS grant that gates data-plane access is held by the QLDB\
\ service principal (qldb.amazonaws.com) in the key policy, not the IAM caller. Emit ACTIVE only when\
\ the KMS key policy is confirmed to grant kms:Decrypt to qldb.amazonaws.com; this is a service-level\
\ fact collected from the KMS key policy, not an IAM caller permission."
narrative: '{principal.name} can initiate a QLDB session (qldb:SendCommand) on {ledger.name}, which
is in ALLOW_ALL permissions mode, and run arbitrary PartiQL SELECT statements against all tables without
any table-level IAM grants. This yields full data-plane read of all committed document revisions in
the ledger journal.'