aws-athena-query-reads-data
athena:StartQueryExecution on an enabled workgroup, combined with s3:GetObject on the data prefix, s3:PutObject on the results output location, and Glue read permissions, enables the principal to read underlying data-lake content.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
AnalyticsService
?workgroup.provider_type == 'AWS::Athena::WorkGroup'
?workgroup.State == 'ENABLED'
?principal has EFFECTIVE athena:StartQueryExecution on ?workgroup ARN
?principal has EFFECTIVE s3:GetObject AND s3:ListBucket on the data-source S3 prefix referenced by tables in ?workgroup's Glue catalog
?principal has EFFECTIVE s3:PutObject on the query-results output S3 location in ?workgroup.Configuration.ResultConfiguration.OutputLocation
?principal has EFFECTIVE glue:GetTable AND glue:GetDatabase on the Glue catalog tables accessible via ?workgroup
?principal has EFFECTIVE glue:GetPartition on partitions in those Glue tables (or glue:GetPartitions wildcard)
emit
| source type | Identity |
|---|---|
| target type | Storage |
| source | ?principal |
| target | <S3 ObjectStorage node for the data-source prefix covered by ?workgroup's Glue catalog> |
| permissions | athena:StartQueryExecution s3:GetObject s3:ListBucket s3:PutObject glue:GetTable glue:GetDatabase glue:GetPartition |
| conditions | iam_permission resource_policy key_permission service_state |
| state logic | ACTIVE when ALL FOUR permission sets are confirmed EFFECTIVE: (1) athena:StartQueryExecution on the workgroup, (2) s3:GetObject + s3:ListBucket on the data prefix, (3) s3:PutObject on the workgroup's output location (where Athena writes result objects before the caller can read them via GetQueryResults), and (4) glue:GetTable + glue:GetDatabase on the catalog; AND the workgroup State is ENABLED AND no KMS key_permission gate is unresolved. CONDITIONAL(service_state) when the workgroup State is DISABLED — queries cannot be submitted. CONDITIONAL(iam_permission) when any of the four permission sets are unconfirmed — athena:StartQueryExecution alone cannot read data; s3:PutObject on the output location is required for result materialization. CONDITIONAL(key_permission) when the workgroup encrypts results with a CMK and kms:GenerateDataKey + kms:Decrypt are unconfirmed (results are written encrypted; reading them also requires kms:Decrypt on the result objects). A resource_policy deny on the S3 bucket or Glue catalog caps accordingly. Inherit weakest across all contributors; a BLOCKED deny on any of the four permission gates blocks this edge. |
Narrative
{principal.name} can submit SQL queries to Athena workgroup {workgroup.name} (athena:StartQueryExecution) and has s3:GetObject on the underlying data prefix, s3:PutObject on the results output location (where Athena writes results before they can be read), plus Glue catalog read permissions. Athena translates the SQL into S3 data reads, materializes results to the output S3 location (which requires s3:PutObject), and {principal.name} can then read the result set - so {principal.name} can read any content accessible through the workgroup's Glue catalog - including sensitive tables, logs, or application data stored in the data lake. data-plane rules roll up CanExfiltrate; credential-chains read-secret-yields-identity fires if the data ContainsSecret.
Raw rule rules/derived/aws/athena.yaml
id: aws-athena-query-reads-data
emits: CanReadData
description: athena:StartQueryExecution on an enabled workgroup, combined with s3:GetObject on the data
prefix, s3:PutObject on the results output location, and Glue read permissions, enables the principal
to read underlying data-lake content.
match:
- - principal: null
- HasPermission
- workgroup: null
where:
- node_type(?workgroup) == AnalyticsService
- ?workgroup.provider_type == 'AWS::Athena::WorkGroup'
- ?workgroup.State == 'ENABLED'
- ?principal has EFFECTIVE athena:StartQueryExecution on ?workgroup ARN
- ?principal has EFFECTIVE s3:GetObject AND s3:ListBucket on the data-source S3 prefix referenced by tables
in ?workgroup's Glue catalog
- ?principal has EFFECTIVE s3:PutObject on the query-results output S3 location in ?workgroup.Configuration.ResultConfiguration.OutputLocation
- ?principal has EFFECTIVE glue:GetTable AND glue:GetDatabase on the Glue catalog tables accessible via
?workgroup
- ?principal has EFFECTIVE glue:GetPartition on partitions in those Glue tables (or glue:GetPartitions
wildcard)
emit:
source_type: Identity
target_type: Storage
source: ?principal
target: <S3 ObjectStorage node for the data-source prefix covered by ?workgroup's Glue catalog>
permissions:
- athena:StartQueryExecution
- s3:GetObject
- s3:ListBucket
- s3:PutObject
- glue:GetTable
- glue:GetDatabase
- glue:GetPartition
conditions:
- iam_permission
- resource_policy
- key_permission
- service_state
state_logic: "ACTIVE when ALL FOUR permission sets are confirmed EFFECTIVE: (1) athena:StartQueryExecution\
\ on the workgroup, (2) s3:GetObject + s3:ListBucket on the data prefix, (3) s3:PutObject on the workgroup's\
\ output location (where Athena writes result objects before the caller can read them via GetQueryResults),\
\ and (4) glue:GetTable + glue:GetDatabase on the catalog; AND the workgroup State is ENABLED AND\
\ no KMS key_permission gate is unresolved. CONDITIONAL(service_state) when the workgroup State is\
\ DISABLED \u2014 queries cannot be submitted. CONDITIONAL(iam_permission) when any of the four permission\
\ sets are unconfirmed \u2014 athena:StartQueryExecution alone cannot read data; s3:PutObject on the\
\ output location is required for result materialization. CONDITIONAL(key_permission) when the workgroup\
\ encrypts results with a CMK and kms:GenerateDataKey + kms:Decrypt are unconfirmed (results are written\
\ encrypted; reading them also requires kms:Decrypt on the result objects). A resource_policy deny\
\ on the S3 bucket or Glue catalog caps accordingly. Inherit weakest across all contributors; a BLOCKED\
\ deny on any of the four permission gates blocks this edge."
confidence: min(contributing_confidences) * 0.95
derived_from:
- ?principal HasPermission ?workgroup (athena:StartQueryExecution effective)
- ?principal HasPermission <S3 data prefix> (s3:GetObject + s3:ListBucket effective)
- "?principal HasPermission <S3 output location> (s3:PutObject effective \u2014 required for result\
\ write)"
- ?principal HasPermission <Glue catalog> (glue:GetTable + glue:GetDatabase + glue:GetPartition effective)
- "credential-chains:decrypt-gates-secret-read (KMS-encrypted results gate \u2014 cited not re-derived)"
false_positive_note: "FOUR independent permission gates are ALL required; never emit ACTIVE when any\
\ one is unconfirmed. (1) athena:StartQueryExecution on the SPECIFIC workgroup ARN \u2014 Athena enforces\
\ workgroup-level access; a grant on a different workgroup does not qualify. (2) s3:GetObject on the\
\ data-source S3 PREFIX identified from Glue table Location fields \u2014 confirm the principal's\
\ S3 permissions cover the actual data location (not just the output bucket). (3) s3:PutObject on\
\ the query-results output S3 location (from the workgroup's Configuration.ResultConfiguration.OutputLocation)\
\ \u2014 WITHOUT this, athena:StartQueryExecution fails at the result-write step, before the caller\
\ can read results via GetQueryResults. This is distinct from the data-source read permission; both\
\ S3 buckets/prefixes must be accessible. (4) glue:GetTable on the SPECIFIC Glue database/table the\
\ workgroup's catalog exposes \u2014 Glue resource-based policies may deny access to specific databases.\
\ Also require glue:GetPartition on the partitions (or glue:GetPartitions wildcard), unless the tables\
\ are non-partitioned. When the workgroup uses EnforceWorkGroupConfiguration: true, the output location\
\ is fixed by the workgroup (not the caller); the CanReadData target is the DATA SOURCE, not the output\
\ location \u2014 do not conflate them. A DISABLED workgroup (State: DISABLED) cannot accept new queries\
\ \u2014 downgrade to CONDITIONAL(service_state). For KMS-encrypted results: the caller needs kms:GenerateDataKey\
\ to write and kms:Decrypt to read result objects \u2014 without both, result-read is CONDITIONAL(key_permission).\
\ credential-chains decrypt-gates-secret-read upgrades to ACTIVE when CanDecrypt is confirmed."
narrative: "{principal.name} can submit SQL queries to Athena workgroup {workgroup.name} (athena:StartQueryExecution)\
\ and has s3:GetObject on the underlying data prefix, s3:PutObject on the results output location\
\ (where Athena writes results before they can be read), plus Glue catalog read permissions. Athena\
\ translates the SQL into S3 data reads, materializes results to the output S3 location (which requires\
\ s3:PutObject), and {principal.name} can then read the result set \u2014 so {principal.name} can\
\ read any content accessible through the workgroup's Glue catalog \u2014 including sensitive tables,\
\ logs, or application data stored in the data lake. data-plane rules roll up CanExfiltrate; credential-chains\
\ read-secret-yields-identity fires if the data ContainsSecret."