> ## Documentation Index
> Fetch the complete documentation index at: https://synthetiq.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Permissions

> The AWS permissions each provisioning stage requires

Every resource the provisioner creates is namespaced under `synthetiq-*` and managed through CloudFormation. The provisioner never modifies or accesses existing resources in your account. Each stage of the lifecycle needs strictly more access than the last, and the CLI prints the exact policy for any of them:

```bash theme={null}
# optional, strictly read-only discovery
synthetiq infra permissions \
  --stage init

# plan: change-set creation, nothing modified
synthetiq infra permissions \
  --stage generate

# apply: the full provisioning policy (the default)
synthetiq infra permissions \
  --stage provision
```

Each prints a ready-to-attach IAM policy JSON. Grant only the stage you're running: a config-authoring laptop needs at most the `init` policy, a CI plan job the `generate` policy, and only the principal that actually applies changes needs the full `provision` policy.

## `init` — strictly read-only discovery (optional)

`init` needs no AWS access at all — without credentials it runs in offline mode and asks for values instead of discovering them. With credentials, it uses read-only discovery so the interview can offer real choices. **There is not a single write action in this policy**:

| Purpose                           | Actions                                                                                                                                                                                 |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Confirm the target account        | `sts:GetCallerIdentity`                                                                                                                                                                 |
| Network discovery (read-only)     | `ec2:DescribeVpcs`, `DescribeSubnets`, `DescribeAvailabilityZones`, `DescribeNatGateways`, `DescribeRouteTables`, `DescribeSecurityGroups`, `DescribeAddresses`, `DescribeVpcEndpoints` |
| Certificate discovery (read-only) | `acm:ListCertificates`, `DescribeCertificate`                                                                                                                                           |

## `generate` — plan, touching nothing

`generate` validates the config against the real account and creates the CloudFormation change sets — the plan — without executing anything. On top of init's read-only discovery (minus all write actions), it adds:

| Purpose                        | Actions                                                                                                                         | Resource scope             |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | -------------------------- |
| Create and inspect change sets | `cloudformation:CreateChangeSet`, `DescribeChangeSet`, `DeleteChangeSet`, `DescribeStacks`, `GetTemplateSummary`, `DeleteStack` | `synthetiq-*` stacks only  |
| Stage the template             | `s3:CreateBucket`, `DeleteBucket`, `PutObject`, `DeleteObject`, `ListBucket`, `GetBucketLocation`                               | `synthetiq-*` buckets only |
| Verify certificates            | `acm:DescribeCertificate`, `ListCertificates`                                                                                   | —                          |

No infrastructure is created or modified: the only writes are the change-set object itself and the staged template in a `synthetiq-*` bucket. (`DeleteStack` looks alarming but is scoped to `synthetiq-*` stacks and exists to clean up the empty `REVIEW_IN_PROGRESS` placeholder CloudFormation leaves behind when an initial-provision change set fails validation — it can't touch a provisioned stack's resources without `ExecuteChangeSet`.)

## `provision` — the full policy

`provision` executes the reviewed change sets, so its principal needs everything CloudFormation will do on your behalf — IAM roles, ECS, load balancers, Lambda, CloudFront, and the rest — plus the direct finishing steps (deploy-key secret, metrics API deployment). This is the full policy printed by `synthetiq infra permissions`. For a sandbox account, **AdministratorAccess** is fine.

The policy is **scoped to the `synthetiq-*` namespace** wherever AWS resource ARNs allow it — including `iam:PassRole`, which is restricted to the Synthetiq roles. A smaller set of actions remain account-wide because AWS doesn't support resource-level scoping for them (read-only describes, account-level log policy) or because the resources have AWS-assigned random IDs (CloudFront, API Gateway).

<Accordion title="AWS services in the provision policy">
  * CloudFormation
  * IAM (roles, OIDC providers, policies)
  * ECS and ECR
  * EC2 (subnets, NAT gateway, security groups, VPC endpoints)
  * Elastic Load Balancing
  * S3
  * Lambda
  * Step Functions
  * CodeBuild
  * CloudFront
  * DynamoDB
  * ACM (certificate verification)
  * API Gateway
  * Secrets Manager
  * CloudWatch Logs
  * Application Auto Scaling
</Accordion>

<Note>
  The stage split maps directly onto a CI setup: the pull-request **plan** role gets the `generate` policy, and the merge-gated **apply** role gets the `provision` policy. See [CI Integration](/docs/platform-docs/deployments/byoi/ci-integration).
</Note>
