expert 55 min read aws Updated: 2025-07-24

Identity Management (IAM)

Manage AWS IAM at enterprise scale with policy-as-code, attribute-based access control (ABAC), least privilege principles, and automated governance.

πŸ“‹ Prerequisites

  • Expert knowledge of core IAM concepts (roles, policies, trust relationships, evaluation logic).
  • Experience with a corporate Identity Provider (IdP) like Okta, Azure AD, or Google Workspace.
  • Advanced proficiency with Terraform for deploying identity and access controls.
  • Familiarity with multi-account strategies and AWS Organizations.

πŸ’‘ From Static Roles to Dynamic Access

Enterprise IAM is no longer about managing thousands of static IAM users and roles. The modern paradigm is to centralize human access through **AWS IAM Identity Center**, federating with your corporate IdP. This approach uses dynamic, attribute-based policies (ABAC) to grant fine-grained, just-in-time access at scale, dramatically reducing operational overhead and improving security posture.

🏷️ Topics Covered

aws iam at scaleattribute-based access control awsiam permissions boundariesaws sso identity center terraformaws least privilege automationpolicy as code iam

The Modern IAM Paradigm: IAM Identity Center

For human access, direct IAM users are an anti-pattern in modern cloud environments. **IAM Identity Center** (formerly AWS SSO) is the recommended best practice for managing human access across your entire AWS Organization.

Legacy IAM Model

  • IAM Users created per-person.
  • Long-lived access keys and passwords.
  • Complex web of cross-account IAM roles.
  • Manual, per-account access management.
  • Difficult to audit and scale.

Modern Identity Center Model

  • Identities managed in your corporate IdP.
  • Temporary credentials via SAML/OIDC federation.
  • Centralized "Permission Sets".
  • Assign users/groups to accounts centrally.
  • Scalable, auditable, and secure.

Implementing Attribute-Based Access Control (ABAC)

While Role-Based Access Control (RBAC) is common, it often leads to "role explosion." **ABAC** is the modern strategy for dynamic permissions at scale. Access is granted based on attributes (tags) of the user (principal) and the resource.

🎯 The ABAC Principle

You write a single, dynamic policy that says, "A principal can manage any resource that has the same 'project' tag as they do." Your IdP passes user attributes (like `project=blue-team`) to AWS as session tags, which are then used in the policy evaluation.

Example: ABAC Policy for Project-Based EC2 & S3 Access

This single IAM policy, attached to a generic Permission Set in Identity Center, dynamically allows principals to manage resources tagged with their assigned project.

🏷️ JSON: Dynamic ABAC Policy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowEC2ActionsOnProjectResources",
            "Effect": "Allow",
            "Action": [
                "ec2:StartInstances",
                "ec2:StopInstances",
                "ec2:RebootInstances",
                "ec2:TerminateInstances"
            ],
            "Resource": "arn:aws:ec2:*:*:instance/*",
            "Condition": {
                "StringEquals": {
                    "ec2:ResourceTag/Project": "${aws:PrincipalTag/Project}"
                }
            }
        },
        {
            "Sid": "AllowS3ActionsOnProjectResources",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::my-project-data-bucket/*",
            "Condition": {
                "StringEquals": {
                    "s3:ExistingObjectTag/Project": "${aws:PrincipalTag/Project}"
                }
            }
        },
        {
            "Sid": "AllowListingResources",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances",
                "s3:ListBucket"
            ],
            "Resource": "*"
        }
    ]
}

Enforcing Least Privilege with Permissions Boundaries

A **Permissions Boundary** is an advanced IAM feature that sets the *maximum* permissions an identity-based policy can grant to a role or user. It's a critical tool for safely delegating permissions to development teams.

Example: Delegating Role Creation for a Lambda Developer

Here, we allow a developer to create roles for their application, but we enforce a boundary that ensures any role they create can *never* escalate privileges beyond what's needed for a simple Lambda function.

βœ… JSON: Developer Policy to Create Roles with a Boundary

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowRoleCreationWithBoundary",
            "Effect": "Allow",
            "Action": [ "iam:CreateRole", "iam:AttachRolePolicy" ],
            "Resource": "arn:aws:iam::ACCOUNT_ID:role/app-lambda-*",
            "Condition": {
                "StringEquals": {
                    "iam:PermissionsBoundary": "arn:aws:iam::ACCOUNT_ID:policy/LambdaDeveloperBoundary"
                }
            }
        },
        {
            "Sid": "AllowPassingRole",
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": "arn:aws:iam::ACCOUNT_ID:role/app-lambda-*",
            "Condition": {
                "StringEquals": {"iam:PassedToService": "lambda.amazonaws.com"}
            }
        }
    ]
}

πŸ›‘οΈ JSON: The Enforced Lambda Permissions Boundary

This policy defines the "walls" of the sandbox. Any role created with this boundary can never gain permissions beyond what is listed here.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "MaxPermissionsForAppLambdas",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "s3:GetObject"
            ],
            "Resource": "*"
        }
    ]
}

Automating IAM as Code with Terraform

At scale, your entire identity configurationβ€”permission sets, assignments, policiesβ€”should be defined as code for versioning, auditing, and automated deployment.

πŸ—οΈ HCL: Managing IAM Identity Center with Terraform

This code defines a "ReadOnly" and a "PowerUser" Permission Set and assigns them to different groups for a specific AWS account.

variable "identity_center_instance_arn" { type = string }
variable "target_account_id" { type = string }
variable "readonly_group_id" { type = string }
variable "poweruser_group_id" { type = string }

# 1. ReadOnly Permission Set
resource "aws_ssoadmin_permission_set" "readonly" {
  name             = "ReadOnlyAccess"
  instance_arn     = var.identity_center_instance_arn
  session_duration = "PT8H"
}

resource "aws_ssoadmin_managed_policy_attachment" "readonly_policy" {
  instance_arn       = var.identity_center_instance_arn
  permission_set_arn = aws_ssoadmin_permission_set.readonly.arn
  managed_policy_arn = "arn:aws:iam::aws:policy/ReadOnlyAccess"
}

# 2. PowerUser Permission Set with Boundary
resource "aws_ssoadmin_permission_set" "poweruser" {
  name             = "PowerUserWithBoundary"
  instance_arn     = var.identity_center_instance_arn
  session_duration = "PT4H"
}

resource "aws_ssoadmin_managed_policy_attachment" "poweruser_policy" {
  instance_arn       = var.identity_center_instance_arn
  permission_set_arn = aws_ssoadmin_permission_set.poweruser.arn
  managed_policy_arn = "arn:aws:iam::aws:policy/PowerUserAccess"
}

resource "aws_ssoadmin_permissions_boundary_attachment" "poweruser_boundary" {
  instance_arn       = var.identity_center_instance_arn
  permission_set_arn = aws_ssoadmin_permission_set.poweruser.arn
  permissions_boundary {
    customer_managed_policy_reference {
      name = "MyCompanyDeveloperBoundary"
      path = "/"
    }
  }
}

# 3. Account Assignments
resource "aws_ssoadmin_account_assignment" "readonly_assignment" {
  instance_arn       = var.identity_center_instance_arn
  permission_set_arn = aws_ssoadmin_permission_set.readonly.arn
  principal_id       = var.readonly_group_id
  principal_type     = "GROUP"
  target_id          = var.target_account_id
  target_type        = "AWS_ACCOUNT"
}

resource "aws_ssoadmin_account_assignment" "poweruser_assignment" {
  instance_arn       = var.identity_center_instance_arn
  permission_set_arn = aws_ssoadmin_permission_set.poweruser.arn
  principal_id       = var.poweruser_group_id
  principal_type     = "GROUP"
  target_id          = var.target_account_id
  target_type        = "AWS_ACCOUNT"
}

Troubleshooting Advanced IAM Scenarios

IAM debugging requires thinking about the entire policy evaluation chain, from your IdP to the resource.

❌ ABAC Policy Not Working as Expected

  • Symptom: A user with the correct `Project` tag cannot access a resource with the same tag.
  • Root Cause Checklist:
    1. **IdP Attribute Mapping:** The most common issue. In IAM Identity Center, verify that the attributes being sent from your IdP (e.g., Okta, Azure AD) are correctly mapped to "Tags for access control" in the AWS configuration.
    2. **Tag Casing:** Tags are case-sensitive. `Project` is not the same as `project`. Ensure the tags on the principal and the resource match exactly.
    3. **Session Duration:** If the user assumed the role before the tags were updated in the IdP, their session might not have the new tags. Ask them to sign out and sign back in to get a new session with the updated attributes.

πŸ›‘οΈ Permissions Boundary is Overly Restrictive

  • Symptom: A developer attaches an identity policy to a role, but the permissions don't work.
  • Cause: The effective permissions of a role with a boundary are the *intersection* of what the identity policy and the boundary policy allow. Even if the identity policy allows `ec2:TerminateInstances`, if the boundary policy does not, the action will be denied.
  • Solution: Use the IAM Policy Simulator in the AWS console. When simulating a role with a boundary, you can select the boundary policy in addition to the identity policies. The simulator will show you the exact result of the intersection and which policy is causing the denial.

πŸ”‘ Expert-Level IAM Best Practices

  • Humans Use Identity Center, Machines Use Roles: Never create IAM users for your human employees. Centralize human access via IAM Identity Center. Use IAM Roles for all applications and services.
  • Prefer ABAC to RBAC at Scale: Use attribute-based controls with session tags from your IdP to avoid creating hundreds of specific roles.
  • **Delegate Safely with Permissions Boundaries:** Use boundaries as a non-negotiable guardrail whenever you delegate IAM role creation to development teams.
  • **Automate Everything as Code:** Your entire IAM and Identity Center configuration should be managed via IaC (e.g., Terraform) and stored in Git for auditing and peer review.
  • **Implement Just-in-Time (JIT) Access:** For highly sensitive roles, move beyond standing permissions. Implement workflows where users must request temporary, time-bound access to elevated roles.

You've Mastered Identity and Access!

With a strong identity foundation, your next step is to ensure your resources are configured correctly and you can detect threats in real time.