Iam best practices
Least-privilege IAM design, key rotation, MFA enforcement, role assumption, and cross-account access patterns for AWS / GCP / Azure / KubernetesFrom its SKILL.md
npx -y skills add ShieldNet-360/secure-vibe --skill iam-best-practicesAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
8.7 KB, ~1.9k tokens by cl100k_base, as published. Nobody here has run it
Identity & Access Management Best Practices
Rules (for AI agents)
ALWAYS
- Grant the minimum permissions required for the workload's stated job
(NIST AC-6). Start with a deny-by-default policy and add concrete actions
with explicit
ResourceARNs; neverAction: "*"combined withResource: "*". - Prefer workload identity (IAM roles for service accounts on EKS, GKE Workload Identity, Azure Managed Identity) over long-lived access keys. Static access keys are the exception, not the default.
- Require MFA for every human IAM user, especially any principal that
can assume a privileged role. Enforce MFA via an IAM policy condition
(
aws:MultiFactorAuthPresent: true), not just a directory-level setting. - Rotate access keys, service-account keys, and signing keys on a documented schedule (≤ 90 days). Detect inactive credentials (≥ 90 days unused) and disable them automatically.
- Use role assumption with
sts:AssumeRole+ ExternalId for cross-account trust. The ExternalId must be unique per consumer and stored as a secret in both accounts. - Issue session-scoped credentials with
MaxSessionDuration ≤ 1hfor human roles and ≤ 12h for break-glass roles. Long-lived sessions defeat rotation. - Separate deploy and runtime identities. The CI/CD pipeline gets a deploy role; the running service gets a distinct runtime role with no IAM-mutating permissions.
- For Kubernetes RBAC, scope
Role/RoleBindingto a single namespace; useClusterRoleonly for true cluster-wide objects. Auditcluster-adminbindings on every PR. - Log every IAM-mutating call (CloudTrail / Cloud Audit Logs / Azure
Activity Log) to a tamper-evident sink. Alert on policy changes,
iam:PassRole,iam:CreateAccessKey, andsts:AssumeRolefrom unexpected principals. - For break-glass access (root, owner, cluster-admin), require an out-of-band approval (e.g., PagerDuty incident + ticket) and emit an immediate alert on every use.
- Tag every IAM principal with
owner,environment, andpurpose. Use these tags in SCPs / org policies to constrain blast radius.
NEVER
- Use the root account for day-to-day operations. Root credentials get a hardware MFA device, are stored offline, and are used only for the small set of root-only tasks (e.g., closing the account, changing the support plan).
- Embed long-lived access keys in source, container images, AMIs, or CI environment variables when a workload identity is available.
- Grant
iam:PassRolewithResource: "*". Always pin the role ARNs the caller may pass to downstream services. - Grant
iam:*orsts:*to a runtime workload — these are deploy-time permissions only. - Share a single IAM user across multiple humans or services. One principal per identity is the audit invariant.
- Use
AdministratorAccess(or any*:*) managed policy on a routine basis; treat it as a break-glass-only attachment. - Trust any cross-account assume-role without an
ExternalIdcondition for third-party integrations (Confused Deputy: AWS Security Bulletin 2021). - Hard-code AWS / GCP / Azure ARNs / resource IDs in policy documents without a corresponding tag-based or organization-path scope (when the number of resources can grow).
- Disable MFA for a principal to "fix" a login problem — rotate the device, do not remove the requirement.
- Persist OIDC / SAML assertion tokens beyond their stated TTL. Refresh by re-assertion, not by storing the original token.
KNOWN FALSE POSITIVES
Resource: "*"is acceptable for inherently account-scoped read operations likeec2:DescribeRegionsorsts:GetCallerIdentity— those APIs do not accept a resource ARN.- Service-linked roles (e.g.,
AWSServiceRoleForAutoScaling) ship with broader permissions than your custom roles; that is by design and managed by the provider. - One-time bootstrap operators (Terraform-runners in a fresh account) often need elevated permissions; gate by tag / SCP and revoke after the bootstrap is complete.
- Local-development emulators (LocalStack, GCS emulator) may accept any credentials; that is a property of the emulator, not a real grant.
Context (for humans)
Identity & access management is the foundation of every cloud security
control. The recurring failure modes are: over-permissive policies
(*:*), long-lived access keys checked into git, missing MFA on
privileged accounts, and AssumeRole trust policies without an
ExternalId. These are the same root causes documented in the Capital
One (2019), Verkada (2021), and Uber (2022) breaches.
The high-leverage controls are:
- Workload identity over access keys. A pod in EKS that assumes a role via IRSA never needs a credential to leak.
- MFA on every human, enforced by policy. A leaked password alone is no longer sufficient to act.
- Least-privilege grants reviewed at PR time. The cheapest moment to constrain a permission is when it's being added — not when an auditor asks six months later.
- Mandatory key rotation. Static credentials silently age into liabilities; automate the rotation so it is not skipped.
- Cross-account trust with ExternalId. The Confused Deputy class of attacks is fully mitigated by an ExternalId convention.
This skill enforces those controls when AI assistants generate IAM policies, trust documents, or CI/CD identities.
Verify & lock (triaging a finding)
A scanner/review hit is a candidate, not a confirmed bug. Confirm it, fix it, then lock it so it can't come back.
- Confirm it's real (simulate, don't eyeball). A wildcard in JSON isn't
proof — what the effective policy resolves to is. Run the provider's policy
evaluator:
aws iam simulate-principal-policy(or GCP Policy Troubleshooter, Azureaz role assignment list) for the flagged action against a concrete resource —iam:PassRole,iam:CreateAccessKey/AttachUserPolicy(priv-esc),*:*,s3:*on*, or a cross-accountsts:AssumeRole. Or, in a sandbox, assume the role and attempt the dangerous action. Real if the result is ALLOWED; FP if a permission boundary, SCP, orConditionalready denies it (or it's an account-scoped read likeec2:DescribeRegionsthat ignores ARNs). For credentials/MFA, check the live fact: key age & last-used (aws iam get-access-key-last-used), and whetheraws:MultiFactorAuthPresentis actually enforced — not just toggled in the directory. - Fix, then lock with a regression test (unit or integration — dev's call):
pin the action and
ResourceARN, add the missingExternalId/MFA/expiry condition, or swap the long-lived key for a workload identity. Then add a policy unit test (or CI check on the policy JSON) asserting the simulator DENIES the dangerous action and ALLOWS the workload's legitimate one, plus a lint that fails onAction:"*"+Resource:"*",PassRoleon*, or trust withoutExternalId. Commit it so the guard can't be silently dropped.
References
rules/iam_policy_invariants.jsonrules/key_rotation_policy.json- AWS IAM Best Practices.
- Google Cloud IAM recommender.
- NIST SP 800-53 Rev. 5.
- CIS Controls v8.
- CNCF Kubernetes RBAC Good Practices.
What ships with it: 3 files
10.5 KB alongside SKILL.md
rules/
tests/
- corpus.json4.7 KB