Building a Governed AWS Landing Zone with Entra ID Federation
Learn how to build a governed AWS landing zone using Entra ID federation, IAM Identity Center, SCIM provisioning, and Service Control Policies for enterprise-grade security.

In this lesson
Table of Contents
Table of contents
Before you begin
- AWS Organizations fundamentals
- Entra ID enterprise application and SAML configuration
- IAM permission boundaries and SCP syntax
Track this tutorial
Choose your current status and tick each safety check as you complete it. Sign in to sync progress between devices.
Current status
Before you apply the change
Confirm these production-safety controls during the tutorial.
#Operational requirement
You have been assigned to build the AWS landing zone that replaces the current sprawl of standalone accounts. Before you touch a single organisational unit, understand why this exists. Every unmanaged AWS account is a liability. A project team spins up an account with an undocumented root email address, creates a couple of local IAM users because sorting out SSO “takes too long”, and six months later that account has an EC2 instance sitting behind an open security group, an IAM user holding AdministratorAccess with a password nobody has ever rotated, and zero CloudTrail visibility because no one enabled an organisation trail. When credential-stuffing bots find that account — and they will — there is no Conditional Access policy standing in the way, no Entra ID sign-in log to correlate against, and no way to tell an auditor who actually had access to production data on a given date.
Your job is to close that gap permanently. You will build a single AWS Organizations structure with Entra ID as the authoritative identity provider through AWS IAM Identity Center, enforce guardrails with Service Control Policies at the organisational-unit level, and route every provisioning and decommissioning action through change control. Get the SCPs wrong and you will lock the entire platform team out of production mid-incident, or leave a permission set wide enough that a support analyst can terminate an RDS instance by accident. Either mistake becomes a Sev1 ticket and a conversation with your CISO that nobody enjoys.
#Prerequisites and permissions
Confirm every item below before you open a single console tab. Do not skip the licensing check — half of the SSO failures a junior admin chases turn out to be a missing P1 seat.
| Requirement | Minimum standard | Why it matters |
|---|---|---|
| Entra ID licensing | P1 (P2 for risk-based Conditional Access) | Federation and Conditional Access both depend on it |
| Tenant role | Global Administrator or Application Administrator | Needed to register the enterprise application and configure SCIM |
| AWS management account | Runs no workloads | Holds billing and org policy only — a compromised management account is a compromised organisation |
| OU structure | Sandbox, Workloads (Production/NonProduction), Security | SCPs are only useful if they can target a tier, not the whole tree |
| Change process | Ticket and peer review required | Every SCP attach and permission set edit is a production change |
If your organisation is still running flat under the root OU, stop here and fix that first. SCPs attached at root apply everywhere, including the management account, and that is almost never what you want. Get the delegated administrator for IAM Identity Center assigned to your team specifically — do not leave it shared across every account owner, or you will spend your first month untangling who changed what.
#Implementation steps
#1. Register AWS as an Entra ID enterprise application
Add the gallery application for “AWS IAM Identity Center” rather than building a generic SAMLsg-aws-sso-eligible and manage membership through your existing joiner-mover-leaver process.
1Connect-MgGraph -Scopes "Application.ReadWrite.All"
2Get-MgApplicationTemplate -Filter "displayName eq 'AWS IAM Identity Center'"
3# Instantiate from the returned template ID, then set SSO mode to SAML
4Set-MgServicePrincipal -ServicePrincipalId -PreferredSingleSignOnMode "saml"In IAM Identity Center, point the external identity provider at the Entra ID SAML metadata URL and confirm the NameID format is set to persistent. Map Subject to user.userprincipalname, not the email address attribute — using email here is the single most common mistake and it breaks the moment someone’s UPN and primary SMTP address diverge after a name change.
#2. Enable SCIM provisioning
Manual account assignment does not scale and creates drift you will not notice until an access review. Configure SCIM provisioning from Entra ID so group membership changes propagate automatically into Identity Center.
1New-MgServicePrincipalSynchronizationJob -ServicePrincipalId -TemplateId "awsSSO"
2Start-MgServicePrincipalSynchronizationJob -ServicePrincipalId -SynchronizationJobIdScope the sync to only the security groups relevant to AWS access. Push every group in a 40,000-object tenant into Identity Center and you will hit AWS’s SCIM throttling limits, then spend an afternoon watching retry loops instead of fixing anything.
#3. Define permission sets by risk tier, not by team
Do not build a permission set per department. Departments reorganise; risk tiers do not. Build four sets and map Entra ID groups onto them per account, as below.

| Permission set | Entra ID group | Session duration | MFA requirement | Typical use |
|---|---|---|---|---|
| ReadOnlyAccess | sg-aws-readonly | 8 hours | Standard CA policy | Support, audit, observability |
| OperatorAccess | sg-aws-operator | 4 hours | MFA + compliant device | On-call engineers, deploys |
| AdministratorAccess | sg-aws-admin | 1 hour | MFA + compliant device + PIM approval | Platform team, change windows only |
| BreakGlassAdmin | local IAM, not federated | Manual revoke | Hardware token, sealed envelope | Entra ID tenant outage only |
Keep the break-glass tier deliberately outside federation. If your identity provider is down, your escape hatch cannot depend on it. Store those credentials in a physical safe or a hardware-backed vault under dual custody, and rotate them every single time they are used — no exceptions, no matter how minor the incident felt.
#4. Attach Service Control Policies at the OU level
SCPs are the actual guardrail. Attach a deny policy on the Workloads/Production OU that blocks local IAM user creation outside the management account, restricts deployment regions, and denies disabling CloudTrail.
1{
2 "Version": "2012-10-17",
3 "Statement": [
4 {
5 "Sid": "DenyLocalIAMUserCreation",
6 "Effect": "Deny",
7 "Action": ["iam:CreateUser", "iam:CreateAccessKey"],
8 "Resource": "*"
9 },
10 {
11 "Sid": "DenyRegionsOutsideApproved",
12 "Effect": "Deny",
13 "NotAction": ["iam:*", "organizations:*", "sts:*", "support:*"],
14 "Resource": "*",
15 "Condition": {
16 "StringNotEquals": { "aws:RequestedRegion": ["eu-west-1", "eu-west-2"] }
17 }
18 },
19 {
20 "Sid": "DenyCloudTrailTamper",
21 "Effect": "Deny",
22 "Action": ["cloudtrail:StopLogging", "cloudtrail:DeleteTrail"],
23 "Resource": "*"
24 }
25 ]
26}Get this policy peer-reviewed through change control before it goes anywhere near Production. Test it first against the NonProduction OU using aws organizations attach-policy. An SCP that denies the wrong action on the wrong OU does not throw a friendly warning — it silently breaks every deployment pipeline touching that OU until someone notices the build failures piling up.
#5. Turn on the organisation trail and Config aggregator
1aws cloudtrail create-trail --name org-trail --s3-bucket-name kby-cloudtrail-logs --is-organization-trail --is-multi-region-trail
2aws cloudtrail start-logging --name org-trailEnable AWS Config with an aggregator in the management account so tag-compliance and encryption rules run centrally instead of per-account. An untagged production resource should generate an AWS Config non-compliant finding routed straight into your existing ticketing queue — not discovered three months later during a cost review, by which point nobody remembers who created it.
#Change control and monitoring
Nothing in this landing zone gets built in one sitting, and nothing gets touched again without a ticket. Roll the SCPs out in three stages: attach and test against NonProduction for at least one full sprint, then attach to a single canary account in Production, then extend to the rest of the Production OU only after the canary has run clean for a week. Log every attach, detach, and permission set edit with the change ticket number in the commit message for the SCP repository, because that ticket number is what you hand an auditor.
Wire an alert from AWS Config non-compliance findings and from CloudTrail AccessDenied events on iam:CreateUser into your existing monitoring channel. A spike in denied CreateUser attempts usually means either an SCP is working exactly as designed, or a legacy automation script nobody documented is still trying to provision local users the old way. Both are worth knowing about immediately, not at the next quarterly review.
#Verification
Confirm federation works end to end before you announce the cutover to anyone. Sign in through the IAM Identity Center portal URL using a test account in sg-aws-operator and confirm it lands in the correct account with the correct permission set — not AdministratorAccess by default, which happens when a permission set assignment gets duplicated across accounts during a console copy-paste.
1aws sso-admin list-account-assignments --instance-arn --account-id --permission-set-arn
2aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=ConsoleLogin --max-results 5Cross-reference the CloudTrail login event timestamp against the Entra ID sign-in log for the same user and confirm the correlation ID chain is intact. This is exactly what your incident responders will rely on during a real investigation, so verify it now, not during a live Sev1 at three in the morning. Finally, attempt iam:CreateUser from inside a Production-OU account; it must return an explicit deny referencing the organisation policy, not a generic permissions error.
#Failure Modes
SCIM group sync lag is the most common support ticket you will generate. A user gets added to sg-aws-operator in Entra ID, tries to sign in five minutes later, and gets told they do not have access to the requested account, because the provisioning job runs on a schedule, not instantly. Check the synchronization job status before assuming the SCP is at fault.

SAML assertion failures usually present as an invalid response in the Identity Center console, and the root cause is almost always clock skew or a NameID format mismatch introduced when someone hand-edits the enterprise application’s claims after the gallery template was applied. Do not hand-edit claims. If a mapping change is genuinely needed, make it through the enterprise application’s SSO configuration blade and re-test against a non-production account first.
SCPs applied too broadly are the lockout scenario every junior admin fears. If a deny statement targets the wrong OU and happens to include sts:AssumeRole, federated sign-in for that entire OU stops working immediately — including for the platform team trying to fix it. This is precisely why the break-glass tier exists outside federation. Use it, detach the offending policy, then do the post-incident review afterwards, not during the outage.
Duplicate UPNs or stale email attributes in Entra ID cause SCIM provisioning errors that surface in the provisioning logs as attribute values containing disallowed characters. This is almost always a legacy on-premises AD sync artefact — a user renamed years ago whose UPN was never cleaned up. Fix it in the source directory. Fixing it in AWS only masks the underlying data-quality problem.
#Rollback
Keep every SCP version in source control with the account and OU it was attached to recorded in the commit message. You cannot roll back what you never versioned. If a policy attachment causes a lockout, use the break-glass credentials to detach it immediately.
1aws organizations detach-policy --policy-id --target-id
2aws organizations list-policies --filter SERVICE_CONTROL_POLICYFor a bad permission set assignment, revoke it rather than deleting the permission set outright — deleting the set also strips historical audit context from the Identity Center console, and that context is exactly what an auditor asks for.
1aws sso-admin delete-account-assignment --instance-arn --account-id --permission-set-arn --principal-id --principal-type GROUPIf SCIM provisioning is misbehaving and creating incorrect assignments faster than you can fix them, disable the synchronization job in Entra ID first to stop the bleeding, correct the source group membership, then restart it.
1Stop-MgServicePrincipalSynchronizationJob -ServicePrincipalId -SynchronizationJobIdNever roll back by deleting the enterprise application itself unless you are decommissioning the entire federation. That severs SCIM state and forces a full re-provisioning cycle across every linked account, which is a far longer outage than the one you were trying to fix.
#Operational Summary
A governed landing zone is not a one-off project you close out and forget. It is a standing control that needs quarterly access reviews, SCP drift detection, and a named owner who gets paged when AWS Config reports a non-compliant resource. Assign the break-glass rotation to a specific person with a calendar reminder, not to “whoever remembers” — that role always ends up unowned within two quarters. Run the permission set assignment list against Entra ID group membership monthly and reconcile any manual assignment that bypassed SCIM, because those are the ones nobody remembers granting six months later, and they are exactly what an audit finding is made of. The entire point of this architecture is simple: when someone asks who had production access on a given date and why, you produce a CloudTrail event, an Entra ID sign-in log, and a change ticket, and all three agree with each other without you having to reconstruct anything from memory.
#Learning Objectives
This enrichment supports a learner in demonstrating three practical competencies once the landing zone described in the article is in place: reasoning about SCP evaluation order across an OU hierarchy, tracing an identity from Entra ID group membership through SCIM into an IAM Identity Center permission set assignment, and executing a safe test-rollback cycle before any control reaches the Production OU.
A learner who has met these objectives can explain why an explicit Deny statement on a parent OU always overrides an Allow at a child OU or account, and can predict which of the four permission set tiers a given Entra ID group maps to without consulting documentation. They can also identify, from a CloudTrail AccessDenied event alone, whether the denial originated from an SCP, an IAM Identity Center permission set boundary, or a resource-based policy, which is the diagnostic skill most junior administrators lack when a Sev1 ticket lands.
- Explain SCP inheritance and explicit-deny precedence across an Organizations OU tree
- Trace a user from an Entra ID security group through a SCIM sync cycle to an active AWS session
- Distinguish an SCP-originated AccessDenied from a permission-set-originated one using CloudTrail event fields
- Design and execute a canary-then-widen rollout for a new SCP with a documented rollback step
#Worked Example
Consider a scenario for verification purposes: an engineer is added to the sg-aws-operator security group in Entra ID at 09:00. The SCIM synchronization job, scheduled on its default interval, has not yet run, so at 09:05 the engineer attempts to sign in through the IAM Identity Center portal and receives an access-denied message at the account-selection stage rather than at the login stage itself. This distinction matters: a failure at login indicates a SAML assertion problem, while a failure at account selection after successful login indicates the permission set assignment has not yet propagated.
To validate the cause rather than guess, an administrator checks the synchronization job's last-run timestamp and status in the Entra ID enterprise application's provisioning report before touching any AWS-side configuration. If the job shows a recent successful run and the user still cannot select the account, the next validation step is to query the account assignment list for that account and permission set ARN and confirm the group principal, not an individual user principal, is present — a missing group entry usually means the group-to-permission-set mapping was created against the wrong Entra ID group object ID during setup.
If an administrator instead jumps straight to manually assigning the user's individual principal to the permission set to unblock them quickly, that manual assignment becomes exactly the kind of SCIM-bypassing drift the article's Operational Summary warns against, and it will surface as an unexplained anomaly during the monthly reconciliation between permission set assignments and Entra ID group membership. The correct remediation is to wait for the next scheduled sync or trigger it manually from the enterprise application blade, confirm the group assignment resolves correctly, and only fall back to a manual assignment under a logged exception with a ticket reference and a scheduled removal date.
Rollback in this scenario is limited to removing any manual assignment created as a stopgap: the administrator revokes the individual principal's account assignment once the group-based assignment is confirmed active, and records both the temporary grant and its removal in the change ticket so the audit trail shows no unexplained gap.
#Practice Exercise
Using a non-production Entra ID tenant and a sandbox AWS Organizations account (never against Production), reproduce and document the following without executing anything against a live estate: identify which OU an SCP denying ec2:TerminateInstances should attach to so that it protects Workloads/Production without also blocking the Security OU's incident-response tooling, and write out the specific condition key you would add to scope the deny to only non-break-glass principals.
Second, walk through the validation sequence you would run after attaching that policy to the NonProduction OU only: list the policies attached to the target OU to confirm attachment, attempt the denied action from a test principal in that OU to confirm the deny fires with a reference to the specific SCP rather than a generic authorization failure, and attempt an unrelated allowed action from the same principal to confirm the policy has not over-broadly blocked adjacent permissions.
Third, write the rollback procedure you would follow if the canary test in step two showed the deny firing against an unintended action: detach the policy from the OU, confirm via the policy-attachment list that no OU still references it, and note in the change ticket the specific statement Sid that needs correction before any re-attachment attempt. Do not proceed to re-attach until the corrected policy has been reviewed by a second person, consistent with the change-control principle described in the source material.
Comments
Add a thoughtful note on Building a Governed AWS Landing Zone with Entra ID Federation. Comments are checked for spam and held for moderation before appearing.
Related articles
Cloud Infrastructure and Operations
How to Validate a Cloud Infrastructure Task in Amazon Web Services
Learn to design, validate and safely roll back a bounded AWS Cloud Infrastructure and Operations task using read-only checks and a reversible test exercise.
Cloud Infrastructure and Operations
Enforcing AWS Resource Tagging with Tag Policies and SCPs
A junior-friendly SOP for enforcing mandatory AWS resource tags using Organizations tag policies, a preventive SCP, and AWS Config compliance checks.
Systems Engineering
Engineering Tech Fundamentals for Predictable Linux Operations
A bounded systemd service workflow on Linux: unit architecture, sequential implementation, observable validation, common failure modes, least-privilege security and a rehearsed rollback path.
Security & Operations
TOCTOU Race Conditions in Admission Webhooks
resourceVersion snapshots and subresource rule gaps create a TOCTOU race condition that lets attackers bypass Kubernetes admission webhooks.
Discover more
Graduate Learning
Ops Playbook
- PlaybookA Safer Identity & Passwordless Operating Model for Microsoft Entra ID
- PlaybookReplacing Manual Multi-Cloud Work with a Verifiable AWS Workflow
- PlaybookA Practical Workflow for Serverless Edge Runtimes with AWS Lambda
- PlaybookBuilding a Safer Passwordless Operating Model with Microsoft Entra ID
Lexicon Definitions
Learn More About KBY
About KBY
Learn about our mission, editorial standards, and commitment to trusted engineering knowledge.
Why Trust KBY
Explore the processes and policies that ensure our publications are accurate, useful, and responsible.
Newsletter
Get our latest editorial publications, research and practical insights sent directly to your inbox.
Was this useful?
Build practical engineering skills.
Receive new lessons, learning paths, practical exercises and early-career guidance.