Cloud IAM & Access Management

Design cloud IAM architecture. Covers least-privilege policies, role hierarchy, service accounts, cross-account access, identity federation, and auditing cloud access.

This reference covers the core mechanics of identity and access control in cloud environments, focusing on how to configure and manage authentication and authorization for services, users, and systems. It applies when provisioning new resources, securing existing workloads, or troubleshooting access issues across cloud platforms.

Configure User and Service Account Access

Create a user with specific permissions

To create a user account with granular access controls:

# Example using AWS CLI v2
aws iam create-user --user-name "[email protected]"
aws iam attach-user-policy --user-name "[email protected]" --policy-arn "arn:aws:iam::123456789012:policy/ReadOnlyAccess"

The user receives access keys via create-access-key command, which must be stored securely. IAM users do not support multi-factor authentication (MFA) directly; MFA is configured at the account level.

Create service accounts with limited scope

Service accounts are typically created through programmatic interfaces:

# Example using Kubernetes RBAC
kubectl create serviceaccount --namespace production my-app-sa
kubectl create rolebinding --namespace production my-app-binding \
  --role=role-name \
  --serviceaccount=production:my-app-sa

The service account token must be mounted into pods to authenticate with other services. A service account's token can be rotated using kubectl patch serviceaccount.

Assign roles to users or groups

Assigning roles is done through identity federation or direct assignment:

# Example using AWS IAM CLI
aws iam attach-group-policy --group-name "developers" --policy-arn "arn:aws:iam::123456789012:policy/EC2FullAccess"

Groups are collections of users, not roles themselves. A user inherits all policies attached to groups they belong to.

Configure Access Control Policies

Define policy statements with conditions

Policies use JSON syntax with Effect, Action, Resource, and optional Condition fields:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/*",
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": "us-west-2"
        }
      }
    }
  ]
}

Conditions are evaluated at request time and may fail silently if a condition key is not supported by the service.

Create cross-account access policies

Policies for cross-account access use Principal with account ARN:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::987654321098:root"
      },
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::123456789012:role/ExternalAccessRole"
    }
  ]
}

The Principal field accepts either a single ARN or an array of ARNs. Policies with multiple principals must be attached to roles, not users.

Configure Authentication Methods

Enable MFA for user accounts

MFA is configured using virtual device tokens:

# Example using AWS CLI
aws iam create-virtual-mfa-device --virtual-mfa-device-name "alice-mfa"
aws iam enable-user-mfa --user-name "[email protected]" --serial-number "arn:aws:iam::123456789012:mfa/alice-mfa"

Users must enroll MFA before accessing protected resources. MFA is enforced at the account level, not per service.

Set up federated identity with SAML

Federated access requires a metadata document from the identity provider:

# Example using AWS IAM
aws iam create-saml-provider --saml-metadata-document file://saml-metadata.xml --name "MySAMLProvider"

The metadata file must contain valid XML with EntityDescriptor element and IDPSSODescriptor. SAML assertions are validated against the provided certificate.

Configure API key-based authentication

API keys for service-to-service communication:

# Example using AWS IAM
aws iam create-access-key --user-name "service-account"

Keys are returned as JSON with AccessKeyId and SecretAccessKey. Secret keys must be rotated regularly to maintain security.

Manage Access Tokens and Sessions

Create temporary credentials for short-lived access

Temporary credentials are generated through AssumeRole or similar mechanisms:

# Example using AWS CLI
aws sts assume-role --role-arn "arn:aws:iam::123456789012:role/TempAccessRole" --role-session-name "temp-session"

Response includes Credentials with AccessKeyId, SecretAccessKey, and SessionToken. These tokens expire after a set duration, typically one hour.

Rotate access keys programmatically

Keys must be rotated regularly to prevent long-term exposure:

# Example using AWS CLI
aws iam create-access-key --user-name "[email protected]"
aws iam delete-access-key --user-name "[email protected]" --access-key-id "AKIAIOSFODNN7EXAMPLE"

Old keys are immediately invalidated. Rotating keys requires updating all applications that use them.

Troubleshoot Access Issues

Debug permission denied errors

Check the effective policy applied to a resource:

# Example using AWS CLI
aws iam get-user-policy --user-name "[email protected]" --policy-name "ReadOnlyAccess"
aws iam list-attached-user-policies --user-name "[email protected]"

Missing permissions often result in AccessDenied responses from services. The error response does not include the full policy context, so audit logs are necessary to trace denied actions.

Handle session expiration

Session tokens expire silently without warning:

# Example using AWS CLI
aws sts get-caller-identity --token-file ~/.aws/credentials

Applications must handle token expiration gracefully. A failed request with ExpiredToken error indicates that session credentials are no longer valid.

Resolve cross-account access failures

Cross-account roles require correct trust policies:

# Example using AWS CLI
aws iam get-role --role-name "ExternalAccessRole"

Failure to match the trust policy's Principal ARN results in AccessDenied errors from the target account. The role must be assumable by the correct principal.

Configure Access Restrictions

Limit access by IP address

IP-based restrictions are defined through policy conditions:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Principal": {
        "AWS": "*"
      },
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "203.0.113.0/24",
            "198.51.100.0/24"
          ]
        }
      }
    }
  ]
}

IP-based conditions are evaluated at the point of authentication, not authorization. Invalid IP addresses in a condition are silently ignored.

Enforce session duration limits

Session durations can be restricted during AssumeRole:

# Example using AWS CLI
aws sts assume-role --role-arn "arn:aws:iam::123456789012:role/TempAccessRole" \
  --role-session-name "temp-session" \
  --duration-seconds 3600

Duration values must be between 900 and 43200 seconds. Values outside this range are rejected with InvalidDuration error.

Configure access from specific regions

Region restrictions use condition keys in policies:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/*",
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": "us-west-2"
        }
      }
    }
  ]
}

Not all services support region-based conditions. Services that do not recognize the condition key silently ignore it.

Monitor Access Events

Audit user activity through logs

Access events are typically logged to CloudTrail or similar services:

# Example using AWS CLI
aws cloudtrail lookup-events --lookup-attributes Key=Username,Value="[email protected]"

Events include EventName, EventTime, and Username. Not all actions generate audit logs; some operations are internal and not logged.

Monitor for unauthorized access attempts

Unauthorized access attempts may appear as failed authentication requests:

# Example using AWS CLI
aws cloudtrail lookup-events --lookup-attributes Key=EventName,Value="ConsoleLogin" \
  --start-time 2023-01-01T00:00:00Z \
  --end-time 2023-01-01T01:00:00Z

Failed logins may not include IP address information if the service does not support it. The event may show EventName as ConsoleLogin but have no additional context about the failure reason.

Detect credential exposure

Credential exposure is detected by monitoring for unusual access patterns:

# Example using AWS CLI
aws cloudtrail lookup-events --lookup-attributes Key=Username,Value="service-account" \
  --start-time 2023-01-01T00:00:00Z \
  --end-time 2023-01-01T01:00:00Z

Unusual activity often manifests as logins from unexpected locations or at unusual times. Access key usage is logged, but the actual access pattern (which resources were accessed) requires parsing of detailed events.

Configure Secure Access Patterns

Use least privilege principle for service accounts

Roles should include only necessary permissions:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::my-bucket/*"
    }
  ]
}

Over-permissioning is a common mistake that increases attack surface. The policy should be reviewed regularly to ensure it reflects actual usage.

Implement role chaining for temporary access

Roles can assume other roles, creating chains:

# Example using AWS CLI
aws sts assume-role --role-arn "arn:aws:iam::123456789012:role/IntermediateRole" \
  --role-session-name "intermediate-session"

Chained roles must be configured with appropriate trust policies to allow the next role in the chain. The final session inherits permissions from all roles in the chain.

Set up access reviews for periodic permission audits

Access reviews are typically implemented through automated tools or scripts:

# Example using AWS CLI
aws iam list-users
aws iam list-groups-for-user --user-name "[email protected]"

Groups and their attached policies must be reviewed regularly. Users should be removed from groups when they no longer need access.

Common Failure Modes

Silent policy evaluation failures

Policy conditions that reference unsupported keys are silently ignored:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/*",
      "Condition": {
        "StringEquals": {
          "aws:RequestTag/Environment": "production"
        }
      }
    }
  ]
}

If the service does not support tag-based conditions, the policy is accepted but ignored. The user gets access even though they should be restricted.

Token expiration without error messages

Temporary credentials expire silently:

# Example using AWS CLI
aws s3 ls s3://my-bucket --no-verify-ssl

If an application uses expired tokens, it receives a generic InvalidToken error. The error does not specify which token expired or when.

Group membership propagation delays

Changes to group membership may take time to propagate:

# Example using AWS CLI
aws iam add-user-to-group --group-name "developers" --user-name "[email protected]"
aws iam list-groups-for-user --user-name "[email protected]"

The user may still be denied access after being added to a group. The delay can range from seconds to minutes, and is not consistent across implementations.

Cross-account trust policy mismatches

Trust policies must exactly match the expected principal:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::987654321098:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

If the principal is arn:aws:iam::987654321098:user/external-user instead of arn:aws:iam::987654321098:root, the assume role operation fails with AccessDenied.

This page was rewritten on 16 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.