Verifying How IAM and Lake Formation Behave for the Glue REST Catalog and S3 Tables

Verifying How IAM and Lake Formation Behave for the Glue REST Catalog and S3 Tables

Introduction

I’m Aki, an AWS Community Builder (@jitepengin). In my previous article, I hit the Iceberg REST Catalog directly and confirmed the design differences between the Glue endpoint and the S3 Tables endpoint. In that article I wrote that “accessing through the Glue endpoint requires a Lake Formation grant.” This time, I’ll deliberately vary the IAM policy and the Lake Formation grant to see exactly how the behavior of each endpoint changes. Along the way, I’ll also check whether GetDataAccess is actually being called via CloudTrail, to peek inside the authorization flow itself.

介绍

我是 AWS Community Builder (@jitepengin) Aki。在上一篇文章中,我直接调用了 Iceberg REST Catalog,并确认了 Glue 端点与 S3 Tables 端点之间的设计差异。在那篇文章中,我提到“通过 Glue 端点访问需要 Lake Formation 授权”。这一次,我将特意调整 IAM 策略和 Lake Formation 授权,以确切观察每个端点的行为如何变化。在此过程中,我还会通过 CloudTrail 检查是否确实调用了 GetDataAccess,从而一窥授权流程的内部机制。


I previously wrote about the design differences between the Glue and S3 Tables Iceberg REST endpoints in another article, worth a read alongside this one: Hitting the Iceberg REST Catalog Directly: Understanding the Differences Between Glue Data Catalog and S3 Tables

我之前在另一篇文章中写过关于 Glue 和 S3 Tables Iceberg REST 端点之间设计差异的内容,建议与本文结合阅读:直接调用 Iceberg REST Catalog:理解 Glue Data Catalog 与 S3 Tables 的区别


What We’re Verifying Today

According to AWS documentation, the Glue REST Catalog is authorized through a combination of IAM policy and Lake Formation grants, while the S3 Tables REST endpoint is authorized through IAM alone.

  • Glue endpoint: IAM authorization → Lake Formation authorization
  • S3 Tables endpoint: s3tables IAM authorization only

我们今天验证的内容

根据 AWS 文档,Glue REST Catalog 通过 IAM 策略和 Lake Formation 授权的组合进行授权,而 S3 Tables REST 端点仅通过 IAM 进行授权。

  • Glue 端点: IAM 授权 → Lake Formation 授权
  • S3 Tables 端点: 仅 s3tables IAM 授权

Let’s verify how this actually plays out, using the following matrix:

ConditionGlue endpointS3 Tables endpoint
IAM ✓ / LF ✓200 (baseline)200 (baseline)
IAM ✓ / LF ✗??
IAM ✗ / LF ✓??

让我们通过以下矩阵来验证实际情况:

条件Glue 端点S3 Tables 端点
IAM ✓ / LF ✓200 (基准)200 (基准)
IAM ✓ / LF ✗??
IAM ✗ / LF ✓??

The IAM ✓ / LF ✗ cell is especially important:

  • If only the Glue endpoint returns 403 → Glue is genuinely enforcing Lake Formation authorization
  • If only the S3 Tables endpoint returns 200 → that confirms the difference in authorization flow

After each cell, I’ll also check whether lakeformation:GetDataAccess was called via CloudTrail, to visualize the internal authorization flow.

IAM ✓ / LF ✗ 这一项尤为重要:

  • 如果只有 Glue 端点返回 403 → 说明 Glue 确实强制执行了 Lake Formation 授权。
  • 如果只有 S3 Tables 端点返回 200 → 这证实了授权流程上的差异。

在测试完每一项后,我还会通过 CloudTrail 检查是否调用了 lakeformation:GetDataAccess,以可视化内部的授权流程。


Test Environment Setup

I’m reusing the resources created in the previous article.

  • Table bucket: penguin-rest-test
  • Namespace: analytics
  • Table: daily_sales
  • Glue integration: enabled
  • register-resource —with-federation: already configured (vended credentials are issued)

测试环境设置

我将复用上一篇文章中创建的资源。

  • 表存储桶: penguin-rest-test
  • 命名空间: analytics
  • 表: daily_sales
  • Glue 集成: 已启用
  • register-resource —with-federation: 已配置(已颁发凭证)

Note: In this test, when using Glue REST Catalog’s federation, the Lake Formation permission-evaluation target was the IAM role used to vend credentials. This can be confirmed from the CloudTrail GetDataAccess event, where the session that assumed that IAM role is recorded as the userIdentity.

注意: 在本次测试中,当使用 Glue REST Catalog 的联合身份验证时,Lake Formation 权限评估的目标是用于颁发凭证的 IAM 角色。这一点可以通过 CloudTrail 的 GetDataAccess 事件确认,其中承担该 IAM 角色的会话被记录为 userIdentity


“IAM ✓” state: the test IAM user has the following policy attached.

{
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["glue:GetCatalog", "glue:GetDatabase", "glue:GetTable"],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3tables:GetTableBucket", "s3tables:GetNamespace", "s3tables:GetTable", 
        "s3tables:GetTableData", "s3tables:GetTableMetadataLocation"
      ],
      "Resource": [
        "arn:aws:s3tables:ap-northeast-1:123456789012:bucket/penguin-rest-test",
        "arn:aws:s3tables:ap-northeast-1:123456789012:bucket/penguin-rest-test/table/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": ["lakeformation:GetDataAccess"],
      "Resource": "*"
    }
  ]
}

“IAM ✓” 状态: 测试 IAM 用户附加了以下策略。


“LF ✓” state: the IAM role used to vend credentials (penguin-irc-test-role) has the following Lake Formation grants.

  • Database (analytics): DESCRIBE
  • Table (daily_sales): SELECT, DESCRIBE

“LF ✓” 状态: 用于颁发凭证的 IAM 角色 (penguin-irc-test-role) 拥有以下 Lake Formation 授权。

  • 数据库 (analytics): DESCRIBE
  • 表 (daily_sales): SELECT, DESCRIBE

IAM ✓ / LF ✓ (Baseline State)

Glue Endpoint

awscurl --service glue --region ap-northeast-1 --profile penguin-irc-test \
"https://glue.ap-northeast-1.amazonaws.com/iceberg/v1/catalogs/123456789012:s3tablescatalog:penguin-rest-test/namespaces/analytics/tables/daily_sales"

Result (excerpt):

{
  "config": {
    "s3.access-key-id": "ASIAXXXXXXXXXXXXXXXX",
    "s3.secret-access-key": "(masked)",
    "s3.session-token": "(masked)"
  },
  "metadata-location": "s3://...(omitted)"
}

HTTP 200, with a response containing vended credentials.

IAM ✓ / LF ✓ (基准状态)

Glue 端点 (命令同左) 结果(节选): (JSON 内容同左) HTTP 200,响应中包含已颁发的凭证。


S3 Tables Endpoint

BUCKET_ARN_PATH="arn:aws:s3tables:ap-northeast-1:123456789012:bucket%2Fpenguin-rest-test"
awscurl --service s3tables --region ap-northeast-1 --profile penguin-irc-test \
"https://s3tables.ap-northeast-1.amazonaws.com/iceberg/v1/${BUCKET_ARN_PATH}/namespaces/analytics/tables/daily_sales"

Result (excerpt):

{
  "config": {
    "tableBucketId": "3b2a6702-dd99-44f2-bc03-2f9f6b273104",
    "namespaceId": "20576faa-861e-499f-a30f-4d6c7550dd55",
    "tableId": "34c72c19-610d-4e5c-bee4-6ae9f093c583"
  },
  "metadata-location": "s3://...(omitted)"
}

HTTP 200, with a response containing internal IDs (no credentials).

S3 Tables 端点 (命令同左) 结果(节选): (JSON 内容同左) HTTP 200,响应中包含内部 ID(无凭证)。


Checking CloudTrail (Glue Endpoint → GetDataAccess)

aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=GetDataAccess \
--region ap-northeast-1 --max-results 3

Result (excerpt):

{
  "EventName": "GetDataAccess",
  "EventTime": "2026-07-10T14:39:35+09:00",
  "EventSource": "lakeformation.amazonaws.com",
  "Username": "penguin-irc-test-session",
  "CloudTrailEvent": "...\"invokedBy\":\"glue.amazonaws.com\"..."
}

GetDataAccess is recorded with invokedBy: glue.amazonaws.com. The event was logged within seconds of when the request was sent, which shows that Glue queries Lake Formation synchronously. No GetDataAccess was recorded for the request made against the S3 Tables endpoint.

检查 CloudTrail (Glue 端点 → GetDataAccess)

(命令同左) 结果(节选): (JSON 内容同左) GetDataAccess 被记录,且包含 invokedBy: glue.amazonaws.com。该事件在请求发送后的几秒钟内被记录,这表明 Glue 是同步查询 Lake Formation 的。针对 S3 Tables 端点的请求没有记录到 GetDataAccess


Checking CloudTrail (the S3 Tables Endpoint’s Own Call)

In addition to confirming that GetDataAccess isn’t recorded, let’s also check how the S3 Tables endpoint’s own API call (GetTableMetadataLocation) shows up in CloudTrail.

aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=GetTableMetadataLocation \
--region ap-northeast-1 --max-results 3 --profile toyano

Result (excerpt, masked):

{
  "EventName": "GetTableMetadataLocation",
  "EventTime": "2026-07-10T14:41:05+09:00",
  "EventSource": "s3tables.amazonaws.com",
  "Username": "penguin-irc-test-session",
  "CloudTrailEvent": "{\"userIdentity\":{\"type\":\"AssumedRole\",\"arn\":\"arn:aws:sts::123456789012:assumed-role/penguin-irc-test-role/penguin-irc-test-session\"},\"eventSource\":\"s3tables.amazonaws.com\",\"eventName\":\"GetTableMetadataLocation\",...}"
}

The eventSource is recorded simply as s3tables.amazonaws.com on its own.

检查 CloudTrail (S3 Tables 端点自身的调用)

除了确认没有记录 GetDataAccess 之外,我们再来看看 S3 Tables 端点自身的 API 调用 (GetTableMetadataLocation) 在 CloudTrail 中是如何显示的。 (命令同左) 结果(节选,已脱敏): (JSON 内容同左) eventSource 仅被记录为 s3tables.amazonaws.com