Skip to content

Commit f397779

Browse files
javbeltran_expediaclaude
andcommitted
fix: add lf_data_access role to S3 bucket policy to allow Glue stats Puffin file writes
LakeFormation vends credentials via the lf_data_access role when Glue stats writes Puffin files to S3. The role was registered as the LF service-linked role for S3 bucket access but was not included in the bucket policy, causing S3 Access Denied on every Puffin file write. Fix aligns with the lakehouse module which explicitly prepends lf_data_access_role to local_write_iamroles in its bucket policy. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 833c158 commit f397779

2 files changed

Lines changed: 7 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file.
33

44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
55

6+
## [7.12.10] - 2026-04-16
7+
### Fixed
8+
- Added `lf_data_access` role ARN to S3 bucket policy `common_producer_iamroles` when `create_lf_data_access_role` is true. LakeFormation vends credentials via this role when Glue stats writes Puffin files, but without it being in the bucket policy the writes were denied with S3 Access Denied.
9+
610
## [7.12.9] - 2026-04-16
711
### Fixed
812
- Added `lakeformation:GetDataAccess` and `iam:PassRole` (self) inline policy to `lf_data_access` role, required for LakeFormation credential vending when Glue stats writes column statistics back to the catalog.

s3.tf

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ locals {
2525
client_roles = replace(lookup(schema, "client_roles", ""), ",", "\",\"")
2626
governance_iamroles = join("\",\"", var.apiary_governance_iamroles)
2727
consumer_prefix_roles = lookup(var.apiary_consumer_prefix_iamroles, schema["schema_name"], {})
28-
common_producer_iamroles = join("\",\"", var.apiary_common_producer_iamroles)
28+
common_producer_iamroles = join("\",\"", compact(concat(var.create_lf_data_access_role ? [aws_iam_role.lf_data_access[0].arn] : [], var.apiary_common_producer_iamroles)))
2929
deny_exception_iamroles = lookup(schema, "deny_exception_iamroles", "") == "" ? "" : join("\",\"", compact(concat(split(",", schema["deny_exception_iamroles"]), var.apiary_managed_service_iamroles, var.apiary_governance_iamroles)))
3030
})
3131
}
@@ -42,7 +42,7 @@ resource "aws_s3_bucket" "apiary_data_bucket" {
4242
bucket = each.value["data_bucket"]
4343
request_payer = "BucketOwner"
4444
policy = local.bucket_policy_map[each.key]
45-
tags = merge(tomap({"Name"=each.value["data_bucket"]}),
45+
tags = merge(tomap({ "Name" = each.value["data_bucket"] }),
4646
var.apiary_tags,
4747
jsondecode(lookup(each.value, "tags", "{}")))
4848
}
@@ -109,7 +109,7 @@ resource "aws_s3_bucket_lifecycle_configuration" "apiary_data_bucket_versioning_
109109
days = each.value["s3_object_expiration_days_num"] != "-1" ? each.value["s3_object_expiration_days_num"] : "0"
110110
}
111111
}
112-
}
112+
}
113113

114114
resource "aws_s3_bucket_inventory" "apiary_bucket" {
115115
for_each = var.s3_enable_inventory == true ? {

0 commit comments

Comments
 (0)