- Newest
- Most votes
- Most comments
The supported pattern is one IAM role per Airflow role, with your service assuming the correct role at request time. Custom Airflow roles always require a per-user Airflow record; IAM alone cannot carry them.
https://docs.aws.amazon.com/mwaa/latest/userguide/security-iam.html
https://docs.aws.amazon.com/mwaa/latest/userguide/security_iam_service-with-iam.html
Hi Malhar,
You asked to confirm rather than assume, so I'll separate what the documentation states from what I'm inferring, and give you a test that settles the open part in about ten minutes.
Direct answers first:
- Probably yes, but not through the IAM policy — and your premise about why it's fixed is the part I'd revisit. See below.
- Role-per-Airflow-role works, but it may not be necessary, and it's not the only way to vary the identity.
- Yes, confirmed. A per-identity Airflow user record is always required for custom roles. IAM alone cannot carry one.
- Role-per-team scales poorly past a few dozen teams. There's a better shape, and the AWS-published automation pattern has a caveat that matters for you specifically.
- No, confirmed — nothing exists and you didn't miss it.
Your premise is slightly off, and it changes the answer
You wrote that the Airflow role comes from the resource ARN and "that ARN is static per policy". The first half is only true for the five default roles, and the second half isn't the binding constraint.
Two separate mechanisms are in play, and conflating them is what makes this look unsolvable:
Mechanism A — resource ARN → default role. The role/<env>/<airflow-role> segment selects which of Admin, Op, User, Viewer, Public the session gets. Only those five are valid values (Accessing an Amazon MWAA environment). Note the tutorial's wording: MWAA maps IAM principals to "one or more" default roles, so a policy can list several. But that doesn't give you request-time selection: per this re:Post article, when the resource is ambiguous ("Resource": "*") MWAA "defaults to the most restrictive role". Resolution is deterministic, not selectable.
Mechanism B — IAM identity → Airflow user record → custom role. Your custom roles don't come from IAM at all. They're attached to the auto-provisioned Airflow user record, and MWAA does not strip them. From Tutorial: Restricting an Amazon MWAA user's access to a subset of DAGs:
Any of the 5 default roles (such as Admin) not authorized by IAM which are added using the Apache Airflow UI will be removed on next user log-in.
Only the five default roles get reconciled against IAM on each login. Custom roles survive — which is exactly why your working setup works, and it's worth understanding that it works by omission rather than by design.
So the real question isn't "can one IAM role point at several Airflow roles". It's "can one IAM role produce several distinct Airflow user records?" Because each record can carry a different custom role.
Why I think the answer is yes
CreateWebLoginToken returns two identity fields that are rarely looked at:
AirflowIdentity— "The user name of the Apache Airflow identity creating the web login token." Max length 64.IamIdentity— "The name of the IAM identity creating the web login token. This might be an IAM user, or an assumed or federated identity. For example,assumed-role/Admin/your-name."
That example is the interesting part. For an assumed role the identity MWAA sees is assumed-role/<RoleName>/<SessionName> — it includes the role session name. The tutorial separately shows the Airflow user's name following the IAM principal name in the pattern user/mwaa-user, i.e. the Airflow record is derived from the identity string.
If the derivation includes the session name, then one IAM role assumed with N different RoleSessionName values yields N distinct Airflow user records, each independently assignable a different custom role. One IAM role, request-time selection, no role-per-team sprawl.
I want to be clear that this is an inference from the documented IamIdentity format, not a documented guarantee. But it's cheap to verify, and MWAA hands you the answer directly.
The decisive test
Assume your single role twice with different session names, and compare what MWAA reports back:
# Session 1 aws sts assume-role \ --role-arn arn:aws:iam::<account-id>:role/mwaa-multitenant \ --role-session-name locational-team # export the three credentials, then: aws mwaa create-web-login-token --name <env-name> \ --query '{airflow:AirflowIdentity, iam:IamIdentity}' # Session 2 — same role, different session name aws sts assume-role \ --role-arn arn:aws:iam::<account-id>:role/mwaa-multitenant \ --role-session-name financial-team aws mwaa create-web-login-token --name <env-name> \ --query '{airflow:AirflowIdentity, iam:IamIdentity}'
If the two AirflowIdentity values differ, you're done: log in once with each so MWAA provisions both records, attach LocationalOperator to one and FinancialOperator to the other, and your service picks the tenant by setting RoleSessionName from the SSO group claim. If they're identical, the session name is discarded and you fall back to role-per-team as in your question 2.
Please post the result either way — this isn't documented anywhere I can find, and it's the crux of the question.
Two things to get right if it works
Set the session name from the validated claim, never from anything user-supplied. With this design the session name is the authorization decision, so a caller who can influence it can choose their tenant. Constrain it in the role's trust policy with the sts:RoleSessionName condition key so even a compromised service can only mint session names from an allowlist. That gives you defence in depth rather than relying solely on your FastAPI code being correct.
Mind the 64-character limit on AirflowIdentity, since assumed-role/<RoleName>/<SessionName> has to fit whatever transformation MWAA applies.
New session names provision empty records. A previously unseen session name creates an Airflow user with only the IAM-derived default role and no custom role, so it sees nothing until someone attaches the custom role. That's an argument for a fixed, small set of session names — one per team — rather than one per end user. Which is what you want anyway: the record count scales with teams, not with headcount.
Where I'd extend the other answer
The other answer's two claims are directionally right, and the second one is straightforwardly correct — custom roles do require a per-user Airflow record, and IAM cannot carry them. That's confirmed twice over: by the tutorial, and explicitly in this AWS Big Data blog: "IAM Based access control to Amazon MWAA works for Apache Airflow default roles. For custom roles, the Admin user can assign the custom role using the Apache Airflow UI."
Where I'd push back is on "the supported pattern is one IAM role per Airflow role" being presented as settled. Nothing in the two linked pages establishes that a single IAM role cannot serve multiple Airflow identities, because neither page addresses session-name derivation at all. It's a reasonable default assumption, but it's the assumption you said you didn't want to build on, and it's testable.
Question 5, definitively: no request-time parameter
Confirmed from the API reference. CreateWebLoginToken takes exactly one URI parameter, the environment Name, and "The request does not have a request body". There is no field for an intended Airflow role, and no undocumented one to find. Your reading was right.
Question 4, scaling
Role-per-team. The default quota is 1,000 IAM roles per account (raisable to 5,000), so you won't hit a hard wall, but you will get a role and policy to provision, review and audit per team, plus a trust-policy edit on every team change. Fine at ten teams, tiresome at fifty.
Single role, session-name-per-team. If the test above passes, this collapses the IAM surface to one role and one trust policy. Team onboarding becomes "add a session name to the allowlist and attach a custom role to the new Airflow record" — no IAM change at all.
Automating the Airflow side. This is where the real toil is: each new team needs a custom role created by copying Viewer, then per-DAG permissions maintained as DAGs come and go. AWS published a tag-based automation for exactly this in the blog linked above, where DAG tags drive role permissions on a schedule.
Read this caveat before you invest in it: that solution's own prerequisites state it requires "version 2.7.2 or later, not supported in Airflow 3.0". You're on 3.2.1, so it does not apply to you as written. The implementation writes directly to the FAB metadata tables (ab_role, ab_permission_view_role) from inside a DAG, and Airflow 3 isolates task code from the metadata database — task execution goes through the Task Execution API rather than holding a DB session. That's my explanation for the incompatibility rather than something AWS states, but either way the stated support boundary excludes your version. The idea still transfers; you'd need to drive the same permission updates from outside the environment instead of from a DAG.
Hard multi-tenancy. If teams must not share an environment at all, separate MWAA environments give you real isolation at real cost. Worth naming as the boundary of the RBAC approach rather than something to reach for first.
Airflow 3.2.1 specifics for the redirect service you're building
Three things that will affect your FastAPI implementation, from the re:Post article above:
- The login path changed in MWAA 3.x. It's now
/pluginsv2/aws_mwaa/login, not the 2.x/aws_mwaa/login. The REST API base also moved from/api/v1to/api/v2. If you've been following 2.x examples, this is the first thing that will break. - The flow is
create_web_login_token→GET https://{WebServerHostname}/pluginsv2/aws_mwaa/login?token={WebToken}with redirects disabled → read the_tokencookie from the response. The article has a complete working Python example. - Sessions cache the role mapping. "Existing sessions use the old role mapping, so you must create a new session after updating the IAM policy." For you this means a user's tenant is fixed for the life of their session, so switching tenants requires minting a fresh token, not reusing the cookie.
Also: don't use "Resource": "*" anywhere in this policy, for the reason above — MWAA resolves it to the most restrictive role and you'll spend an afternoon debugging a Forbidden that has nothing to do with your code.
One last practical note: the web login token is short-lived and intended for immediate exchange, so mint it inside the request that redirects rather than caching it. I haven't verified the exact TTL, so measure it before you build retry logic around it.
Post back the two AirflowIdentity values from the test and I'll help you work through whichever branch you land in.
answered 19 days ago
Relevant content
asked 10 months ago
asked 10 months ago
