Cloud Computing
IAM and Access Policies
In 2019 Capital One lost data on 100 million customers: a former AWS employee found a misconfigured WAF, called AssumeRole on a role with access to all of S3, and exfiltrated credit histories. The investigation showed: the IAM policy attached to that role permitted ListBuckets and GetObject on any resource. No IP condition, no explicit Deny, no audit boundary. The principle of least privilege was not enforced. IAM in the cloud is not bureaucracy but the foundation of security; one mistake in a trust policy or Action: '*' can cost a company billions.
- **Netflix:** each microservice runs under its own IAM role, and access to data and secrets is controlled by condition keys on team tags
- **HashiCorp Vault / AWS Secrets Manager:** replace long-lived database and third-party API credentials with dynamic, on-demand ones
- **GitHub Actions OIDC + AWS IAM Roles:** the 2024-2025 CI/CD standard - zero AWS keys in GitHub Secrets under corporate policy
IAM Roles: Short-Lived Credentials Instead of Keys
In 2017 Uber lost data on 57 million users: a contractor committed AWS access keys to public GitHub. The same class of incident has repeated for years at Snapchat, Capital One, and Imperva. The root cause is the same - long-lived access-key + secret pairs that sit in repositories, on engineers' laptops, and in CI configs. AWS IAM Roles are the mechanism that replaces those keys with short-lived STS tokens. An EC2 instance, a Lambda function, or an ECS container automatically receives temporary credentials via the instance metadata service. No keys in code, rotation is built in, and revoking a role is instantaneous.
A role has two parts: a trust policy (who is allowed to AssumeRole) and permission policies (what is allowed). An EC2 instance gets a role through an instance profile, Lambda through an execution role, and an ECS task through a task role. AWS STS issues temporary credentials (1 hour by default, up to 12) that runtime rotates automatically. This is the basis of the zero-trust approach in the cloud: identity is not tied to a static secret.
Why are IAM roles safer than hardcoding access key + secret in service environment variables?
JSON Policies: Effect, Action, Resource, Condition
An IAM policy is a JSON document that describes permissions. Each Statement has four key fields: Effect (Allow or Deny), Action (what is allowed - 's3:GetObject', 'ec2:RunInstances'), Resource (on which - the ARN of the resource), and Condition (under what circumstances - IP, time, tag). The evaluation logic: an explicit Deny overrides any Allow; the absence of an explicit Allow is equivalent to Deny. This is the principle of least privilege expressed as a rule: anything not explicitly allowed is forbidden.
Action supports wildcards: 's3:Get*' covers GetObject, GetObjectAcl, GetBucketPolicy. Resource is an ARN that may include patterns: 'arn:aws:s3:::company-logs/*' matches every object inside the company-logs bucket. Condition is the standard mechanism for narrowing: aws:SourceIp restricts by IP, aws:RequestedRegion by region, aws:PrincipalTag/team by the principal's tag. Composing these fields gives an extremely flexible model: 'a backend developer may write only into their own dev bucket, only from the office IP, and only during business hours'.
Policy A grants s3:* on a bucket with Allow. Policy B forbids s3:DeleteObject on the same bucket with Deny. What happens on a delete?
Cross-Account Access: AssumeRole Across Accounts
A large company does not live in a single AWS account. Production is separate from dev, billing from the data lake, security tooling from application services. A common scenario: the analytics team in account 333333333333 must read an S3 bucket in production account 999999999999. Cross-account IAM solves this without copying keys: production creates a role with a trust policy allowing AssumeRole from an identity in the analytics account. The analytics identity calls sts:AssumeRole, receives temporary credentials for the production account, and acts on its behalf. No keys are exchanged - only a declaration of trust in JSON.
External ID is an extra mechanism against the confused-deputy attack: when trusting a third-party vendor (Datadog, Snowflake) the trust policy requires not only the right account but also a matching external ID. This protects against the case where an attacker has convinced the vendor to AssumeRole into a victim's account. AWS Organizations plus SCPs add another layer on top: even if a child account creates a role with broad permissions, an organization Service Control Policy can forbid entire actions (for example, DeleteBucket in every production account).
Why does a trust policy for a third-party SaaS vendor require an External ID?
Federation: SSO and Identity Providers in the Cloud
Creating 5000 IAM users for a 5000-person company is a management failure. An employee joins - one must be created; leaves - one must be revoked; switches team - the permission boundary must be reassigned. Federation solves this by leaving the corporate identity provider (Okta, Azure AD, Google Workspace, AWS IAM Identity Center) as the source of truth. The employee signs in to the IdP, receives a SAML or OIDC token, and AWS STS exchanges it for temporary credentials via AssumeRoleWithSAML / AssumeRoleWithWebIdentity. No local accounts in AWS - identity is the same as for Slack, GitHub, and Notion.
Workload identity federation (AssumeRoleWithWebIdentity) solves authentication for workloads in the same way. GitHub Actions runs a CI job, identifies itself as 'repo:org/repo, branch:main', and AWS exchanges the OIDC token for STS credentials. No stored keys in GitHub Secrets and no long-lived deploy user. This is the 2024 standard: AWS, GCP, Azure, and Vault all support federation with GitHub, GitLab, and Kubernetes service accounts.
IAM policies are a formality; the main thing is not to expose resources externally through bucket policies
IAM policies are the primary security boundary. Resource-based policies complement identity-based ones but do not replace them. Most breaches start with compromised IAM credentials, not with public buckets
The Uber, Capital One, and Imperva incidents all began with leaked IAM credentials or excessive permissions. Locking buckets away from the public internet matters, but that is the last line of defence. Correct least-privilege policies, IAM roles instead of keys, and federation instead of local accounts are the primary line of defence for cloud infrastructure
GitHub Actions OIDC federation replaces which typical antipattern?
Key Takeaways
- **IAM roles replace static keys** with short-lived STS tokens; no credentials in code means no leak through GitHub.
- **JSON policy Effect/Action/Resource/Condition** is the principle of least privilege as a rule; an explicit Deny always overrides Allow.
- **Cross-account AssumeRole** grants access between accounts without sharing keys; External ID protects against confused-deputy with SaaS vendors.
- **Federation (SAML/OIDC)** makes the corporate IdP or GitHub OIDC the source of truth - local accounts in AWS almost disappear.
Related Topics
IAM is a cross-cutting security boundary that intersects networking, billing, and audit.
- DNS and Route 53 — IAM policies control access to Route 53 zones the same way they control S3 and EC2
- Cloud Networking and VPC — Conditions aws:SourceVpc and aws:SourceIp constrain IAM permissions by the network boundary
Вопросы для размышления
- Capital One lost data because of excessive IAM-role permissions, not because of a public bucket. How is a policy-review process organized so that Action: '*' does not slip into production?
- OIDC federation removes long-lived keys from CI. Which teams and tasks still need IAM users with access keys, and can they be fully weaned off?
- External ID protects against confused-deputy in vendor integrations. Which other categories of cross-account access call for additional conditions in the trust policy?
Связанные уроки
- cloud-12 — Previous cloud lesson - context for IAM
- cloud-14 — KMS uses IAM policy for key access control
- cloud-15 — Compliance requires IAM audit trail
- bt-28-security — IAM principles apply to API security
- net-44-zero-trust — Zero Trust = IAM everywhere, no perimeter
- prob-04-bayes — Policy evaluation is conditional inference of permissions
- devops-13