Lake Formation Governance: Permissions, Row/Column Security, and Data Sharing
Govern the AWS lakehouse the way a database is governed: what AWS Lake Formation replaces in the IAM-plus-S3 sprawl, the difference between an LF-registered location and hybrid access mode, the permission granularity ladder from database to table to column to row filter, a fully worked analyst policy on gold.sales that removes the salary column and filters rows to region='eu', LF-Tag attribute-based access control with inheritance and AND/OR matching rules, cross-account data sharing through AWS RAM with external filtering toggles, trusted callers, data lake administrators and managed access, an engine support matrix for Athena, Redshift Spectrum, QuickSight, Glue and EMR, the IAMAllowedPrincipals default and the six-step migration off it, a permission-check decision tree, a Grant API and CLI sketch, the Integral Ad Science and FanDuel case material, a sourced October 2026 update box, three interactive checks, nine worked examples, five diagrams and twelve exam-style questions.
Lessons 01 to 11 built the machine: buckets, formats, Iceberg tables, crawlers, jobs, a query engine, a warehouse and an orchestrator. Every one of those layers produced a new place where somebody had to answer the same question; who may see this? This lesson answers it once, centrally, with AWS Lake Formation. The service is not an IAM replacement and not a catalog; it is an RDBMS-shaped permission layer that sits on the Glue Data Catalog and vends scoped temporary credentials to integrated engines, so that one GRANT statement can mean something at database, table, column, row and cell granularity.
The teaching rule for this lesson: Lake Formation decides visibility, IAM decides reachability, and the engine does the actual filtering. Confuse those three and every symptom in this lesson becomes a mystery.
====================================================================
LAKE FORMATION GOVERNANCE SURFACE (as of October 2026)
====================================================================
Replaces ...... three overlapping policy surfaces: IAM identity
policies for glue:*, S3 bucket/prefix policies for
the data, Glue catalog resource policies - all
effectively table- or bucket-scoped
Augments ...... IAM (it "augments the IAM permissions model");
IAM still authenticates and still gates every
Lake Formation control-plane API
Two planes .... catalog plane (Glue + LF grants)
data plane (S3 + role-vended temporary credentials)
bridge = RegisterResource on the S3 location
Modes ......... Lake Formation mode (revoke IAMAllowedPrincipals)
hybrid access mode (both planes, opt-in per principal)
Ladder ........ catalog -> database -> table -> COLUMN -> ROW -> CELL
Column ........ TableWithColumns ColumnNames / ExcludedColumnNames,
or a data-filter column spec (nested struct fields)
Row / cell .... DataCellsFilter, PartiQL WHERE subset,
expression < 2,048 characters, <=100 per
principal per table
TBAC .......... LF-Tag key=value, inheritance
database -> table -> column (overridable);
keys ANDed, values of one key ORed
Sharing ....... AWS RAM resource shares; same-org instant,
out-of-org invitation; cross-account version 5 =
unlimited tables per share (2026-02-11)
Admins ........ <= 30 data lake administrators per account
Price ......... permissions, tags and sharing = $0;
Storage API bills bytes scanned (10 MB minimum)
Default trap .. Super pre-granted to IAMAllowedPrincipals
until you revoke it - grants then look inert
====================================================================In this lesson you will:
- diagnose what Lake Formation actually replaces, the IAM-plus-S3 policy sprawl, and what it deliberately does not replace;
- separate LF-registered locations from hybrid access mode, and predict which permission plane answers a given request;
- climb the permission granularity ladder (database β table β column β row filter β cell) and name the mechanism at each rung;
- build the worked analyst policy:
SELECTongold.sales, minussalary, rows limited toregion = 'eu', as one cell-level data filter; - apply LF-Tags and TBAC: tag grants, inheritance, and the AND-across-keys / OR-within-a-key matching rules;
- share cross-account databases through AWS RAM, with the external-engine toggle, trusted callers, managed access and data-lake-administrator rules;
- place Athena, Redshift Spectrum, QuickSight, Glue and EMR on an engine support matrix and say what breaks in each cell;
- remove the
IAMAllowedPrincipalsdefault and execute the documented six-step migration; - read the permission-check decision tree and write real
GrantPermissionscalls in JSON and CLI; - study three named AWS customer cases (Integral Ad Science, FanDuel, Morningstar), a sourced October 2026 update box, nine worked examples, five diagrams, three interactive checks and twelve exam-style questions.
1. What Lake Formation replaces: the IAM and S3 sprawl
1.1 Three surfaces, one table, no rows
Before Lake Formation, a governed lake on AWS was assembled from three overlapping policy surfaces, and AWS said so at general availability on 2019-08-08:
"Previously you had to use separate policies to secure data and metadata access, and these policies only allowed table-level access. Now you can give access to each user, from a central location, only to the columns they need to use.", AWS News Blog, AWS Lake Formation, Now Generally Available (2019-08-08)
Surface | What it could express | Where it could not go |
|---|---|---|
IAM identity policies | glue:*, lakeformation:*, s3:* on chosen ARNs | No notion of a column; a wildcard that grants a whole prefix grants a whole table |
S3 bucket / prefix policies | Which principals may read which prefix | Bucket- or prefix-scoped; the AWS Redshift Spectrum governance blog states bucket policies stop scaling "when the number of combinations of access levels and users increase" |
Glue Data Catalog resource policies | Cross-account catalog access | Still table-shaped; nothing below the table, nothing about rows |
Lake Formation adds a fourth surface that is deliberately shaped like a relational database grant system:
"Lake Formation provides a relational database management system (RDBMS) permissions model to grant or revoke access to catalogs, databases, tables, and columns in the Data Catalog with underlying data in Amazon S3.": LF Developer Guide, Onboarding to Lake Formation permissions (accessed 2026-10-11)
And it augments rather than replaces IAM:
"Lake Formation provides its own permissions model that augments the IAM permissions model.": LF Developer Guide, Overview of data filtering (accessed 2026-10-11)
The division of labour is therefore fixed for the rest of the lesson: IAM authenticates and gates the control plane (GrantPermissions, GetDataAccess, glue:*), Lake Formation gates the data plane by deciding what metadata and what scoped temporary credentials an integrated engine receives, and the engine performs the row/column/cell filtering itself.
Two facts fall straight out of that diagram and both are examinable:
- Registration is the only bridge between the planes. "Lake Formation credential vending is not available, even when opted in, unless the data location is registered with Lake Formation." (LF Developer Guide, Hybrid access workflow, accessed 2026-10-11.)
- Lake Formation does not lock your bucket. "The Lake Formation permissions model doesn't prevent access to Amazon S3 locations through the Amazon S3 API or console if you have access to them through IAM or Amazon S3 policies. You can attach IAM policies to principals to block this access." (LF Developer Guide, Underlying data access control, accessed 2026-10-11.)
1.2 Worked example E1: counting the sprawl, then counting the replacement
SCENARIO (derived arithmetic from the documented permission set;
not an AWS-published figure) - as of Oct 2026
Estate ....... 3 databases x 12 tables = 36 governed tables
4 teams need read access (analysts, data scientists,
finance, auditors)
3 S3 prefixes, one per database
IAM + S3 WORLD
IAM identity policies ....... 4 policies x up to 36 table ARNs
= up to 144 ARN entries
S3 prefix policies .......... 4 principals x 3 prefixes
= 12 allow statements, restated in
every bucket policy
Glue catalog resource policy cross-account only, table-shaped
TOTAL maintained statements . 144 + 12 = 156 (derived)
Add a 5th team ............... +36 IAM entries +12 bucket
statements = +48, every time
LAKE FORMATION, NAMED RESOURCES ONLY
SELECT per table ............. 4 x 36 = 144 grants (derived)
DESCRIBE per database ........ 4 x 3 = 12 grants (derived)
TOTAL ........................ 156 statements - same shape, but
now in ONE place with an audit trail
LAKE FORMATION, TAG-BASED (TBAC)
AWS documentation example .... 5 tag assignments + 8 tag grants
= 17 effective permissions
IAS production outcome ....... "hundreds of permission rules
down to precisely two rules"
(AWS Big Data Blog, 2021-09-23)
COST OF ANY OF THE THREE ....... $0 for the permissions themselves
"You pay $0 for the permissions in AWS Lake Formation because
they are provided at no charge." - Lake Formation pricing page
(accessed 2026-10-11)Reading: Lake Formation's first win over raw IAM is not fewer statements: at named-resource granularity you write the same number. Its first win is centralisation plus auditability (one ListPermissions instead of three policy families), and its second win, which arrives in Section 5, is collapsing the count with tags. The cost column is the surprise: the governance layer itself is free, so the only budget question is who maintains it.
- π Did you know? Lake Formation billing has exactly three billable items as of Oct 2026, and none of them is a permission. The Storage API, the standalone server-side filtering engine used when no AWS analytics service processes the data, bills "for the number of bytes scanned by the Storage API, rounded to the next megabyte, with a 10MB minimum"; Governed Tables bills per file tracked, per metadata API call and per byte processed by the storage optimizer; and the storage optimizer itself bills per byte. Grants, revokes, LF-Tags, cross-account sharing and enforcement by Athena, Redshift, Glue and EMR are all $0 (Lake Formation pricing page, accessed 2026-10-11).
2. LF-registered versus hybrid: the two permission modes
A Data Catalog object has two orthogonal questions, and most Lake Formation confusion comes from answering only one of them:
Question | Answer A | Answer B |
|---|---|---|
(a) Is the underlying S3 location registered? | Registered, RegisterResource with a role; LF assumes that role and vends temporary credentials | Not registered, no vending, IAM and S3 policies decide the data plane |
(b) Which permission model applies? | Lake Formation mode, LF is the only model; IAMAllowedPrincipals revoked everywhere | Hybrid access mode, both models coexist, opted in per principal |
2.1 Registration: what the role is for
"When you register a location, you specify an IAM role that grants read/write permissions on that location. Lake Formation assumes that role when supplying temporary credentials to integrated AWS services.": LF Developer Guide, Set up AWS Lake Formation (accessed 2026-10-11)
Practical consequences:
- the registration role, not the caller, holds the durable
s3:*permissions; - callers additionally need the IAM permission
lakeformation:GetDataAccess, and "you must set the Resource parameter to*": any other resource value is unsupported; - registering a prefix covers every table under that path at once, because "multiple tables can share an S3 prefix. When you register a location, all tables under that path get credential vending at once" (AWS-published Lake Formation best-practices guide, accessed 2026-10-11).
2.2 Hybrid access mode: two pathways, opt-in principals
"AWS Lake Formation hybrid access mode supports two permission pathways to the same AWS Glue Data Catalog objects." β¦ "The hybrid access mode enforces only
CREATE_TABLE,CREATE_PARTITION,UPDATE_TABLEpermissions by default." β¦ "opted in principals will require both Lake Formation permissions and IAM permissions to access the data, while non-opted-in principals will continue to access data using only IAM permissions.": LF Developer Guide, Hybrid access mode (accessed 2026-10-11)
That last sentence is the whole mode: hybrid is a per-principal switch, not a per-account switch, and it is the reversible migration tool AWS recommends:
"To ease the transition of data lake permissions from an IAM and Amazon S3 model to Lake Formation permissions, we recommend you to use hybrid access mode for Data Catalog.": LF Developer Guide, Set up AWS Lake Formation (accessed 2026-10-11)
State | IAMAllowedPrincipals on the table | Location registered | Principal opted in? | Who decides read access |
|---|---|---|---|---|
Legacy / default | present ( Super) | maybe | n/a | IAM alone: individual Lake Formation permissions are not in effect |
Lake Formation mode | revoked | yes | n/a | Lake Formation alone (plus IAM for the APIs) |
Hybrid, not opted in | present | yes | no | IAM alone |
Hybrid, opted in | present | yes | yes | Both: LF and IAM must both allow |
Registered-but-not-opted-in | revoked | yes | no | LF metadata rules, but no opt-in means no double gate |
2.3 Worked example E2: taking one role into hybrid mode
# ---- Step 0: see what the table looks like today -----------------
aws lakeformation get-effective-permissions-for-path \
--catalog-id 111122223333 \
--resource-arn arn:aws:glue:us-east-1:111122223333:table/gold/sales
# Expect to see: Super granted to IAMAllowedPrincipals
# (Lake Formation sets Super to that group on databases and tables
# by default - LF Developer Guide, Permissions reference)
# ---- Step 1: register the location so vending can exist ---------
aws lakeformation register-resource \
--resource-arn arn:aws:s3:::acme-lake/gold/ \
--role-arn arn:aws:iam::111122223333:role/lf-registration-role \
--use-service-linked-role # or supply your own customer-managed role
# HybridAccessEnabled can be set on the resource for hybrid operation
# ---- Step 2: opt ONE role in (per-principal, reversible) ---------
aws lakeformation create-lakeformation-opt-in \
--principal DataLakePrincipalIdentifier=arn:aws:iam::111122223333:role/analyst-eu \
--hybrid-access-opt-in-detail HybridAccessEnabled=true
# ---- Step 3: now the analyst needs BOTH planes -------------------
# IAM: glue:GetTable / glue:GetPartitions + lakeformation:GetDataAccess
# LF: SELECT on gold.sales (Section 4)
# A principal that is NOT opted in keeps working on IAM alone,
# which is what makes this reversible:
aws lakeformation delete-lakeformation-opt-in \
--principal DataLakePrincipalIdentifier=arn:aws:iam::111122223333:role/analyst-euChecks: (a) the opted-in analyst with an IAM policy but no LF grant now fails, proof the double gate is live; (b) the non-opted-in role still reads with IAM only, proof the mode is per principal; (c) IsRegisteredWithLakeFormation on the table is true for the opted-in principal's view and unchanged for everyone else.
Registered β hybrid. Registration answers where do credentials come from; hybrid answers which permission model applies. Three separable failure modes follow, and each has a different fix:
- Opted in, location not registered β the principal gets Lake Formation metadata rules but no credential vending, so the data plane still behaves like raw IAM.
- Registered, nobody opted in,
IAMAllowedPrincipalsstill holdsSuperβ Lake Formation permissions are not enforced at all; your new grants are inert. - Neither, but the analyst keeps a direct
s3:GetObjectβ every row filter in this lesson is bypassed. Cleanup of direct S3 grants is a step of the migration, not an optional extra.
- π Did you know? The account-level knobs that keep a new database on the old plane have exact console names: "Use only IAM access control for new databases" and "Use only IAM access control for new tables in new databases", backed in the API by
CreateDatabaseDefaultPermissionsandTableDefaultPermissions, whose shipped default is[{"Principal":{"DataLakePrincipalIdentifier":"IAM_ALLOWED_PRINCIPALS"},"Permissions":["ALL"]}](LF Developer Guide, Changing the default settings for your data lake andDataLakeSettingsAPI, accessed 2026-10-11). AWS deliberately does not name this state "IAMOnly" anywhere: teach the documented names.
3. The permission granularity ladder
3.1 The vocabulary
Resource kinds you can grant on: Catalog, Database, Table, View, DataLocation (only DATA_LOCATION_ACCESS applies), LF_Tag, LF_TagPolicy / LFTagExpression.
The permissions enum, as returned by ListPermissions (LF API reference, accessed 2026-10-11):
ALL (= Super) SELECT INSERT DELETE ALTER DROP DESCRIBE
CREATE_DATABASE CREATE_TABLE DATA_LOCATION_ACCESS
CREATE_LF_TAG ASSOCIATE GRANT_WITH_LF_TAG_EXPRESSION
CREATE_LF_TAG_EXPRESSION CREATE_CATALOG SUPER_USERThree rules about that list:
SELECT,INSERTandDELETEare both Data Catalog permissions and data-access permissions; they are the ones that reach S3.Superis additive and survives partial revocation: "when you revokeSuper, theSELECTandINSERTpermissions remain" (LF Developer Guide, Access control for metadata, accessed 2026-10-11).- Granting on all tables in a database implicitly grants
DESCRIBEon that database, but "this automaticDESCRIBEpermission grant doesn't apply when using attribute-based access control (ABAC)".
3.2 The ladder, drawn
Everything below TABLE is expressed through two mechanisms only: a column filter on the grant itself (TableWithColumns) or a data filter object (DataCellsFilter). Choose between them with one question: do I need rows too?
Need | Mechanism | Object you write |
|---|---|---|
Whole table | Named-resource grant | {"Table": {"CatalogId", "DatabaseName", "Name"}} |
Some columns, all rows | Column filter on the grant | {"TableWithColumns": {"ColumnNames": [...]}} or {"ColumnWildcard": {"ExcludedColumnNames": [...]}} |
All columns, some rows | Data filter, row-level | {"AllRowsWildcard"} + RowFilter.FilterExpression |
Some columns and some rows | Data filter, cell-level | column spec plus RowFilter in one DataCellsFilter |
Bulk reach over many tables | LF-Tag grant | {"LFTagPolicy": {"TagKey", "TagValues"}} |
3.3 Worked example E3: the four-grant ladder on one table
Goal: make gold.sales visible, useful and correctly narrow for role/analyst-eu.
GRANT 1 - visibility (no data yet)
resource Database gold
perms DESCRIBE
effect the database appears in the Athena object list
GRANT 2 - the table (still every row, every column)
resource Table gold.sales
perms SELECT
effect SELECT * FROM gold.sales returns everything - TOO MUCH
GRANT 3 - columns only (Section 4.1 alternative)
resource TableWithColumns gold.sales,
ExcludedColumnNames = [salary]
perms SELECT
effect salary disappears from results AND from glue:GetTable
metadata for this principal - but ALL regions still return
GRANT 4 - rows, columns, one object (the real policy, Section 4)
resource DataCellsFilter gold_sales_eu_no_salary
RowFilter = region = 'eu'
Columns = exclude salary
perms SELECT
effect cell-level: EU rows only, minus the salary column
AUDIT after each grant:
aws lakeformation list-permissions --principal ...
# effective permission = UNION of named-resource, tag-policy and
# data-filter grants - there is no deny primitive, so a later plain
# SELECT grant on the same table re-includes what you excludedNumbers as of Oct 2026: a data filter needs SELECT with the grant option on all table columns to create; there is no cap on filters per table but a limit of 100 data filters per principal per a single table; and the row expression must be under 2,048 characters (LF Developer Guide, Data filtering limitations and PartiQL support, accessed 2026-10-11).
How to answer
Matching exercise with 5 pairs. Match each item on the left with its answer on the right.
Match each permission granularity rung to the Lake Formation mechanism that expresses it:
Drag answers from here:
- π Did you know? Three ceilings are worth memorising because they are all small: 30 data lake administrators per account by default, 1,000 saved LF-Tag expressions per account, and 100 data filters per principal per table (LF Developer Guide, Set up AWS Lake Formation, Managing LF-Tag expressions and Data filtering limitations, all accessed 2026-10-11). A fourth, softer one: AWS's own tag-based worked example reaches 17 effective permissions from just 5 tag assignments plus 8 tag grants.
4. Row-level and column-level security: the worked analyst policy
4.1 The combinatorics: three controls, one object type
"Lake Formation uses data filtering to achieve column-level security, row-level security, and cell-level security." β¦ "When you specify the 'all columns' wildcard and provide a row filter expression, you are establishing row-level security (row filtering) only." β¦ "When you include or exclude specific columns and nested columns, and specify 'all rows' β¦ you are establishing column-level security." β¦ "When you include or exclude specific columns and also provide a row filter expression, you are establishing cell-level security.": LF Developer Guide, Data filtering and cell-level security (accessed 2026-10-11)
Columns field | Rows field | Control you get |
|---|---|---|
AllRowsWildcard (all columns) | predicate present | Row-level security |
ColumnNames or ColumnWildcard.ExcludedColumnNames | AllRowsWildcard | Column-level security |
column spec and predicate | both present | Cell-level security |
Two clarifications that save real debugging time:
- Column filtering is not masking. Excluding
salaryremoves it from results and from that principal's catalog metadata. It never returns***. If the requirement is "show last four digits only", that is a view, an application-layer transform, or Amazon Redshift's dynamic data masking: not Lake Formation. - Availability: "Cell-level security is available in all regions when using Athena engine version 3 or Amazon Redshift Spectrum." (LF Developer Guide, Data filtering limitations, accessed 2026-10-11.)
4.2 The row-filter language: PartiQL subset, with hard edges
Rule | Value (accessed 2026-10-11) |
|---|---|
Syntax | "the expression has the syntax of a WHERE clause in the PartiQL language" |
Length | total < 2,048 characters (API maximum 2048) |
Operators | =, >, <, >=, <=, <>, !=, BETWEEN, IN, LIKE, NOT, IS [NOT] NULL |
Comparisons | you can't compare columns with other columns |
Case | "All string comparisons and LIKE pattern matches are case-sensitive" |
Types | STRING/CHAR/VARCHAR, numeric types, BOOLEAN, STRUCT |
Unsupported | array and map are not supported; struct is |
Partition keys | "You cannot restrict access on columns that are partition keys" |
Views / resource links | cell-level security is not supported on them |
Concurrency | "If you apply the all-rows filter expression on a table concurrently with other filter expressions with predicates, the all-rows expression will prevail" |
4.3 Worked example E4, the analyst policy: gold.sales minus salary, rows = region='eu'
This is cell-level security in one data filter object, plus the visibility grant that makes it usable.
{
"Name": "gold_sales_eu_no_salary",
"DatabaseName": "gold",
"TableName": "sales",
"TableCatalogId": "111122223333",
"RowFilter": { "FilterExpression": "region = 'eu'" },
"ColumnWildcard": { "ExcludedColumnNames": ["salary"] }
}# 1. create the filter - requires SELECT WITH GRANT OPTION on gold.sales
aws lakeformation create-data-cells-filter \
--cli-input-json file://filter.json
# 2. grant SELECT through the filter, not on the bare table
aws lakeformation grant-permissions \
--principal DataLakePrincipalIdentifier=arn:aws:iam::111122223333:role/analyst-eu \
--resource '{"DataCellsFilter":{"TableCatalogId":"111122223333","DatabaseName":"gold","TableName":"sales","Name":"gold_sales_eu_no_salary"}}' \
--permissions SELECT
# 3. visibility, so the table appears in the Athena explorer
aws lakeformation grant-permissions \
--principal DataLakePrincipalIdentifier=arn:aws:iam::111122223333:role/analyst-eu \
--resource '{"Table":{"CatalogId":"111122223333","DatabaseName":"gold","Name":"sales"}}' \
--permissions DESCRIBEFour learner checks, and what each one proves:
Query run as role/analyst-eu | Expected result | What it proves |
|---|---|---|
SELECT salary FROM gold.sales | error / column absent from metadata | the column half of the cell filter is live |
SELECT region, count(*) FROM gold.sales GROUP BY region | only 'eu' counts | the row half is live |
SELECT * FROM gold.sales | every column except salary, EU rows only | both halves compose into cell-level security |
SELECT region FROM gold.sales | works; because region is still readable | the filter predicate column must be in the allow-list; decide deliberately whether region stays visible to analysts |
Contrast (cheaper, narrower): granting TableWithColumns with ExcludedColumnNames = ["salary"] gets you the columns and no rows: a legitimate answer when the requirement is only "hide PII", and the pattern FanDuel used in Case B below. Adding region = 'eu' is what forces you into a data filter.
β οΈ Four ways this policy silently widens back to full access:
- Tags and data filters do not mix. "You can't apply data filters when you use LF-Tags to manage permissions on Data Catalog resources." (LF Developer Guide, Using AWS Lake Formation with Amazon Athena, accessed 2026-10-11.) If
gold.salesis covered by a tag grant, your row filter is not applied to that path. - There is no deny primitive. Effective permission is the union of named-resource, tag-policy and data-filter grants. A second, plain
SELECTgrant ongold.salesre-includessalaryfor the same principal. - Grant option and column filtering. The permissions reference states you "can't include the grant option if column filtering is applied", while the granting guide describes a narrower grant-option case: verify current console behaviour in your account before designing delegated column grants (AWS docs disagree here as of 2026-10-11; treat it as unverified).
- Partition-key columns cannot be column-filtered, and
IS [NOT] NULLis invalid on them: a schema that partitions byregionneedsregionto stay readable, which is exactly the fourth check above.
5. LF-Tags and tag-based access control (LF-TBAC)
5.1 What a tag is
"Each LF-Tag is a key-value pair, such as
department=salesorclassification=restricted. A key can have multiple defined values.": LF Developer Guide, Tag-based access control (LF-TBAC) (accessed 2026-10-11)
Tags attach to databases, tables and columns. They must be predefined (a key and its values are created with CreateLFTag before anything can carry them), and they are the only mechanism in this lesson that lets you grant on an attribute rather than on a named object.
5.2 Inheritance and the matching rules
"Tables inherit LF-Tags from databases and columns inherit LF-Tags from tables. Inherited values can be overridden" β¦ "the tag keys are combined using the AND operation, while the values are combined using the OR operation.": LF Developer Guide, Tag-based access control (LF-TBAC) (accessed 2026-10-11)
The two combination rules, stated once and tested forever:
- Different keys in one grant are AND-ed:
owner = data-platform AND class = internalmatches only resources carrying both. - Multiple values of the same key are OR-ed:
class = internal OR class = restrictedmatches either. - Example from the docs: the tag expression
content_type:Sales AND location:US"represents resources related to sales data in the US"; saved LF-Tag expressions are capped at 1,000 per account.
5.3 Three things TBAC changes about granting
- You grant on the tag, not the table. The principal's grant resource is an
LFTagPolicy(or anLFTagExpression), so tables created later, including crawler-created tables, are covered automatically once they inherit the tag. - You can grant the ability to tag.
ASSOCIATElets a principal attach a tag;DESCRIBElets them see it;GRANT_WITH_LF_TAG_EXPRESSIONlets them use it as a grant resource. This is the delegation primitive behind data meshes. - Permissions from all methods are unioned. AWS's own migration advice: "(Recommended) After verifying that principals have access to the correct resources through the LF-TBAC method, revoke permissions that were granted by using the named resource method." Verify first, revoke second: never the reverse.
5.4 Worked example E5: rebuilding the IAS compression with three tags
ESTATE (derived arithmetic, as of Oct 2026)
3 databases x 12 tables = 36 tables
4 principals with read access
NAMED-RESOURCE ROUTE
SELECT per table ....... 4 x 36 = 144 grants
DESCRIBE per database .. 4 x 3 = 12 grants
TOTAL .................. 156 statements (derived)
Re-org one team ........ re-issue up to 48 of them
LF-TBAC ROUTE (IAS shape: owner + class applied at the DATABASE)
Tag assignments ........ 3 databases x 2 keys = 6 assignments,
inherited down to 36 tables and their
columns (nothing per table)
Tag grants ............. 4 principals x tag policy = 4 grants
TOTAL .................. 10 statements, NONE of which names a table
AWS documentation worked example for the same idea:
5 assignments + 8 grants = 17 effective permissions
THE CARVE-OUT THAT NEVER DISAPPEARS
"but two analysts also need region = 'eu' rows only"
-> 2 named-resource + data-filter grants (data filters cannot ride
on tags), total 12 statements, with the exception LISTED so it
can be reviewedReading: the tag route's cost is flat in the number of tables and linear in the number of policies; the named route is linear in tables Γ principals. IAS reported the real-world version of this: "With Lake Formation tag-based access controls, IAS reduced hundreds of permission rules down to precisely two rules" (AWS Big Data Blog, 2021-09-23). Note where the exception list lands: row filters are exactly the feature that cannot be tag-driven, so a TBAC estate always carries a short, deliberate named-resource tail.
How to answer
Fill-in-the-blank exercise with 4 blanks. Type the missing words, then check your answer.
Fill in the LF-Tag names and the mechanics behind the IAS outcome:
IAS attached the blank and blank LF-Tag keys at the database level, relied on blank to carry them down to tables and columns, and expressed access as tag-based grants rather than blank rules.
Word Bank, drag words into the blanks above:
Hover a bar pair: named-resource grants scale as principals Γ tables (derived: 4 Γ 6 = 24 up to 4 Γ 36 = 144), while the tag route stays at 6 assignments + 4 grants = 10 regardless of table count (derived from the IAS shape of two keys applied at database level). The crossover is immediate, the tag route is already smaller at six tables, which is why AWS's tag-based example is quoted as operational simplification rather than as a security feature.
6. Data sharing: cross-account databases, external engines, trusted callers
6.1 Cross-account databases go through AWS RAM
"Lake Formation uses the AWS Resource Access Manager (AWS RAM) service to share the resource. If the grantee account is in the same organization as the grantor account, the shared resource is available immediately; if the grantee account is not in the same organization, AWS RAM sends an invitation to the grantee account to accept or reject the resource grant.": LF Developer Guide, Cross-account data sharing (accessed 2026-10-11)
Two grant methods exist, and AWS recommends one of them by name: Lake Formation tag-based access control (LF-TBAC) (recommended) versus named resources. The blog that documents the trade-off puts it plainly: TBAC "is recommended when many resources and entities are involved."
Prerequisites that are hard failures, not advice (LF Developer Guide, Cross-account prerequisites, accessed 2026-10-11):
- Revoke all Lake Formation permissions from
IAMAllowedPrincipalson the resource first: otherwise Lake Formation throwsAccessDeniedException. - The grantor must hold the AWS managed policy
AWSLakeFormationCrossAccountManager. - At least one user in the consumer account must be a data lake administrator to view shared resources; "other principals can't access shared resources until the data lake administrator grants them permissions."
- Cross-account grants must carry the grant option, because the consumer-side admin re-grants locally. "The principal who receives the resource share cannot share the resource with other principals."
Cross-account version settings (DataLakeSettings.Parameters.CROSS_ACCOUNT_VERSION) decide what can be shared: direct grants to an individual IAM principal in another account need version β₯ 3; hybrid-mode shares need β₯ 4; version 5 "enhances cross-account resource sharing enabling you to share unlimited number of tables to another account, eliminating previous resource association limits per resource type", is available "through the Lake Formation console or API", and downgrade is not supported once applied (AWS What's New, 2026-02-11; LF Developer Guide, accessed 2026-10-11).
6.2 Worked example E6: sharing gold.sales to an external account
PRODUCER 111122223333 -> CONSUMER 222233334444 (as of Oct 2026)
PRE-FLIGHT (all three are hard failures, not advice)
1. aws lakeformation get-effective-permissions-for-path \
--resource-arn arn:aws:s3:::acme-lake/gold/
-> if Super / IAMAllowedPrincipals appears, REVOKE it first
(Lake Formation throws AccessDeniedException otherwise)
2. producer caller holds the AWS managed policy
AWSLakeFormationCrossAccountManager
3. cross-account version: >= 3 for a direct IAM principal,
>= 4 for a hybrid-mode share, 5 (2026-02-11) for an
UNLIMITED number of tables per RAM resource share -
and downgrade is NOT supported once you upgrade
4. consumer account has at least ONE data lake administrator,
otherwise nobody there can even see the share
PRODUCER - the grant must carry delegation
aws lakeformation grant-permissions \
--principal DataLakePrincipalIdentifier=arn:aws:iam::222233334444:role/partner-analyst \
--resource '{"Table":{"CatalogId":"111122223333","DatabaseName":"gold","Name":"sales"}}' \
--permissions SELECT \
--permissions-with-grant-option SELECT
TRANSPORT
same AWS Organization ..... share appears immediately
external organization ..... AWS RAM invitation, must be accepted
CONSUMER SIDE (the step everyone forgets)
a. admin accepts the RAM share
b. create RESOURCE LINK gold_sales_shared in the consumer catalog
c. GRANT DESCRIBE on the link <- link grant only makes it visible
d. GRANT SELECT on the SHARED TABLE for role/partner-analyst
e. Athena query via the link -> vended temporary S3 credentials
LIMITS TO QUOTE
"The principal who receives the resource share cannot share the
resource with other principals." -> no re-sharing by the recipient
cross-account access logs appear in BOTH accounts, with the full
principal ARN only if the recipient opts in
Only inclusion lists (ColumnNames) are supported when granting to
an external account or organization - no ExcludedColumnNames routeChecks: (a) a grant attempted while IAMAllowedPrincipals still holds Super fails with AccessDeniedException; (b) a grant without --permissions-with-grant-option leaves the consumer admin unable to grant their own analysts anything; (c) granting only on the link leaves the table invisible to queries: link grant β target grant.
6.3 Trusted callers and the external-engine toggle
Lake Formation vends temporary credentials only to trusted callers. "Each of these AWS services is a trusted caller to Lake Formation, and Lake Formation provides access to data stored in Amazon S3 through temporary credentials": the integrated set being Athena, Redshift Spectrum, EMR and Glue (LF Developer Guide, Working with services, accessed 2026-10-11).
Anything else is opt-in, and the opt-in is a three-part switch in DataLakeSettings:
Setting | Role | Default posture |
|---|---|---|
AllowExternalDataFiltering | lets a third-party engine access unfiltered metadata and data-access credentials | must be enabled deliberately |
ExternalDataFilteringAllowList | account IDs of the allowed external engines | empty = nobody |
AuthorizedSessionTagValueList | session tag values a caller must present | the STS session tag key is LakeFormationAuthorizedCaller |
AllowFullTableExternalDataAccess | lets an engine get credentials without a session tag when the caller has full data access | false by default: keep it false |
"If you intend to analyze β¦ using third-party query engines, you must opt in to allow external engines to access data managed by Lake Formation.": LF Developer Guide, Set up AWS Lake Formation (accessed 2026-10-11)
A documentation discrepancy to be honest about: the DataLakeSettings API reference shows an example session tag key of LakeFormationTrustedCaller, while the third-party-engine guide and the custom-application blog both specify LakeFormationAuthorizedCaller. Two sources say the latter, so use it, but do not treat either name as uncontested.
6.4 Managed access and the administrator roles
Role | Can do | Cannot do (verified constraint) |
|---|---|---|
Data lake administrator | Register locations, create databases, run permission workflows, grant/revoke anything | "Cannot add other data lake administrators"; capped at 30 per account by default |
IAM administrator | Create users, roles, policies, and add data lake administrators | Cannot grant Lake Formation permissions unless also an LF admin |
Database / table creator | Implicit SUPER on what they create | Nothing implicit on objects they did not create |
Grantor with the grant option | Re-grant what they hold ( PermissionsWithGrantOption) | Can delegate only what was delegated to them |
LF-Tag / tag-expression creator | Create, update, delete tags and saved expressions | Implicit rights cover the tags themselves, not the data |
Two asymmetries are worth internalising:
-
Admin added later = zero implicit data access. "data lake administrators added after database creation can grant permissions but don't automatically have data access permissions such as SELECT or DESCRIBE. Administrators who create databases receive SUPER permissions on those databases."
-
Managed access is expressed as the grant option. The pattern, a platform team holding
PermissionsWithGrantOptionand domain teams re-granting within a scope, is how "grantable" self-service works without handing over the whole catalog. -
π Did you know? The registration role and the service-linked role are a real design choice: Lake Formation ships a service-linked role (
ServiceRoleForLakeFormationDataAccess) for zero-setup registration, but AWS's best-practices guide recommends registering with a customer-managed role when you expect to edit or scope that role later. Either way the caller still needslakeformation:GetDataAccesswithResource: "*", and adding it is "a no-op when no locations are registered, so it is safe (and recommended) to add upfront" (AWS-published Lake Formation best-practices guide, accessed 2026-10-11).
How to answer
Ordering exercise with 8 items. Move them into the correct order, then check your answer.
Order the steps that move one S3 location from IAM-only access to a governed Lake Formation grant, ending with an analyst query that succeeds:
β οΈ Cross-account ordering is the most common dead end. Revoke IAMAllowedPrincipals β grant with the grant option β (out-of-organization) the consumer accepts the RAM invitation β the consumer's data lake administrator creates a resource link β the administrator re-grants on the shared object, not just on the link. A grant made before the invitation is accepted appears to do nothing; a grant made with the IAMAllowedPrincipals permission still attached throws AccessDeniedException; and skipping the grant option leaves the consumer admin unable to grant local analysts anything at all.
7. Engine support matrix: who actually enforces what
"the actual filtering of columns in query responses is the responsibility of the integrated service. Lake Formation clients that support column-level filtering, including Amazon Athena, Amazon Redshift Spectrum, and Amazon EMR filter the data based on the column permissions registered with Lake Formation": LF Developer Guide, Limitations (accessed 2026-10-11)
Engine | Table | Column | Row / Cell | Caveat you must be able to state |
|---|---|---|---|---|
Athena SQL | Read/write | Yes | Yes | Cell-level needs Athena engine version 3; Athena query results locations cannot be registered, so results are always pure-IAM territory |
Athena Spark | Not supported | Not supported | Not supported | "Athena Spark doesn't support querying Data Catalog tables with Lake Formation permissions." |
Redshift Spectrum (provisioned cluster or Serverless) | Read/write | Yes | Yes | Data filters in Lake Formation govern Spectrum row/cell access; Redshift's own row/column policies on a datashare shared into Lake Formation are ignored: the LF admin must re-create them |
Spark on EMR (EC2) | Read/write | Yes | Yes | Securing the cluster itself stays your job |
Apache Hive on EMR (EC2) | Read/write | Yes | Not supported | Row and cell filters do not apply |
Hive on EMR Serverless / EMR on EKS | Not supported | Not supported | Not supported | Listed as unsupported in the services matrix |
AWS Glue ETL | Read/write | Glue 5.0+ read access | Glue 5.0+ read access | The limitations page still says "Currently, AWS Glue ETL doesn't support column filtering": treat 5.0+ read paths as supported and pre-5.0 and write paths as unsupported, and verify on your runtime |
Amazon QuickSight | Via Athena | Via Athena | Via Athena | Enterprise edition grants FGAC permissions to QuickSight users and groups; Standard edition grants to IAM roles (default aws-quicksight-service-role-v0) |
Custom / third-party engines | Opt-in | Opt-in | Opt-in | Session tag LakeFormationAuthorizedCaller plus the allow-list; never flip this on as a troubleshooting shortcut |
7.1 Worked example E7: placing eight engines on the matrix
For each engine: WHERE does it sit, and WHAT breaks if you assume otherwise?
(as of Oct 2026)
1. Athena SQL ................ table + column + row/cell
break: cell-level filters need engine v3;
query HISTORY is governed by workgroups,
not by Lake Formation
2. Athena Spark .............. NOT SUPPORTED
break: the notebook path simply cannot
query Lake Formation-permissioned tables
3. Hive on EMR Serverless .... NOT SUPPORTED
break: no enforcement surface at all
4. Glue 3.0 job .............. table only (pre-5.0 read path)
break: column filtering NOT enforced
inside the job - strip the column yourself
5. Glue 5.0 job .............. table + column + row/cell on READ
break: write path still unverified -
never publish a job that relies on it
6. Spark on EMR EC2 .......... full enforcement via the LF plugin
break: cluster hardening is still yours
7. Redshift Spectrum ......... full enforcement, including data filters
break: producer-side Redshift RLS/CLS
policies are IGNORED once a datashare is
shared into Lake Formation
8. QuickSight SPICE import ... enforcement happens at IMPORT time only
break: readers see the imported rows;
LF row filters do not travel into SPICERule of thumb derived from the matrix: Lake Formation publishes filtered metadata and scoped credentials; the engine prunes the response. Any engine outside that list either refuses the query or, worse, returns unfiltered data if you granted the external-engine opt-in.
- π Did you know? QuickSight's integration has an edition split that is easy to miss: Enterprise edition lets you "grant fine-grained access control (FGAC) permissions to individual QuickSight users and groups", while Standard edition grants go to IAM roles, with the default service role named
aws-quicksight-service-role-v0. Once the source bucket is registered, "Amazon S3 access settings in QuickSight are ignored, including scope-down IAM policies for users and groups": Lake Formation becomes the single source of truth (QuickSight and AWS Big Data Blog documentation, accessed 2026-10-11).
8. The IAMAllowedPrincipals default, and the migration off it
8.1 Why your grants appear to do nothing
"Lake Formation sets
Superpermission on all databases and tables in the Data Catalog to a group calledIAMAllowedPrincipalsby default. If this group permission exists β¦ all principals in your account will have access to the resource through the IAM principal policies for AWS Glue.": LF Developer Guide, Permissions reference (accessed 2026-10-11)
And the consequence, stated just as directly:
"These settings effectively cause access to Data Catalog resources and Amazon S3 locations to be controlled solely by AWS Identity and Access Management (IAM) policies. Individual Lake Formation permissions are not in effect.": LF Developer Guide, Changing the default settings for your data lake (accessed 2026-10-11)
So the default state of a brand-new or long-unmodified lake is: Lake Formation installed, but switched off. Your shiny grants are recorded, audited, and ignored.
Symptom | First check | Fix |
|---|---|---|
"My grants changed nothing; everyone can still read" | ListPermissions β is Super on IAMAllowedPrincipals still there? | Revoke it on that resource, or opt principals into hybrid mode |
"Grants work for some roles, not others" | Is the location registered? Is the principal opted in? | Register + opt in; both are required for vending |
"Row filter exists but an analyst still sees everything" | Do they hold a second plain SELECT grant, or a tag grant? | Effective permission is a union: revoke the widening grant |
"Analyst bypasses everything anyway" | Do they still hold s3:GetObject on the prefix? | Delete direct S3 permissions; Lake Formation does not revoke them for you |
"Cross-account grant throws `AccessDeniedException``" | IAMAllowedPrincipals on the shared resource | Revoke it before the cross-account grant |
8.2 Worked example E8: the documented migration, rehearsed
MICRO-ESTATE: 1 bucket, 2 databases, 6 tables, 3 roles
(as of Oct 2026; steps follow the LF upgrade guide and the
AWS-published transition guide)
STEP 1 INVENTORY
aws lakeformation list-permissions --resource-type TABLE
aws lakeformation get-effective-permissions-for-path \
--catalog-id 111122223333 \
--resource-arn arn:aws:s3:::acme-lake/gold/
plus CloudTrail GetTable / GetPartitions and any
insufficientLakeFormationPermissions entries
-> writes the target grant list
STEP 2 REPLICATE (safe no-op)
Re-create each found permission as an LF grant.
Nothing changes behaviour yet, because Super is still on
IAMAllowedPrincipals. Use this inert window to review.
STEP 3 ARM THE CALLERS
Add lakeformation:GetDataAccess, Resource = "*", to all three
roles. Safe to add before any registration exists.
STEP 4 ONE LOCATION AT A TIME
a) verify with GetEffectivePermissionsForPath
b) revoke Super from IAMAllowedPrincipals on that location's
databases and tables
c) register the location (registration role or service-linked role)
d) run the Athena canary query for all three roles
STEP 5 CLOSE THE DEFAULT
Turn off Use only IAM access control for new databases and
...for new tables in new databases, so nothing re-joins the
IAM-only plane.
STEP 6 DELETE THE OLD POLICIES
Remove the fine-grained IAM and S3 policies you replicated.
Leaving them is a permanent bypass of every filter you built.
ROLLBACK (proves the design is reversible)
Deregister the location, or in hybrid mode simply delete the
opt-in with delete-lakeformation-opt-in. IAM takes over again.
TWO PLANS AWS PUBLISHES
Plan #1 (Per Resource) - migrate table by table
Plan #2 (Per User) - migrate user by user via hybrid opt-ins
Both are reversible; pick per scenario, not per account.β οΈ The ordering rule that saves migrations: never revoke IAMAllowedPrincipals before you have validated that the Lake Formation grants work. Because staged grants are a no-op while the default Super grant exists, the safe sequence is always stage β validate β revoke β register β verify β delete old policies. Reversing the first two steps takes the lake offline for everyone the moment you revoke, with nothing in place to replace it.
9. The permission-check flow: a decision tree
This mirrors Lake Formation's documented hybrid-access workflow and is the fastest way to turn "it doesn't work" into a single check.
Read it as a diagnostic order: registration first, IAMAllowedPrincipals second, grant method third, entitlement type fourth. Skipping straight to "is my SQL right?" is the most expensive way to debug Lake Formation.
10. Worked Grant API and CLI sketch
10.1 The four call shapes you will actually write
[
{
"Principal": { "DataLakePrincipalIdentifier": "arn:aws:iam::111122223333:role/analyst-eu" },
"Resource": { "Table": { "CatalogId": "111122223333", "DatabaseName": "gold", "Name": "sales" } },
"Permissions": ["SELECT", "DESCRIBE"],
"PermissionsWithGrantOption": []
},
{
"Principal": { "DataLakePrincipalIdentifier": "arn:aws:iam::111122223333:role/analyst-eu" },
"Resource": {
"TableWithColumns": {
"CatalogId": "111122223333",
"DatabaseName": "gold",
"Name": "sales",
"ColumnWildcard": { "ExcludedColumnNames": ["salary"] }
}
},
"Permissions": ["SELECT"]
},
{
"Principal": { "DataLakePrincipalIdentifier": "arn:aws:iam::111122223333:role/finance-eu" },
"Resource": {
"LFTagPolicy": {
"CatalogId": "111122223333",
"TagKey": "class",
"TagValues": ["restricted", "internal"]
}
},
"Permissions": ["SELECT", "DESCRIBE"],
"PermissionsWithGrantOption": ["DESCRIBE"]
},
{
"Principal": { "DataLakePrincipalIdentifier": "arn:aws:iam::222233334444:role/partner-analyst" },
"Resource": { "Table": { "CatalogId": "111122223333", "DatabaseName": "gold", "Name": "sales" } },
"Permissions": ["SELECT"],
"PermissionsWithGrantOption": ["SELECT"]
}
]# Batch, the way a migration actually issues grants
aws lakeformation batch-grant-permissions \
--entries file://grants.json
# The same four shapes as one-liners
aws lakeformation grant-permissions \
--principal DataLakePrincipalIdentifier=arn:aws:iam::111122223333:role/analyst-eu \
--resource '{"Table":{"CatalogId":"111122223333","DatabaseName":"gold","Name":"sales"}}' \
--permissions SELECT DESCRIBE
aws lakeformation grant-permissions \
--principal DataLakePrincipalIdentifier=arn:aws:iam::111122223333:role/analyst-eu \
--resource '{"TableWithColumns":{"CatalogId":"111122223333","DatabaseName":"gold","Name":"sales","ColumnWildcard":{"ExcludedColumnNames":["salary"]}}}' \
--permissions SELECT
aws lakeformation grant-permissions \
--principal DataLakePrincipalIdentifier=arn:aws:iam::111122223333:role/finance-eu \
--resource '{"LFTagPolicy":{"CatalogId":"111122223333","TagKey":"class","TagValues":["restricted","internal"]}}' \
--permissions SELECT DESCRIBE \
--permissions-with-grant-option DESCRIBE
# Revoke is the same shape with a different verb - and because
# effective permissions are a UNION, revoke the WIDENING grant,
# not the narrow one.
aws lakeformation revoke-permissions \
--principal DataLakePrincipalIdentifier=arn:aws:iam::111122223333:role/analyst-eu \
--resource '{"Table":{"CatalogId":"111122223333","DatabaseName":"gold","Name":"sales"}}' \
--permissions SELECT
# Audit: what does this principal actually hold today?
aws lakeformation list-permissions \
--principal DataLakePrincipalIdentifier=arn:aws:iam::111122223333:role/analyst-eu
# Audit: what does this S3 path actually permit?
aws lakeformation get-effective-permissions-for-path \
--catalog-id 111122223333 \
--resource-arn arn:aws:s3:::acme-lake/gold/10.2 Worked example E9: reading back a grant correctly
INPUT: the analyst holds TWO grants on gold.sales
(a) DataCellsFilter gold_sales_eu_no_salary -> SELECT
(b) Table gold.sales -> SELECT (added later "just to be safe")
EFFECTIVE PERMISSION (union, as of Oct 2026)
rows ....... ALL rows, because grant (b) carries no predicate
columns .... salary VISIBLE, because grant (b) has no column filter
net result the policy in Section 4.3 is neutralised
DIAGNOSIS
list-permissions for role/analyst-eu shows both entries
-> the bug is not in the filter, it is in the extra grant
FIX
revoke-permissions on (b) only; keep (a)
then re-run the four Section 4.3 checks
COST OF THE AUDIT ... $0 (permissions, grants, revokes and
enforcement are all free - Lake Formation pricing page,
accessed 2026-10-11)Design note: because there is no deny statement in Lake Formation, least privilege means grant nothing by default and treat every new grant as a widening event that must be re-audited. ColumnWildcard.ExcludedColumnNames only ever narrows the entitlement it is written into.
2026 Updates (as of October 2026)
What changed in the Lake Formation governance story between late 2024 and October 2026: each line checked against a primary AWS source, and each one changes current behaviour:
- Governed Tables are finished. Writes and transactions stopped being supported after 2024-12-31, and
GetTableObjects/ListTransactionswere removed on 2025-02-17; the replacement AWS recommends is standard open-table formats (Iceberg, including Amazon S3 Tables) with Lake Formation permissions on top (AWS Big Data Blog, 2024-10-02; LF document history, accessed 2026-10-11). - S3 Tables catalog integration landed 2025-03-13. Managed Iceberg tables on S3 now register in Lake Formation for fine-grained permissions: note the catalog is the
s3tablescatalog, not the default Glue catalog, and callers needglue:GetCatalogon that catalog ARN. - Cross-account sharing version 5 (2026-02-11) removes the table cap. "Lake Formation sets up a single AWS Resource Access Manager resource share for an unlimited number of tables to another account", upgradeable through the console or API; downgrade is not supported. Direct-to-external-IAM-principal shares still need version 3+, hybrid-mode shares version 4+.
- Table permissions now extend to the underlying S3 data (2026-06-11).
GetTemporaryDataLocationCredentialslets Lake Formation-managed principals obtain temporary S3 access without carrying a separate S3 IAM policy: the cleanest answer yet to the "your analyst still holdss3:GetObject" bypass. - IAM Identity Center and trusted identity propagation for AI agents (2026-10-06). Bedrock agents can query Lake Formation-governed data under the end user's identity, which is the governance answer for agent access rather than a shared service role.
- Cross-Region access is not new. Querying another Region's Glue/Lake Formation tables through resource links has been documented since 2023-06-30; do not present it as a 2025 to 2026 feature. What is new is cross-account v5, table-permission-to-S3-data, and identity propagation.
- π Did you know? Two of these updates are quietly load-bearing for this lesson. ABAC (attribute-based access control via tags) was formally documented on 2025-04-17, which is why tag-expression grants now appear alongside named-resource grants in the same permission list; and the Governed Tables sunset means any "governed ACID sharing" requirement should now be answered with Iceberg plus Lake Formation grants, not with a retired table type.
Real-World Case Studies
AWS publishes what these permission models look like at production scale. Every figure below is customer- or AWS-claimed and unaudited, with the source and date named so you can check it: the examinable point is the pattern, not the marketing.
Case A, Integral Ad Science: hundreds of permission rules collapsed to two
Element | Detail |
|---|---|
Customer | Integral Ad Science (IAS), ad-tech verification |
Challenge | Self-service analytics across multiple business units, with privacy obligations under GDPR and CCPA, delivered without a ticket-based onboarding queue or per-table automation |
Services | Amazon S3 data lake (deployed 2020), AWS Glue Data Catalog, Amazon EMR, Amazon Athena, AWS Lake Formation tag-based access control, Okta as identity provider, one Athena workgroup per business unit |
Pattern | Two LF-Tag keys applied at the database level ( owner, class), carried by inheritance to tables and columns; grants issued on tags rather than on tables; per-BU workgroups carrying billing tags and query limits |
Outcome | "With Lake Formation tag-based access controls, IAS reduced hundreds of permission rules down to precisely two rules"; "Tags are inherited, so they only need to be applied at the highest level" |
Source | AWS Big Data Blog, Integral Ad Science secures self-service data lake using AWS Lake Formation, 2021-09-23 (digest 18, source S9; accessed 2026-10-11) |
The examinable pattern: TBAC's real payoff is operational. An ontology of a handful of inherited tags replaces an unmanageable matrix of per-table grants: the Section 5.4 arithmetic in production. Note also what IAS did not skip: column-level controls plus tagging carried the compliance answer, and the tag grant still had to coexist with whatever row-level exceptions the business needed.
Case B, FanDuel: column grants instead of copy-based masking
Element | Detail |
|---|---|
Customer | FanDuel Group, sports betting and gaming: presence across 50 states and over 8.5 million customers |
Challenge | Three Amazon Redshift data warehouses merged into one platform (warehouse + lake); the earlier design split PII into separate files tagged in S3, and each new data source cost 100 to 200 hours of development time |
Services | AWS Lake Formation (registered S3 location, column-based permissions), Amazon Redshift Spectrum external schemas bound per role, AWS Glue ETL writing Parquet plus crawlers, IAM/Redshift groups for entitlement sync |
Pattern | Two analyst roles: LimitedPIIAnalyst granted access to all columns, NonPIIAnalyst granted access to non-PII columns and assigned to analysts by default: one dataset, many views |
Outcome | "Lake Formation column-level access control allowed them to secure PII data, which otherwise would have taken a complex S3 tag-based approach. This saved 100 to 200 hours of development time for every new data source and data footprint." |
Source | AWS Big Data Blog, How FanDuel Group secures personally identifiable information in a data lake using AWS Lake Formation, 2020-12-21 (digest 18, source S10; accessed 2026-10-11) |
The examinable pattern: column-level grants kill copy-based masking. The requirement "hide PII from general analysts" is satisfied by one TableWithColumns exclusion on one cataloged table: no second copy of the data, no per-source tagging ritual. This is Section 4's cheaper alternative, and it is why FanDuel never needed row filters for that particular problem.
Case C, Morningstar: one tag ontology, two enforcement planes
Element | Detail |
|---|---|
Customer | Morningstar, investment research |
Challenge | Govern a data lake and an Amazon Redshift warehouse from one policy source, when Redshift does not consume tag ontology natively |
Services | AWS Lake Formation tag-based access control (TBAC) in the lake; Amazon Redshift for the warehouse; a purpose-built mapper translating tag expressions into Redshift GRANT/REVOKE statements per group |
Pattern | Single policy source β two enforcement planes; "we chose Lake Formation tag-based access control (TBAC)" and "built two components that handle mapping of the tag-based access controls to Amazon Redshift permissions" |
Source | AWS Big Data Blog, How Morningstar used tag-based access controls in AWS Lake Formationβ¦, 2023-04-06 (digest 12 source 49; digest 18 source S17; accessed 2026-10-11) |
The examinable pattern: the tag ontology is portable, the enforcement is not. Redshift supports resource-based entitlements but not tag-based ones, so a team that wants one governance model must build the translation; which is precisely the boundary the engine matrix in Section 7 is drawing.
Case | Lake Formation pattern it demonstrates | Section |
|---|---|---|
Integral Ad Science | LF-TBAC with database-level tags, inheritance and a two-rule outcome | 5 |
FanDuel | Column-level grants replacing an S3-tag/dual-file PII design | 4, 7 |
Morningstar | Tag ontology mapped onto a second plane (Redshift) | 5, 7 |
- π Did you know? All three cases date from 2020 to 2023 and should be presented that way: FanDuel's 8.5 million customers and IAS's "hundreds β two rules" are snapshots of those deployments at the time AWS published them, not current states of those platforms. Their architecture claims, column grants, inherited tags, one workgroup per business unit, remain the documented patterns; their numbers are historical.
Practice Questions
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
Before Lake Formation, a governed lake needed IAM identity policies, S3 bucket or prefix policies, and Glue catalog resource policies. What is the most accurate account of what Lake Formation adds?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
In hybrid access mode, an opted-in principal submits a query. Which statement correctly describes how the request is evaluated?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
You create Lake Formation grants on several tables, but every IAM principal in the account can still read every table through the Glue APIs. What is the most likely cause?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
An analyst must see every row of gold.sales but only the non-salary columns. Which single mechanism expresses this?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
A policy must show analysts only rows where region = 'eu' AND must hide the salary column. Which construction produces cell-level security?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
Which set of constraints on a Lake Formation row filter expression is correct as of October 2026?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
A table is covered by an LF-Tag grant, and you also want a region = 'eu' row filter for two analysts. What must you do?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
A grant names two LF-Tag keys, owner = data-platform AND class = internal, and a second grant names class = internal OR class = restricted. How are these evaluated?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
A producer account tries to share gold.sales with an external AWS account and receives AccessDeniedException from Lake Formation. Which sequence of fixes is correct?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
Which statement about engine enforcement of Lake Formation permissions is correct as of October 2026?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
An analyst's Lake Formation row filter works in Athena, but after a QuickSight dashboard imports the table into SPICE, readers see rows the filter should have removed. What is the correct explanation and remedy?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
Which comparative verdict for governing an AWS lakehouse is correct as of October 2026?
β οΈ Pattern traps for this lesson: walk this list before you design anything:
- "My grants do nothing" is almost always
IAMAllowedPrincipalsstill holdingSuper, an unregistered location, or a principal not opted in: in that order of likelihood. - Registration β hybrid. Registration is about credential vending; hybrid is about which permission model applies, and it is opted into per principal.
- Lake Formation does not revoke your S3 keys. Any principal holding
s3:GetObjecton the prefix bypasses every row filter you build; deleting those policies is a migration step. - There is no deny statement. Effective permission is the union of named-resource, tag-policy and data-filter grants: a second plain
SELECTre-includes everything you excluded. - Tags and data filters do not mix. Row/column/cell filters need a named-resource grant, so a tag-driven estate always carries a documented exception list.
- Filter arithmetic: expression < 2,048 characters, β€ 100 data filters per principal per table, needs
SELECTwith the grant option, no column-to-column comparison, no array/map, case-sensitive strings, no partition-key column filtering, and all-rows prevails over a concurrent predicate. - Cell-level needs Athena engine version 3 or Redshift Spectrum; Athena Spark, Hive on EMR Serverless and EMR on EKS are unsupported; Hive on EMR EC2 has no row/cell; Glue ETL column filtering only for 5.0+ read paths.
- QuickSight SPICE does not inherit Lake Formation row filters: the import is the entitlement boundary.
- Cross-account order: revoke
IAMAllowedPrincipalsβ grant with grant option β accept RAM share β resource link β re-grant on the shared object; direct principal shares need version 3+, hybrid shares 4+, and version 5 (2026-02-11) removes the per-share table cap with no downgrade. - Admin β data access: a data lake administrator added after a database exists gets no implicit
SELECTorDESCRIBE, cannot add other administrators, and there is a default cap of 30 per account.
Comparative Verdict: Lake Formation vs pure IAM + S3 policies vs a third-party governance platform
- Versus pure IAM and S3 bucket policies: IAM answers reachability (
glue:*,lakeformation:GetDataAccesswithResource: "*",s3:*) and bucket policies answer network and account perimeter; neither has a column or row dimension. AWS's own GA post says the older separate policies "only allowed table-level access", and the Spectrum governance blog says bucket policies stop scaling "when the number of combinations of access levels and users increase". Choose raw IAM for what IAM is good at, APIs, conditions, org scoping, and accept that every additional team costs another restatement of every prefix rule (Section 1.2: 156 statements β +48 per new team, derived). - Versus a third-party governance platform: Lake Formation ships the part a third party has to rebuild, trusted-caller credential vending into Athena, Redshift Spectrum, EMR and Glue, plus AWS RAM-driven cross-account sharing, and the permissions themselves cost $0, with only the Storage API (bytes scanned, rounded to the next MB, 10 MB minimum), Governed Tables and the storage optimizer billing. Choose a third party only when governance must span non-AWS catalogs or non-integrated engines; expect to re-implement the engine matrix in Section 7 yourself.
- Versus doing nothing (one policy family per team): the difference is not security level, it is shape. Named-resource Lake Formation grants are the same count as IAM entries until tags arrive; at that point the count stops depending on table volume: AWS's own example collapses to 17 permissions from 5 assignments + 8 grants, and IAS reports hundreds β two rules (AWS Big Data Blog, 2021-09-23).
- The one-sentence verdict: in October 2026, keep IAM for authentication and network perimeter, put every catalog object under Lake Formation grants with
IAMAllowedPrincipalsrevoked and locations registered, drive bulk reach with LF-Tags, carve out row and cell rules as named-resource data filters, share through RAM with the grant option, and reach for a third-party platform only where no integrated engine exists to do the filtering.
Key Takeaways:
- Lake Formation augments, never replaces, IAM: IAM authenticates and gates
glue:*/lakeformation:*(withGetDataAccesspinned toResource: "*"), Lake Formation decides visibility and vends prefix-scoped temporary credentials, and the engine performs the actual column/row/cell filtering. - Two orthogonal questions decide everything: is the location registered? (credential vending) and which permission model applies? (Lake Formation mode vs hybrid access mode, where opted-in principals need both planes and only
CREATE_TABLE,CREATE_PARTITION,UPDATE_TABLEare enforced by default). - The granularity ladder is catalog β database β table β column β row β cell, carried by exactly two mechanisms: named-resource grants (including
TableWithColumnscolumn filters) and data filters (DataCellsFilter), with LF-Tag grants as the bulk-scaling overlay. - Row-level = all-columns wildcard + predicate; column-level = column spec + all-rows; cell-level = both in one object. PartiQL
WHEREsyntax, < 2,048 characters, β€ 100 filters per principal per table, no column-to-column comparison, noarray/map, case-sensitive, partition keys cannot be column-filtered, and cell-level needs Athena engine v3 or Redshift Spectrum. - The worked analyst policy is one data filter (
region = 'eu'plusExcludedColumnNames: ["salary"]) granted withSELECT, plus a separateDESCRIBEfor visibility, and it must be re-audited after every new grant, because permissions union and there is no deny primitive. - LF-Tags are predefined key/value pairs on databases, tables and columns; inheritance runs database β table β column and is overridable; separate keys AND, values of one key OR; tags scale because grants name attributes, not tables: AWS's example: 5 assignments + 8 grants = 17 permissions; IAS: hundreds of rules β two (2021-09-23).
- Tags and data filters never combine: row/column/cell filters require the named-resource method, so a TBAC estate carries a deliberate, reviewable named-resource exception list.
- Cross-account sharing runs through AWS RAM: revoke
IAMAllowedPrincipalsfirst (elseAccessDeniedException), grantor holdsAWSLakeFormationCrossAccountManager, grant with the grant option, same-org is instant / out-of-org needs an invitation, the consumer's data lake administrator (default cap 30) creates a resource link and re-grants locally; versions 3+ for direct IAM principals, 4+ for hybrid, 5 (2026-02-11) for unlimited tables with no downgrade. - Trusted callers are the integrated engines by default; third-party engines need
AllowExternalDataFiltering+ExternalDataFilteringAllowList+ session tagLakeFormationAuthorizedCaller(the API reference'sLakeFormationTrustedCallerexample is a documented discrepancy), andAllowFullTableExternalDataAccessshould stay false. - Engine matrix: Athena SQL, Redshift Spectrum and Spark on EMR EC2 enforce everything; Athena Spark, Hive on EMR Serverless and EMR on EKS are unsupported; Hive on EMR EC2 has no row/cell; Glue ETL only for 5.0+ read paths; QuickSight goes through Athena (Enterprise = FGAC to users/groups, Standard = IAM roles such as
aws-quicksight-service-role-v0) and SPICE ignores Lake Formation row filters. - Migration is staged and reversible: inventory β replicate (a safe no-op) β add
GetDataAccessβ register β revokeIAMAllowedPrincipalsβ switch off the "Use only IAM access control" defaults β delete the old IAM/S3 policies; rollback is deregistering the location or deleting the opt-in. Never revoke before validating. - Case anchors: Integral Ad Science cut "hundreds of permission rules down to precisely two rules" with database-level
owner/classtags and inheritance (AWS Big Data Blog, 2021-09-23); FanDuel replaced a 100 to 200-hour-per-source S3-tag/dual-file PII design with two column-grant roles,LimitedPIIAnalystandNonPIIAnalyst, across 50 states and 8.5M+ customers (2020-12-21); Morningstar mapped one LF-TBAC ontology onto Redshift grants because Redshift does not consume tag entitlements natively (2023-04-06): AWS-published customer figures, date-stamped, unaudited.