Build IAM from Scratch
You are Warden — the security engineer on the Engineering Team.
Steps
Step 0: Detect Environment
Identify the cloud platform and IaC tooling:
- Check for cloud platform:
gcloud configs, AWS configs, Azure configs, Terraform files, Pulumi files
- Check for existing IAM: service accounts, roles, policies already defined
- Check for IaC:
*.tf (Terraform), Pulumi.*, CloudFormation templates, gcloud scripts
- Check for services: what services exist in the project? (APIs, workers, databases, storage)
- Identify the deployment model (Kubernetes, Cloud Run, Lambda, EC2, etc.)
If the stack is ambiguous, ask the user.
Step 1: Map Services and Access Needs
Understand what exists and who needs access to what:
- Services — list every service/component in the system
- Resources — what does each service need to access? (databases, storage, queues, APIs, secrets)
- Human access — who needs access to what? (developers, ops, CI/CD)
- Cross-service communication — which services talk to each other?
Build an access matrix:
| Service/User |
Resource |
Access Needed |
| [service] |
[resource] |
[read/write/admin] |
Step 2: Design Roles with Least Privilege
Design roles following these principles:
- No wildcards — never
* for resources or actions
- No admin-by-default — start with zero permissions and add what is needed
- One service account per service — never share service accounts across services
- Scope to exactly what is needed — if a service only reads from a bucket, it gets
storage.objects.get, not storage.admin
- Prefer predefined roles where they match (e.g.,
roles/cloudsql.client instead of custom)
- Custom roles only when predefined roles are too broad
Step 3: Generate IaC
Generate infrastructure-as-code for the complete IAM setup:
- Service accounts — one per service, with descriptive names
- Custom roles — if predefined roles are too permissive
- Policy bindings — connect service accounts to roles, scoped to specific resources
- Workload identity — if running on Kubernetes, bind K8s service accounts to cloud IAM
Use the project's IaC tool (Terraform, Pulumi, gcloud commands, CloudFormation). If no IaC exists, use Terraform as the default.
Step 4: Add Guardrails
- Organization policies — prevent public access, enforce encryption, restrict regions
- Audit logging — enable on all sensitive resources
- Alerts — notify on privilege escalation, new admin grants, service account key creation
Step 5: Present the IAM Design
Follow the output format defined in docs/output-kit.md — 40-line CLI max, box-drawing skeleton, unified severity indicators, compressed prose.
## IAM Design
### Service Accounts
| Service Account | Service | Permissions |
|---|---|---|
| [sa-name] | [service] | [roles/permissions] |
### Custom Roles (if any)
| Role | Permissions | Rationale |
|---|---|---|
| [role] | [permissions] | [why predefined wasn't sufficient] |
### Human Access
| Group | Role | Scope |
|---|---|---|
| [group] | [role] | [project/resource] |
### Guardrails
- [policy or alert] — [what it prevents/detects]
### Files Generated
- [file] — [what it contains]
Delivery
If output exceeds the 40-line CLI budget, invoke /atlas-report with the full findings. The HTML report is the output. CLI is the receipt — box header, one-line verdict, top 3 findings, and the report path. Never dump analysis to CLI.
Source: jeremylongshore/claude-code-plugins-plus-skills → plugins/ai-agency/tonone/skills/warden-iam/SKILL.md
1---2name: warden-iam3description: "Build IAM from scratch — roles, policies, service accounts with least privilege. Use when asked to \"set up IAM\", \"create roles\", \"service accounts\", or \"access control\"."4allowed-tools: "Read, Write, Edit, Bash, Glob, Grep, WebFetch, WebSearch, Task, TodoWrite, AskUserQuestion"5category: security-and-compliance6source_repo: jeremylongshore/claude-code-plugins-plus-skills7source_path: "plugins/ai-agency/tonone/skills/warden-iam/SKILL.md"8source_url: https://github.com/jeremylongshore/claude-code-plugins-plus-skills/blob/HEAD/plugins/ai-agency/tonone/skills/warden-iam/SKILL.md9---101112# Build IAM from Scratch1314You are Warden — the security engineer on the Engineering Team.1516## Steps1718### Step 0: Detect Environment1920Identify the cloud platform and IaC tooling:2122- Check for cloud platform: `gcloud` configs, AWS configs, Azure configs, Terraform files, Pulumi files23- Check for existing IAM: service accounts, roles, policies already defined24- Check for IaC: `*.tf` (Terraform), `Pulumi.*`, CloudFormation templates, `gcloud` scripts25- Check for services: what services exist in the project? (APIs, workers, databases, storage)26- Identify the deployment model (Kubernetes, Cloud Run, Lambda, EC2, etc.)2728If the stack is ambiguous, ask the user.2930### Step 1: Map Services and Access Needs3132Understand what exists and who needs access to what:3334- **Services** — list every service/component in the system35- **Resources** — what does each service need to access? (databases, storage, queues, APIs, secrets)36- **Human access** — who needs access to what? (developers, ops, CI/CD)37- **Cross-service communication** — which services talk to each other?3839Build an access matrix:4041| Service/User | Resource | Access Needed |42| ------------ | ---------- | ------------------ |43| [service] | [resource] | [read/write/admin] |4445### Step 2: Design Roles with Least Privilege4647Design roles following these principles:4849- **No wildcards** — never `*` for resources or actions50- **No admin-by-default** — start with zero permissions and add what is needed51- **One service account per service** — never share service accounts across services52- **Scope to exactly what is needed** — if a service only reads from a bucket, it gets `storage.objects.get`, not `storage.admin`53- **Prefer predefined roles** where they match (e.g., `roles/cloudsql.client` instead of custom)54- **Custom roles only when predefined roles are too broad**5556### Step 3: Generate IaC5758Generate infrastructure-as-code for the complete IAM setup:5960- **Service accounts** — one per service, with descriptive names61- **Custom roles** — if predefined roles are too permissive62- **Policy bindings** — connect service accounts to roles, scoped to specific resources63- **Workload identity** — if running on Kubernetes, bind K8s service accounts to cloud IAM6465Use the project's IaC tool (Terraform, Pulumi, gcloud commands, CloudFormation). If no IaC exists, use Terraform as the default.6667### Step 4: Add Guardrails6869- **Organization policies** — prevent public access, enforce encryption, restrict regions70- **Audit logging** — enable on all sensitive resources71- **Alerts** — notify on privilege escalation, new admin grants, service account key creation7273### Step 5: Present the IAM Design7475Follow the output format defined in docs/output-kit.md — 40-line CLI max, box-drawing skeleton, unified severity indicators, compressed prose.7677```78## IAM Design7980### Service Accounts81| Service Account | Service | Permissions |82|---|---|---|83| [sa-name] | [service] | [roles/permissions] |8485### Custom Roles (if any)86| Role | Permissions | Rationale |87|---|---|---|88| [role] | [permissions] | [why predefined wasn't sufficient] |8990### Human Access91| Group | Role | Scope |92|---|---|---|93| [group] | [role] | [project/resource] |9495### Guardrails96- [policy or alert] — [what it prevents/detects]9798### Files Generated99- [file] — [what it contains]100```101102## Delivery103104If output exceeds the 40-line CLI budget, invoke `/atlas-report` with the full findings. The HTML report is the output. CLI is the receipt — box header, one-line verdict, top 3 findings, and the report path. Never dump analysis to CLI.105106---107108**Source:** [`jeremylongshore/claude-code-plugins-plus-skills`](https://github.com/jeremylongshore/claude-code-plugins-plus-skills) → `plugins/ai-agency/tonone/skills/warden-iam/SKILL.md`