Identity & Access Management Best Practices
SkillDocs & knowledgeLeast-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.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Identity & Access Management Best Practices skill
What this skill tells your AI
The instructions your AI receives, as published by shieldnet-360/secure-vibe in skills/iam-best-practices/SKILL.md and read by ahel’s review.
Rules (for AI agents)
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 iniam:*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:PassRolewithlambda:CreateFunction,ec2:RunInstances,glue:CreateJob) inherits that role's privileges. These read as narrow grants and are administrative ones.references/escalation-paths.mdlists 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-securityowns 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 anExternalId— a per-consumer value the third party supplies, which defeats the confused-deputy case where another of their customers can name your account. TreatExternalIdas 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
RoleandRoleBindingto one namespace and reserveClusterRolefor genuinely cluster-wide objects. Review everycluster-adminbinding 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-securityowns 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:PassRolewithResource: "*". 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:DescribeRegionsand 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.
Context (for humans)
Cloud IAM has one property that makes reviewing it different from reviewing other
access control: the effective permission set is not the stated one. A role that
can attach a policy can attach AdministratorAccess to itself. A role that can pass
another role into a service it can also create runs as that role. Neither policy
contains a wildcard, and both are administrative. Reading a policy for what it says,
rather than for what it can reach, is the failure that produces most
over-permissioned estates.
The second property is that the scalable answer is rarely a better-written policy.
Permissions boundaries and organization policies are what let a platform team hand
role creation to product teams without handing over the account, and attribute-based
scoping is what keeps a policy correct as the resource set grows. Enumerating ARNs
more carefully does not scale past the point where someone starts pasting * to make
the deploy pass.
Capital One (2019) and Uber (2022) are the canonical illustrations of the two halves: an over-permissioned role reached through a server-side request, and a static credential found in a script after an MFA-fatigue login.
References
references/verifying-findings.md— confirm or refute a finding, then lock itreferences/escalation-paths.md— the permission combinations that are administrative without containing a wildcard, and how boundaries cap themrules/iam_policy_invariants.jsonrules/key_rotation_policy.json- AWS IAM best practices.
- Google Cloud IAM recommender.
- CNCF Kubernetes RBAC good practices.
- NIST SP 800-53 Rev. 5.
Signals
- GitHub stars
- 22
- Last commit
- Aug 2026
Advanced
- Catalog kind
- skill
- Gateway key
iam-best-practices- Source
- github.com/shieldnet-360/secure-vibe