Skip to content

Cloud Automation Permission Review

Use this page before calling a cloud-aware automation path ready to run. The goal is to make permission and trust-policy work visible early, especially when a workflow, script, Lambda, role, or command gains new authority.

This page is an operations review policy, not a live permission inventory. Durable IAM resources and cloud outputs still belong to Pulumi, reviewed procedures belong to runbooks, and raw proof stays private unless reduced to a reusable lesson.

Run this review when a change introduces or broadens:

  • A GitHub Actions job that assumes an AWS role or uses a new GitHub environment secret.
  • A deploy, smoke, docs, topology, or operations command that calls cloud APIs.
  • A shell wrapper that sends SSM commands, invokes Lambda, pushes images, reads provider inventory, writes parameters, or mutates storage.
  • A Lambda, EventBridge rule, SSM document, instance profile, OIDC role, or resource policy.
  • A Pulumi change that creates, replaces, deletes, or broadens IAM, trust, DNS, runtime, storage, registry, or data-bearing resources.
  • A new source of live cloud evidence such as AWS inventory, workflow artifacts, topology captures, or discrepancy reports.

Do not wait for the first failed workflow run to discover the missing grant. Trace the action, resource, and trust path before presenting the automation as ready.

Every new or changed automation path should be explainable with this table:

QuestionRequired Answer
Who acts?The exact actor: GitHub OIDC role, runtime EC2 role, Lambda role, local infra operator, or service.
What API actions run?The cloud API actions or provider CLI operations, including read, write, wait, and cleanup calls.
Which resources?The smallest resource ARN, prefix, hosted-zone condition, parameter path, repository, or bucket.
What trust boundary?GitHub environment subject, service principal, Lambda invoke source, instance profile, or profile.
What evidence appears?Summary fields, artifact names, SSM command IDs, simulator output, smoke result, or preview line.
What is intentionally absent?Explicit non-goals such as no Pulumi update, no direct EC2 stop, no S3 delete, or no secret read.

If one answer is unknown, record the gap before mutation. Unknown permission scope is a work item, not a harmless detail.

Prefer the narrowest authority that still lets the automation complete:

  • Scope GitHub OIDC trust to the intended repository and environment.
  • Prefer separate roles for app deploy, docs deploy, topology ingest, and future live inventory instead of one broad shared deploy role.
  • Keep runtime host authority separate from GitHub orchestration authority.
  • Use Lambda or SSM documents as explicit control-plane boundaries when direct API access would be too broad.
  • Grant list/read access only where the command actually inspects state.
  • Add write/delete permissions only behind explicit command names, --execute gates, or reviewed workflow inputs.
  • Use resource tags, parameter prefixes, repository ARNs, bucket prefixes, hosted-zone conditions, or function ARNs where the provider supports them.
  • Name permission gaps beside the implementation work so the reviewer can see whether the code and IAM change belong in one patch or separate approvals.

Some AWS APIs require broad read scope or * resources. When that happens, document why the service requires it and keep the mutating action narrow.

The current deployed-dev shape intentionally splits authority:

ActorOwnsShould Not Own
GitHub app deploy roleImage push, guarded SSM runtime deploy/reset/readback, selected smoke permissions, shutdown invoke, and, after the modeled grant is applied, read-only deployment contract artifact access.Pulumi updates, broad inventory, direct EC2 start/stop, runtime secret reads, docs publishing, or deployment contract writes.
GitHub docs deploy roleDocs bucket object writes/deletes, docs CloudFront invalidation, and read-only deployment contract artifact access.App/API runtime mutation, app media buckets, ECR repositories, SSM runtime parameters, deployment contract writes, or DNS.
Runtime EC2 rolePull images, read runtime parameters, access media storage, and register with SSM.GitHub orchestration, Route53 control-plane writes, shutdown authority, or workflow summaries.
Wake Lambda roleStart the runtime host and refresh the dynamic app-origin record.EC2 stop, database/media cleanup, deploy-state ownership, or general DNS mutation.
Shutdown Lambda roleStop the runtime host through the approved host-stop path.Public routing, automatic scheduling by itself, S3/database cleanup, or deploy rollback.
Inactivity monitor Lambda roleRead CloudFront request activity, inspect runtime state, and invoke only the shutdown Lambda.Direct EC2 stop, Route53 writes, SSM access, S3 access, or release mutation.
GitHub infra-topology roleRead-only access to the self-managed Pulumi state backend for manual private topology capture and workflow artifact upload.Pulumi updates, routine app/docs CD, deployment contract writes, live AWS inventory, docs publish, commits, or cloud mutation.

When a new actor is needed, add it deliberately. Do not quietly reuse the nearest existing role if the new job has a different trust boundary, evidence path, or blast radius.

Before a cloud automation change is ready for review:

  • The owning actor and trust boundary are named.
  • The planned cloud API actions are listed, including wait/readback calls.
  • The target resources are scoped as tightly as the provider allows.
  • The explicit non-goals are written down.
  • The command or workflow has a dry-run, preview, or no-mutation mode where practical.
  • Mutating execution has a clear --execute, workflow input, environment protection, or human approval gate.
  • Required IAM, resource policy, trust-policy, or Pulumi changes are included in the scoped work or called out as a separate approval-gated step.
  • The expected evidence is safe to publish in workflow summaries, docs, or private artifacts.
  • Secret values, rendered env files, raw cloud inventory, and live identifiers do not cross the public docs boundary.

Use the narrowest durable home for the result:

Result TypeHome
Pulumi-owned role, policy, trust, resource, output, or lifecycle classInfrastructure Change Policy plus IaC source
Pipeline actor, job responsibility, profile, cloud plan, or CD secret flowDeployment Workflows
Repeated operator command, failure triage, reset, rollback, or recoveryRunbooks
Docs deploy role, docs bucket permissions, docs invalidation, publish gateDocs Hosting
Private raw evidence, sanitized projection, topology graph, publication gateGenerated Documentation
Command name, flag, compatibility script, or default mutation postureWavemap CLI Command Reference

Working notes may keep detailed proof history while the shape is moving. Once the actor boundary is stable, promote the reusable lesson here or into the owning operations page.