Skip to main content

Option C — Combined (group + email) access

Two-layer security: Lake Formation tags control which tables a group can access (table-level), and data cell filters further restrict rows by user email (row-level).

  • How it works: Tag-Based Access Control (TBAC) for table isolation, plus email-based cell filters for row isolation within the allowed tables.
  • Best for: multi-department setups where different groups access different tables, and within those tables users see only their own data.
  • Requires: everything Option B requires, namely the sts:TagSession permission on every IAM role and the email scope on the Cognito app client.

Complete Set up Amazon Cognito first, including the email scope and read attribute on the app client.

Step 1: Prepare Lake Formation

  1. In the Lake Formation Console go to Data lake locationsRegister location. Register the S3 paths where your data resides (e.g. s3://my-athena-data-bucket/) and select the IAM role Lake Formation should use to access the data (or use the service-linked role).
  2. Under Administrative roles and tasksData lake administrators, add your admin IAM user or role.

Step 2: Tag tables by group (table-level layer)

  1. Go to LF-TagsAdd LF-Tag and create tags that model your access dimensions, for example key Department with values finance, hr, engineering.
  2. Assign tags to your databases and tables under Data lake permissionsLF-Tags → select a database or table → Assign LF-Tag. For example, assign Department=finance to finance_table and Department=hr to hr_table.
note

AWS Lake Formation allows only one LF-tag value per key per resource, so you may need separate tables per department. Assign the department tag to each table, then apply the email-based data cell filter within each table.

Step 3: Create email-based data cell filters (row-level layer)

For each tagged table, go to Data filtersCreate new filter and configure:

Filter name: email_row_filter
Target database: my_analytics_db
Target table: finance_table
Row filter expression: owner_email = '${session:UserEmail}'

The ${session:UserEmail} variable is resolved to the authenticated user's email address at query time.

Step 4: Grant permissions

For each Cognito group's IAM role:

  1. Go to Data lake permissionsGrant and select IAM users and roles → the role.
  2. Under LF-Tags or catalog resources, select the database and the table that carries the group's tag.
  3. Under Data filters, select the email cell filter for that table.
  4. Grant SELECT.

The tag decides which tables the role can reach; the filter decides which rows inside them.

Step 5: Add sts:TagSession to every IAM role

Add this statement to each role's permissions policy so the UserEmail session tag reaches Lake Formation:

{
"Sid": "AllowTagSession",
"Effect": "Allow",
"Action": "sts:TagSession",
"Resource": "*"
}
caution

Without sts:TagSession, the ${session:UserEmail} variable will not resolve and queries will silently return zero rows. Also confirm the Cognito App Client has email in both AllowedOAuthScopes and ReadAttributes.

What each user sees

Consider a setup with two departments and email-based row filtering:

  • finance_analysts group → Athena-FinanceRole → LF-Tag grants access to finance_table
  • hr_viewers group → Athena-HRRole → LF-Tag grants access to hr_table
  • Data cell filter owner_email = '${session:UserEmail}' on both tables
  • alice@example.com is in finance_analysts, assigned to rows 1, 2, 3 in finance_table
  • bob@example.com is in hr_viewers
  • dave@example.com is in finance_analysts, assigned to rows 4, 5, 6 in finance_table
UserQueryTBAC checkEmail filterResult
aliceSELECT * FROM finance_table✅ PASS (finance group has access)owner_email = 'alice@example.com'Sees rows 1, 2, 3
aliceSELECT * FROM hr_table❌ DENIED (finance group has no access)Table is invisible
bobSELECT * FROM finance_table❌ DENIED (hr group has no access)Table is invisible
bobSELECT * FROM hr_table✅ PASS (hr group has access)owner_email = 'bob@example.com'Sees only bob's rows
daveSELECT * FROM finance_table✅ PASS (finance group has access)owner_email = 'dave@example.com'Sees rows 4, 5, 6 (different from alice)

TBAC controls which tables a user can see, and email-based cell filters control which rows within those tables.

Next step

Connect to Abacus.AI and use in ChatLLM.