IAM #

In cloud compute infrastructure management, security is no longer determined by the physical perimeter of a data center or simply a network firewall. In the public cloud era, identity is the new security perimeter (identity is the new perimeter). The main service managing this security boundary is Identity and Access Management (IAM). Every time an administrator opens the cloud console, every time application code calls an object storage API, or every time a CI/CD pipeline deploys serverless architecture — all those interactions must pass strict inspection under IAM control. IAM isn’t an add-on feature configured after the system is built. IAM is the most critical security foundation determining whether all our corporate data can be hacked just from one leaked developer credential file, or stays safe thanks to highly precise access restrictions. This article deeply dissects IAM’s three pillars, identity component anatomy, policy evaluation logic, and advanced control delegation strategies.

The Three Main Pillars of IAM Security #

To understand how IAM protects cloud resources, we must separate the security inspection process into three main pillars running sequentially:

flowchart TD
    Request["1. Client API Request"] --> AuthN["2. AUTHENTICATION (AuthN) <br>Who is the accessing subject?<br>(Validate: Password, Token, Access Key)"]
    AuthN -->|"Verified"| AuthZ["3. AUTHORIZATION (AuthZ) <br>What actions are allowed?<br>(Evaluate Policy Documents & Conditions)"]
    AuthN -->|"Failed"| Reject1["HTTP 401 Unauthorized<br>(Access Denied)"]
    
    AuthZ -->|"Allowed"| Execute["4. ACTION EXECUTED<br>(e.g., Read S3 file, Stop VM)"]
    AuthZ -->|"Denied"| Reject2["HTTP 403 Forbidden<br>(Access Denied)"]
    
    Execute --> Audit["5. AUDIT LOGGING<br>(Activity Recording via CloudTrail / Audit Logs)"]
    Reject1 --> Audit
    Reject2 --> Audit

1. Authentication (AuthN) #

Authentication is the process of proving the identity of the entity trying to log in or send a request. IAM asks: “Who is this accessing subject?”.

  • Mechanism: Human users prove it using a combination of username, password, and Multi-Factor Authentication (MFA) codes. Applications, servers, or scripts prove it using digital certificates, OIDC tokens, or access key pairs (Access Key ID & Secret Access Key).

2. Authorization (AuthZ) #

After identity is verified as legitimate, IAM performs authorization. IAM asks: “What actions are allowed on this resource?”.

  • Mechanism: The IAM evaluation engine scans all policies attached to that identity and matches the requested action (e.g., deleting a database table) against the defined permission rules. If no rule explicitly allows it, the request is immediately denied with an HTTP 403 Forbidden error status.

3. Auditing & Accounting #

The third pillar records and captures every API transaction activity in the cloud transparently. Services like AWS CloudTrail or Google Cloud Audit Logs automatically record complete metadata of every API call: “Who did it, what action was requested, which resource was accessed, when it executed, from which IP the request came, and what the result status was (Success/Denied)”. These audit records are permanent and must not be modifiable by anyone for security forensics needs.


Identity Components: Users, Groups, and Roles #

The IAM system distinguishes accessing entities into three main categories to simplify access rights governance:

flowchart TD
    subgraph Users ["IAM Users (Humans)"]
        Alice["Alice (Dev)"]
        Bob["Bob (Dev)"]
        Charlie["Charlie (Ops)"]
    end
    
    subgraph Groups ["IAM Groups"]
        DevGroup["Developer Group"]
        OpsGroup["Operations Group"]
    end
    
    subgraph Policies ["IAM Policies"]
        DevPolicy["Dev Environment Policy"]
        ProdPolicy["Prod Admin Policy"]
    end
    
    Alice --> DevGroup
    Bob --> DevGroup
    Charlie --> OpsGroup
    
    DevGroup --> DevPolicy
    OpsGroup --> ProdPolicy

1. IAM User #

Represents a single permanent identity usually associated with one human (e.g., our corporate employee).

  • Root Account: This is the primary identity automatically created when first registering a cloud account. The root account has absolute, unlimited power over all resources and financial billing. CRITICAL RULE: Never use the root account for daily operational activities. Root credentials must be locked with a long password stored in a digital password manager vault, physical MFA enabled, and operations fully delegated to regular administrator users at the IAM level.
  • Individual Identity Principle: Every team member must have their own individual user. Sharing one user’s credentials among several developers is a heavy anti-pattern because it breaks audit log accountability (we can’t know which developer accidentally deleted the database if everyone uses the “admin_developer” account).

2. IAM Group #

A collection of several IAM Users sharing the same job function.

  • Manageability: It’s highly recommended to attach permission policies at the Group level, not directly to individual Users. When a new employee joins the developer team, we simply add their user to the “Developer Group” and that user automatically inherits all required permissions. If they move divisions to the Operations team, we simply move them to the “Operations Group” to instantly revoke their old permissions.

3. IAM Role (Workload Identity) #

A temporary identity without permanent credentials. Unlike Users who have fixed passwords or access keys that never expire, Roles work using temporary security credentials dynamically created by the Security Token Service (STS) and automatically expiring within hours (e.g., 1 to 12 hours).

  • Workload Security Principle: Never put physical Access Keys in our application code configuration files running on Virtual Machines or containers.
  • How Roles Work: Our VM is attached with an Instance Profile bound to a Role. When our application calls the cloud SDK (e.g., to upload a file to S3), the SDK automatically fetches a temporary token from the local instance metadata server. This token is transparently refreshed in the background. If our VM is hacked by outsiders, attackers only get a temporary key token that automatically expires soon, minimizing the window of exposure security risk duration.
# ANTI-PATTERN: Putting permanent credentials in application config files
aws_access_key_id: "«redacted:AKIA…»"       # DON'T: Highly vulnerable to leaking in Git commits!
aws_secret_access_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

# --- Separator ---

# CORRECT: Using an IAM Role bound to the VM instance (declarative Terraform)
resource "aws_iam_instance_profile" "app_profile" {
  name = "app_server_instance_profile"
  role = aws_iam_role.app_role.name
}

resource "aws_iam_role" "app_role" {
  name = "app_server_role"

  # Allows EC2 (VM) instances to temporarily assume this role
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "ec2.amazonaws.com"
        }
      }
    ]
  })
}

Policy Evaluation Logic #

When an API request enters IAM, the cloud authorization engine evaluates policies using a very strict structured logic flow to decide whether the request is allowed or denied.

flowchart TD
    Start["API Request Received"] --> DefaultDeny["1. DEFAULT DENY<br>(All access denied by default)"]
    DefaultDeny --> CheckDeny{"2. EXPLICIT DENY EXISTS?<br>(Check for explicit denial rules)"}
    
    CheckDeny -- "Yes" --> Denied["ACCESS DENIED (Deny wins)"]
    CheckDeny -- "No" --> CheckAllow{"3. EXPLICIT ALLOW EXISTS?<br>(Check for permission rules)"}
    
    CheckAllow -- "Yes" --> Allowed["ACCESS ALLOWED (Allow)"]
    CheckAllow -- "No" --> Denied

IAM Decision Logic: #

  1. Default Deny (Implicit Deny): By default, all access requests to cloud resources are denied. If we create no rules, no user can access anything.
  2. Explicit Deny: The evaluation engine scans all applicable policies. If even one explicit Deny rule matches the requested action or resource, the request is immediately denied, regardless of how many Allow rules in other policies permit it. In IAM: “Deny always wins over Allow”.
  3. Explicit Allow: If no Deny is detected, the engine looks for a matching explicit Allow rule. If found, access is granted.
  4. Implicit Deny (Fallback): If there’s no Deny and no matching Allow, the request falls back to being denied per the first default deny rule.

Policy Types: Managed vs Inline and Identity-based vs Resource-based #

Permission policies are written in JSON document format. We must separate these policies by how they’re attached and managed.

1. Managed Policy vs Inline Policy #

  • Managed Policy (Recommended): A standalone policy with a unique cloud ID (ARN) that can be attached to many identities at once (Users, Groups, and Roles). If we update the contents of a Managed Policy, the changes instantly apply to all identities using it. Managed Policies are divided into:
    • Provider-managed: Provided directly by the cloud provider (like AdministratorAccess or AmazonS3ReadOnlyAccess). CAUTION: Provider built-in policies are often too broad and violate the principle of least privilege.
    • Customer-managed: Written by us from scratch per our application needs. This is the production best practice.
  • Inline Policy (Avoid if possible): A policy embedded directly inside one specific identity and not shareable with other identities. This makes security compliance governance very hard to track (audit spaghetti).

2. Identity-based vs Resource-based Policy #

  • Identity-based Policy: A policy document attached to accessing identity objects (Users, Groups, or Roles) determining what they may access.
  • Resource-based Policy: A policy document attached directly to the target resource object (like an S3 Bucket, KMS Key, or SQS Queue) defining who is allowed to access that resource.
// Example Resource-based Policy attached directly to an S3 Bucket
// This rule allows a specific application IAM Role to read files in this bucket
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowAppReadAccess",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:role/app_server_role"
      },
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::corporate-finance-data",
        "arn:aws:s3:::corporate-finance-data/*"
      ]
    }
  ]
}

Access Boundary Controls: Permission Boundaries and SCPs #

In large organizations with hundreds of cloud accounts and dozens of developer teams, the central cloud security team can’t manually configure IAM every day for every developer. They must delegate IAM Role creation authority to local developer teams. However, this delegation triggers a new risk: Developers can create Roles with Administrator access for themselves (Privilege Escalation).

To mitigate this danger, we must apply advanced access restriction techniques:

1. Permission Boundary #

A special control policy tasked with limiting the maximum capability of access rights an IAM identity can hold (like new Roles created by developers).

  • How It Works: Even if a developer creates a new IAM Role attaching the AdministratorAccess policy (Allow All), if that new Role is configured under a Permission Boundary only allowing S3 and DynamoDB access, the effective access rights of that new Role are limited to S3 and DynamoDB only. Other administrative access is automatically blocked by the boundary.
Effective Access Rights Formula:
┌─────────────────────────────┐
│  IAM Policy (Normal Perms)  │ ────────┐
│  e.g., Allow All (*)        │         │
└─────────────────────────────┘         │
                                        ├──> Intersect = Effective Access Rights
┌─────────────────────────────┐         │                         (S3 & DynamoDB only)
│  Permission Boundary (Limit)│ ────────┘
│  e.g., Allow S3 & DynamoDB  │
└─────────────────────────────┘

2. Service Control Policy (SCP) #

For multi-account governance at the cloud organization level (Organization Units). SCPs sit above each account’s local IAM level.

  • How It Works: SCPs are used by the central security team to limit maximum access rights for all entities (including local account Administrator users) inside child cloud accounts.
  • Mandatory SCP Examples:
    • Preventing any account from deleting or disabling CloudTrail audit logs.
    • Restricting all compute instances to deploy only in law-compliant regions (e.g., only in Jakarta ap-southeast-3) for regional data sovereignty compliance.
    • Prohibiting creation of public databases directly exposed to the internet.

Summary #

  • Identity is the new security perimeter in the cloud — IAM strictly and centrally controls authentication (AuthN), authorization (AuthZ), and audit recording.
  • Use IAM Roles with temporary tokens (temporary credentials) for server and container workloads, avoiding physical Access Keys in code configuration files.
  • The Root Account is the primary attack target — Lock it with physical MFA, store the password in a password manager, and never use it for daily operations.
  • Manage access rights at the Group level rather than attaching them directly to individual Users to minimize security audit complexity.
  • Deny always wins over Allow — Leverage this explicit denial rule to permanently block sensitive access.
  • Apply Permission Boundaries and SCPs when delegating IAM role creation rights to developer teams to prevent privilege escalation loopholes.

← Previous: Spot/Preemptible Instance   Next: Least Privilege →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact