In Amazon Web Services (AWS), authorization is governed universally by AWS Identity and Access Management (IAM) Policy Documents. Whether an API call is made by a software developer clicking the AWS Management Console, an automated Terraform pipeline running in CI/CD, or an Amazon EC2 instance querying an Amazon S3 bucket, AWS evaluates an attached JSON policy document to permit or deny the request.
Authoring secure, auditable IAM policies is the primary defense against catastrophic cloud data breaches and privilege escalation.
The Anatomy of an AWS IAM JSON Policy Document
An IAM policy is an explicit JSON object containing a top-level Version and an array of one or more Statement objects:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowSpecificS3BucketRead",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::corp-financial-reports-2026",
"arn:aws:s3:::corp-financial-reports-2026/*"
],
"Condition": {
"Bool": {
"aws:SecureTransport": "true"
}
}
}
]
}
Deconstructing Policy Statement Elements
Version: Defines the language syntax rules. Always declare"2012-10-17". (Never omit this or use the current calendar date, as legacy versions fail to process modern policy variables).Sid(Statement ID): An optional, human-readable identifier describing the business intent of the statement.Effect: Explicitly states whether the policy grants or denies access. Accepts only two values:"Allow"or"Deny".Action: The specific AWS service API calls being controlled. Expressed asservice:operation(e.g.ec2:StartInstances,dynamodb:Query). Wildcards (*) are supported but should be strictly curtailed in production.Resource: The Amazon Resource Name (ARN) identifying the exact AWS object to which the action applies. Notice in the S3 example that bucket operations (ListBucket) require the bucket ARN (arn:aws:s3:::bucket), while object operations (GetObject) require the wildcard object ARN (arn:aws:s3:::bucket/*).Condition: The most powerful authorization block, evaluating environmental context (e.g. source IP, TLS cipher, MFA status, current timestamp, or resource tags).
The AWS Policy Evaluation Logic: The Explicit Deny Rule
When an API call is executed, the AWS IAM evaluation engine follows a deterministic, non-negotiable decision tree:
| Evaluation Step | Evaluation Logic | Result |
|---|---|---|
| 1. Default State | By default, all requests are implicitly denied | Implicit Deny |
| 2. Explicit Deny Check | Does ANY applicable policy contain "Effect": "Deny" matching this Action and Resource? |
Immediate Deny. Evaluation halts immediately. An explicit deny overrides all allows. |
| 3. Explicit Allow Check | Does at least ONE applicable policy contain "Effect": "Allow"? |
Request Permitted. |
| 4. Final Fallback | No explicit Allow found and no explicit Deny found | Implicit Deny. Request rejected. |
AdministratorAccess group granting *:* (Full Administrative Access), if a Service Control Policy (SCP) or boundary policy contains a statement with "Effect": "Deny" for s3:DeleteBucket, the user is permanently blocked from deleting S3 buckets.Operationalizing the Principle of Least Privilege (PoLP)
The Principle of Least Privilege mandates that identities should be granted only the minimum permissions necessary to complete their specific business function—nothing more.
Anti-Pattern: The Dangerous Wildcard Administrator
Novice cloud practitioners frequently write overly broad policies to eliminate permission errors quickly:
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
If an application server running under this policy is compromised via an SSRF (Server-Side Request Forgery) flaw, the attacker can list, download, overwrite, and delete every S3 bucket across the entire AWS account.
Best Practice: Granular Action & Resource Scoping with Conditions
Enforce contextual constraints using Condition blocks:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyAllWithoutMFAAndCorporateIP",
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": "false"
},
"NotIpAddressIfExists": {
"aws:SourceIp": [
"198.51.100.0/24",
"203.0.113.50/32"
]
}
}
}
]
}
Eliminating Long-Lived Access Keys: IAM Roles for Workloads
Never hardcode static AWS Access Keys (AKIA...) inside application configuration files or EC2 servers. Modern cloud architecture mandates attaching an IAM Role directly to the compute resource via an Instance Profile. The instance queries the AWS Instance Metadata Service (IMDSv2) to obtain ephemeral, short-lived security tokens that automatically rotate every 6 hours.
Summary
AWS IAM JSON policies are the bedrock of cloud governance. By mastering the Version, Statement, Effect, Action, Resource, and Condition schema, respecting the non-negotiable priority of Explicit Deny, and applying the Principle of Least Privilege, cloud architects construct impenetrable cloud security perimeters.