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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
We use cookies for analytics (Google Analytics) and advertising (Google AdSense) to improve your experience and support free content. Privacy Policy