Skip to content

Enterprise IAM at Scale: Workload Identity, Permission Boundaries, and Trust Architecture

Executive Summary

Identity and Access Management (IAM) is the security perimeter of the modern cloud. While network boundaries remain critical, they are easily bypassed if identity controls are weak. In large-scale cloud operations, maintaining least privilege becomes exponentially harder. Traditional Role-Based Access Control (RBAC) often results in "role explosion" and privilege creep, where engineers continuously request new permissions and rarely clean up old ones. To solve this, organizations must shift toward Attribute-Based Access Control (ABAC) and enforce structural guardrails like Permission Boundaries.

A major failure mode in enterprise cloud platforms is the mismanagement of workload identities. Hardcoded, long-lived API keys are still a leading cause of compromise. Even when teams adopt modern solutions like OpenID Connect (OIDC) federation or Kubernetes IAM Roles for Service Accounts (IRSA), they often misconfigure trust relationships. This creates vulnerabilities like multi-cluster OIDC token audience confusion or lateral cross-account privilege escalation. This whitepaper explains the design patterns and cryptographic principles required to secure workload identity, configure boundaries, and build a resilient cross-account trust architecture.


Threat Model and Attack Surface

The IAM attack surface expands as organizations adopt multi-cloud, multi-region, and multi-tenant architectures. Attackers target trust relationships to transition from compute access to global platform control.

       [ Stolen Kubernetes SA Token ]
       [ Calls sts:AssumeRoleWithWebIdentity ]
       ┌─────────────┴─────────────┐
       ▼                           ▼
[ Target Role: No Aud Match ]   [ Target Role: Aud Wildcarded ]
       │                           │
       ▼                           ▼
[ Signature verification fails ]   [ STS grants Session Credentials ]
       │                           │
  ( Blocked )                      ▼
                       [ Lateral Cluster Takeover ]

Threat Vectors and Kill-Chains

  1. OIDC Audience (aud) Confusion:
  2. Adversary Goal: Assume high-privilege AWS roles using a low-privilege OIDC token from a different cluster.
  3. Attack Vector: An enterprise shares a single OIDC provider or configures a trust relationship with wildcarded resource constraints in the AWS IAM Role trust policy. An attacker on Cluster A generates a token for service account dev-sa. They call sts:AssumeRoleWithWebIdentity against a role in Cluster B. Because the trust policy of the Cluster B role accepts a wildcarded audience (* or has lax checks on issuer/client IDs), AWS STS validates the signature and issues session credentials, allowing the attacker to assume the high-privilege role.
  4. Confused Deputy in Role Assumption:
  5. Adversary Goal: Compromise resources by tricking a trusted service into acting on their behalf.
  6. Attack Vector: An attacker specifies a victim's role ARN in an integration request to a third-party monitoring SaaS. If the victim's role trust relationship does not enforce a unique sts:ExternalId condition, the monitoring tool's integration role assumes the victim's role without verifying who initiated the request.
  7. Escalation via PassRole Abuse:
  8. Adversary Goal: Attach admin privileges to a compute instance under their control.
  9. Attack Vector: A developer has permission to run EC2 instances and has iam:PassRole permissions over a role named EC2-Admin-Role. They spin up a custom EC2 instance, pass the administrative role to it, log into the instance (via SSM or SSH), and query the instance metadata service (IMDSv2) to extract full administrator credentials.

Deep Technical Body

Workload Identity Federation (OIDC) Security Mechanics

Workload Identity Federation removes the need for long-lived credentials. Instead of configuring IAM users with access keys, applications authenticate using short-lived tokens (JSON Web Tokens - JWTs) issued by an identity provider (IdP), such as GitHub Actions, GitLab, HashiCorp Vault, or a Kubernetes OpenID Connect issuer.

The Token Exchange Flow

  1. The workload requests an identity token from its local provider (e.g. GitHub Actions runner requests a token from GitHub's OIDC issuer).
  2. The provider generates a signed JWT containing claims: iss (issuer), sub (subject), aud (audience), and exp (expiry).
  3. The workload sends this JWT to AWS STS via the AssumeRoleWithWebIdentity API call.
  4. AWS STS validates the JWT signature using the provider's public key (fetched from the provider's .well-known/openid-configuration JWKS endpoint).
  5. AWS STS matches the claims against the IAM role's trust policy. If they match, STS returns temporary AWS credentials.

The OIDC Audience Wildcard Vulnerability

A common and dangerous misconfiguration is using wildcards in OIDC role trust relationships. Consider the following trust policy designed to allow GitHub Actions to deploy resources:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringLike": {
          "token.actions.githubusercontent.com:sub": "repo:my-org/*"
        }
      }
    }
  ]
}

What is the flaw? While this policy limits the subject (sub) to repositories under my-org/*, it fails to validate the audience (aud). By default, if the audience check is missing, any JWT issued by GitHub Actions for any repository in the world can potentially assume this role if the attacker can spoof the subject format or if the OIDC provider configurations overlap. To secure this, the aud condition must be strictly locked down to sts.amazonaws.com.

IAM Permission Boundaries: Mechanics and Bypasses

A Permission Boundary is an advanced IAM feature that limits the maximum permissions a policy can grant to an identity (User or Role). It acts as a logical AND filter.

          [ Permissions Granted by IAM Policy ]
                         ├─────────┐
                         ▼         ▼
                     [ Action A ] [ Action B ]
        [ Matches Permission Boundary Policy? ]
               ┌─────────┴─────────┐
               ▼                   ▼
           [ Action A ]        [ Action B ]
             (Allowed)         (Matches: No)
                            [ ACCESS DENIED ]

When an administrator delegates role-creation privileges to developers or teams, they must enforce a permission boundary. This prevents developers from creating a role with greater permissions than they themselves possess.

The Enforcement Pattern

To enforce a boundary, the developer's IAM policy must contain a condition requiring the boundary policy to be attached to any new role they create:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "CreateRoleWithBoundaryOnly",
      "Effect": "Allow",
      "Action": [
        "iam:CreateRole",
        "iam:PutRolePolicy",
        "iam:AttachRolePolicy"
      ],
      "Resource": "arn:aws:iam::123456789012:role/developer/*",
      "Condition": {
        "StringEquals": {
          "iam:PermissionsBoundary": "arn:aws:iam::123456789012:policy/Developer-Boundary"
        }
      }
    }
  ]
}

Common Permission Boundary Bypasses

If not configured carefully, developers can bypass boundary rules: 1. Missing DeleteRolePermissionsBoundary Prevention: If the developer has iam:DeleteRolePermissionsBoundary access, they can simply remove the boundary from a role they created, restoring full admin privileges to that role. 2. Lax Resource Paths: If the developer can modify roles outside the arn:aws:iam::123456789012:role/developer/* path, they can target system roles or core integration roles. 3. IAM Policy Updates: If the developer has permissions to create new versions of the Developer-Boundary policy itself (iam:CreatePolicyVersion), they can update the boundary to grant themselves administrative permissions.


Defensive Architecture

A secure enterprise identity architecture requires combining ABAC for scale with strict validation rules on trust relationships.

Hardened Role Trust Blueprint (Kubernetes IRSA)

This policy shows the correct way to configure IRSA (IAM Roles for Service Accounts) on EKS, preventing token audience confusion and limiting access to a specific Kubernetes Namespace and ServiceAccount.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::123456789012:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/EXAMPLETOCKENID"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "oidc.eks.us-west-2.amazonaws.com/id/EXAMPLETOCKENID:aud": "sts.amazonaws.com",
          "oidc.eks.us-west-2.amazonaws.com/id/EXAMPLETOCKENID:sub": "system:serviceaccount:payment-processing:payment-processor-sa"
        }
      }
    }
  ]
}

Attribute-Based Access Control (ABAC) Design Pattern

To avoid maintaining thousands of individual IAM policies, use session tags for authorization. Ensure that compute instances or roles can only access S3 buckets, secrets, or databases that share their environment tag.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowSecretsAccessByTagMatching",
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetSecretValue",
        "secretsmanager:DescribeSecret"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:ResourceTag/Environment": "${aws:PrincipalTag/Environment}",
          "aws:ResourceTag/CostCenter": "${aws:PrincipalTag/CostCenter}"
        }
      }
    }
  ]
}

Tooling and Implementation

Modern organizations automate the validation and management of IAM policies:

  1. IAM Access Analyzer: Use this service to check for external or public access sharing and identify overly permissive policies.
  2. CloudMapper / PMapper (Principal Mapper): An open-source tool that maps the relationship chains between IAM principals. It detects privilege escalation paths (e.g. User A can assume Role B, which can pass Role C to an EC2 instance, leading to Admin access).
  3. Kube-2-IAM / EKS Pod Identity: Utilize native AWS EKS Pod Identity agents. EKS Pod Identity associates IAM roles with Kubernetes service accounts directly using API calls instead of OIDC provider configurations, making management simpler and less prone to configuration errors.

IAM Audit Checklist

Item Focus Area Verification Step / Command Target State
1 Credential Expiry Scan for active, long-lived AWS IAM Access Keys. Access keys older than 90 days are disabled or rotated automatically.
2 OIDC Security Audit EKS and GitHub OIDC trust relationships. All trust statements must contain a explicit "aud": "sts.amazonaws.com" (or similar client identifier) constraint.
3 Confused Deputy Verify that external/third-party roles use an ExternalId. Trust policies require sts:ExternalId containing a unique ID.
4 Permission Boundaries Audit roles used by deployment tools (e.g. Jenkins, GitLab, Terraform). If they have role-creation rights, they must be constrained by an iam:PermissionsBoundary check.
5 PassRole Scope Scan policy configurations for "Action": "iam:PassRole" on resource *. PassRole is strictly restricted to roles with matching paths (e.g. arn:aws:iam::*:role/compute/*).
6 Over-permissive Wildcards Hunt for policies containing "*" in both Action and Resource blocks. Allowed only in central admin roles, blocked on all application and compute roles.

References