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

# AWS configuration

> Configure an AWS target for formae: credentials and target settings.

The AWS plugin enables formae to manage AWS resources using the [AWS Cloud Control API](https://docs.aws.amazon.com/cloudcontrolapi/latest/userguide/what-is-cloudcontrolapi.html).

## Configuration

### Target

Configure an AWS target in your Forma file:

```kotlin theme={"languages":{"custom":["/languages/pkl.json"]}}
import "@formae/formae.pkl"
import "@aws/aws.pkl"

target: formae.Target = new formae.Target {
    label = "aws-target"
    config = new aws.Config {
        region = "us-east-1"
        // Optional: specify a named profile
        // profile = "my-profile"
    }
}
```

**Config field mutability:**

| Field     | Mutable | Description                                                                                             |
| --------- | ------- | ------------------------------------------------------------------------------------------------------- |
| `profile` | Yes     | Changing the profile updates the target in place                                                        |
| `region`  | No      | Changing the region triggers a full [target replace](/documentation/concepts/target#replacing-a-target) |

See [Replacing a target](/documentation/concepts/target#replacing-a-target) for details.

### Credentials

The plugin uses the standard AWS credential chain. Configure credentials using one of the following methods:

**Environment Variables:**

```bash theme={"languages":{"custom":["/languages/pkl.json"]}}
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_REGION="us-east-1"

# For temporary credentials (e.g., from STS AssumeRole)
export AWS_SESSION_TOKEN="your-session-token"
```

**Named Profile:**

```bash theme={"languages":{"custom":["/languages/pkl.json"]}}
# Use a profile from ~/.aws/credentials
export AWS_PROFILE="my-profile"
```

You can also restrict credential usage to a named profile using the `profile` property:

```kotlin theme={"languages":{"custom":["/languages/pkl.json"]}}
config = new aws.Config {
    region = "us-east-1"
    profile = "my-profile"
}
```

```ini theme={"languages":{"custom":["/languages/pkl.json"]}}
# ~/.aws/credentials
[my-profile]
aws_access_key_id = YOUR_ACCESS_KEY_ID
aws_secret_access_key = YOUR_SECRET_ACCESS_KEY
```

**IAM Instance Profile / ECS Task Role:**
When running on EC2 or ECS, credentials are automatically retrieved from the instance metadata service.

**OIDC (for CI/CD):**
For GitHub Actions, use `aws-actions/configure-aws-credentials` with OIDC federation.

### Required IAM permissions

The credentials above must be allowed to perform the operations the plugin needs. Two distinct sets of permissions apply:

* **Apply / destroy**: create, read, update, and delete the resource types in your formas. The AWS-managed `PowerUserAccess` policy covers most services, but **excludes IAM**; managing IAM resources (roles, policies, users, instance profiles) requires explicit `iam:*` grants.
* **Discovery**: the agent continuously discovers existing resources via the CloudControl `ListResources` API. This needs **read-only `List*` / `Describe*` / `Get*` permissions** across the services you want discovered. For IAM in particular, `PowerUserAccess` does not grant `iam:List*` / `iam:Get*`, so without them discovery logs recurring `403` errors (e.g. `iam:ListServerCertificates`, `iam:ListSAMLProviders`, `iam:ListOpenIDConnectProviders`, `iam:ListGroups`).

For a complete, copy-pasteable task-role policy, including the IAM management and read-only discovery statements, see [Install on AWS: Create IAM roles](/documentation/guides/install-agent).
