# AWS Resources & Runtime Access

Applications use short-lived ECS task-role credentials. Declare resources once, then bind each resource only to the services that need it.

```yaml
resources:
  uploads:
    type: s3
    create:
      versioning: true
    retain: true

  events:
    type: sns
    existing:
      arn: arn:aws:sns:us-east-1:123456789012:application-events

  reporting:
    type: rds
    existing:
      identifier: reporting-prod
      endpoint: reporting.internal
      port: 5432
      security_group_id: sg-0123456789
      secret_arn: arn:aws:secretsmanager:us-east-1:123456789012:secret:reporting
      kms_key_arn: arn:aws:kms:us-east-1:123456789012:key/00000000-0000-0000-0000-000000000000

services:
  web:
    type: web
    port: 8080
    health_check: /health
    bindings:
      - resource: uploads
        access: [list, read, write]
        prefix: user-content
      - resource: events
        access: [publish]
      - resource: reporting
        access: [connect]
```

Keel creates a separate IAM task role and security group for each service. S3, SNS, and SQS bindings become resource-scoped IAM statements. RDS and cache bindings add ingress rules to the linked security group. Keel injects resource identifiers through variables such as `UPLOADS_BUCKET_NAME` and `EVENTS_TOPIC_ARN`, and linked secrets through ECS secret injection.

## Supported capabilities

| Type | Ownership | Capabilities |
|------|-----------|--------------|
| S3 | managed or existing | `list`, `read`, `write`, `delete` |
| SNS | managed or existing | `publish` |
| SQS | managed or existing | `send`, `consume` |
| RDS / cache | existing | `connect` |
| IAM role | existing | `assume` |

An IAM-role binding grants the service `sts:AssumeRole`. The target role's trust policy must also trust the generated `<app>-<service>-ecs-task` role, including for cross-account access.

For an AWS service without a curated resource type, use an advanced custom IAM statement on the service and keep actions/resources narrowly scoped:

```yaml
services:
  worker:
    permissions:
      - actions: [ses:SendEmail]
        resources: [arn:aws:ses:us-east-1:123456789012:identity/example.com]
```

Set `kms_key_arn` for an existing resource or secret encrypted with a customer-managed KMS key. Keel adds the necessary data-key and decrypt actions. For cross-account access, the resource, role, or KMS key policy in the owning account must also authorize the generated service task role.

Private subnets automatically receive a free S3 gateway endpoint when an S3 resource is configured. Set `vpc.private_aws_endpoints: true` to provision interface endpoints for configured SNS, SQS, and STS access.

## What `retain` means

`retain` defaults to `true` and controls what happens to managed data resources during `keel destroy`:

- **S3, SNS, and SQS:** `keel destroy` removes the resource from Keel state but leaves it in AWS, where it continues to incur charges. Keel prints the AWS CLI command to delete each retained resource. During normal applies, `retain` also sets `lifecycle { prevent_destroy = true }`.

- **Database:** Keel cannot retain the live RDS instance while removing its VPC and security group. Instead, `database.retain` enables deletion protection and creates a final snapshot. Teardown prints the command to restore it.

`keel destroy` names everything it will delete and everything it will keep, then asks you to type the app name. Two flags change what survives:

- `--delete-retained` destroys `retain: true` resources along with the stack.
- `--no-final-snapshot` deletes the database without a snapshot.

Deployment history also survives by default. Remove it with `--prune-history` during teardown or `keel history prune` later. See [Interruptions & Rescue](./rescue) for other account-wide state.

**After redeploying an app whose resources were retained**
The new `keel up` will collide with the surviving names — delete them, rename the resource in `keel.yml`, or import them first.

## Resource commands

```bash
# Create and bind a managed resource
keel resources add s3 uploads --versioning --bind web:list,read,write

# Link an existing resource without transferring ownership to Keel
keel resources link arn:aws:sns:us-east-1:123456789012:application-events \
  --as events --bind web:publish

# Change access later
keel resources bind uploads worker --access read
keel resources unbind uploads worker

# Inspect the complete app inventory and effective rules
keel resources
keel resources show uploads
keel resources show @load-balancer
keel resources --service web
keel resources --json

# Inspect access from a service's point of view
keel access show web
keel access explain web uploads
```

Built-in resources use `@` names in the inventory, including `@vpc`, `@cluster`, `@registry`, `@load-balancer`, `@logs`, and optional add-ons such as `@database`, `@cache`, `@domain`, and `@waf`.
