Least-privilege cloud IAM: policy scope, privilege-escalation paths, permissions boundaries, workload identity over static keys, MFA enforced by policy, cross-account trust, and separating deploy from runtime. Use when generating IAM policies, roles, or trust documents, wiring CI/CD service accounts or workload identities, delegating role creation, or designing cross-account access.
Scanned 9/6/2026
Install to Claude Code
npx -y skills add ShieldNet-360/secure-vibe --skill iam-best-practices --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Iam Best Practices?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/shieldnet-360-iam-best-practices-secure-vibe)More formats (shields.io, HTML) on the badges page.
---
name: iam-best-practices
description: "Least-privilege cloud IAM: policy scope, privilege-escalation paths, permissions boundaries, workload identity over static keys, MFA enforced by policy, cross-account trust, and separating deploy from runtime. Use when generating IAM policies, roles, or trust documents, wiring CI/CD service accounts or workload identities, delegating role creation, or designing cross-account access."
---
<!-- Native skill bundle for Claude Code. Generated by `secure-vibe dev regenerate`. -->
<!-- Do not edit by hand; the source of truth is skills/iam-best-practices/SKILL.md. -->
# Identity & Access Management Best Practices
Least-privilege cloud IAM: policy scope, privilege-escalation paths, permissions boundaries, workload identity over static keys, MFA enforced by policy, cross-account trust, and separating deploy from runtime. Use when generating IAM policies, roles, or trust documents, wiring CI/CD service accounts or workload identities, delegating role creation, or designing cross-account access.
## ALWAYS
- Grant the minimum permissions the workload's stated job requires: deny by default, then add concrete actions against concrete resources. A wildcard action on a wildcard resource — in a custom policy, in `AdministratorAccess`, or in `iam:*` attached to something that runs continuously — is the same finding wearing three different names.
- Read a policy for the **privileges it can reach**, not only the ones it names. A principal that can write policy (`iam:PutRolePolicy`, `iam:AttachRolePolicy`, `iam:CreatePolicyVersion`) can grant itself anything, and a principal that can pass a role into a compute service it may also create (`iam:PassRole` with `lambda:CreateFunction`, `ec2:RunInstances`, `glue:CreateJob`) inherits that role's privileges. These read as narrow grants and are administrative ones. `references/escalation-paths.md` lists the combinations worth failing a review over.
- Bound delegated permissions with a **permissions boundary** or an organization-level policy (SCP, GCP org policy, Azure management-group policy) when teams may create their own roles. The boundary caps what any role they create can do, which is what makes self-service role creation safe rather than a privilege-escalation primitive.
- Prefer **workload identity** — IRSA on EKS, GKE Workload Identity, Azure Managed Identity, OIDC federation from CI — over a static key. The goal is that no long-lived credential exists to leak. Where one is genuinely unavoidable, give it a documented rotation cadence and automatic disablement on inactivity, and treat that as a temporary state rather than the steady state.
- Enforce MFA for human principals through a **policy condition** (`aws:MultiFactorAuthPresent`), not only a directory setting, so a credential that bypasses the directory still cannot act.
- Separate the **deploy** identity from the **runtime** identity. The pipeline gets permission to create and change infrastructure; the running service gets permission to do its job and nothing that mutates IAM. `cicd-security` owns hardening the pipeline that holds the deploy role.
- Scope cross-account trust to the actual counterparty. Inside your own organization that means a specific principal ARN or `aws:PrincipalOrgID`; for a **third party** acting on your behalf it additionally means an `ExternalId` — a per-consumer value the third party supplies, which defeats the confused-deputy case where another of their customers can name your account. Treat `ExternalId` as an identifier, not a secret: it is not one, and relying on its confidentiality is a false assurance.
- Keep sessions short and make the length a deliberate choice. Human and CI roles should use the shortest session the workflow tolerates. A longer window on a break-glass role is a defensible operational trade — an incident should not expire mid-response — but it has to be stated as a decision, paired with alerting, and not copied onto ordinary roles.
- For Kubernetes RBAC, scope `Role` and `RoleBinding` to one namespace and reserve `ClusterRole` for genuinely cluster-wide objects. Review every `cluster-admin` binding at pull-request time, and remember that permission to create workloads in a namespace is permission to use every service account in it.
- Log IAM-mutating calls to a tamper-evident sink and alert on them: policy changes, `iam:PassRole`, access-key creation, and role assumption from an unexpected principal. `logging-security` owns the shape of the record.
- Require out-of-band approval for break-glass use (root, organization owner, `cluster-admin`) and alert on every invocation, not on a sample.
## NEVER
- Use the root or organization-owner account for day-to-day work. It gets a hardware MFA device, offline storage, and only the tasks that genuinely require it.
- Embed a long-lived access key in source, a container image, a machine image, or a CI environment variable where a workload identity or OIDC federation is available.
- Grant `iam:PassRole` with `Resource: "*"`. Pin the exact role ARNs the caller may pass, and read that grant together with what the caller can launch.
- Share one principal between multiple humans or multiple services. One identity per actor is what makes the audit log mean anything.
- Disable MFA for a principal to resolve a login problem. Rotate the device; the requirement stays.
- Persist an OIDC or SAML assertion beyond its stated lifetime. Refresh by re-assertion rather than storing the original token.
## KNOWN FALSE POSITIVES
- `Resource: "*"` on APIs that accept no resource ARN — `sts:GetCallerIdentity`, `ec2:DescribeRegions` and their equivalents. The wildcard is the only expressible value, so the finding is the *action* being unnecessary, not the resource scope.
- Provider-managed service-linked roles carry broader permissions than a role you would write. That breadth is the provider's contract and is not yours to narrow.
- A bootstrap operator in a fresh account often needs elevated permissions before the guardrails it installs exist. Gate it by tag or organization policy and revoke on completion — a bootstrap role that survives bootstrap is a finding again.
- Local development emulators accept any credential. That is a property of the emulator, not a grant in your account.
- Enumerating explicit resource ARNs is correct for a bounded set. Attribute-based scoping (tags, organization paths) is the answer when the set grows, not a security upgrade over naming resources you can name.
## Reference files
Read these only when the task calls for them.
- `references/escalation-paths.md`
- `references/verifying-findings.md`
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!