> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.islo.dev/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.islo.dev/_mcp/server.

# AWS

> Give an Islo sandbox access to your AWS account by registering an IAM role for it to assume.

An Agent can reach AWS through the gateway profile on its [Machine](/concepts/machines). This integration guide covers the IAM role and gateway setup behind that access.

Islo can give a sandbox access to your AWS account without ever putting long-lived credentials inside the sandbox. You register an IAM role you own, and the sandbox assumes it via STS.

Any tool that uses the AWS SDK default credential chain — AWS CLI, boto3, the Go/JS SDKs, `mount-s3`, Terraform — works out of the box. No env vars, no `~/.aws/credentials`, no per-tool configuration.

## How it works

1. You create an IAM role in your AWS account with a trust policy that allows Islo to assume it.
2. You register that role with Islo as a **cloud role**, which returns an External ID you paste into the trust policy.
3. You attach the cloud role to a **gateway profile**.
4. Any sandbox attached to that gateway can call AWS APIs as that role, with no credentials in the sandbox.

## Prerequisites

* An Islo account and API key — see [Authentication](/cli/authentication).
* Permission to create IAM roles in the target AWS account.

## 1. Create the IAM role in AWS

Create a role in your AWS account with whatever permissions the sandbox should have. The example below scopes to a single S3 bucket; substitute any other AWS service.

**Permissions policy** (example — read/write a bucket):

```json
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["s3:ListBucket", "s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
    "Resource": [
      "arn:aws:s3:::my-bucket",
      "arn:aws:s3:::my-bucket/*"
    ]
  }]
}
```

**Trust policy** — leave `<ISLO_PRINCIPAL_ARN>` and `<EXTERNAL_ID>` as placeholders for now; you'll fill them in after step 2.

```json
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"AWS": "<ISLO_PRINCIPAL_ARN>"},
    "Action": "sts:AssumeRole",
    "Condition": {"StringEquals": {"sts:ExternalId": "<EXTERNAL_ID>"}}
  }]
}
```

The Islo Principal ARN is shown in the dashboard under **Integrations → AWS**.

## 2. Register the role with Islo

**`Python`**

```python title="Python"
from islo import Islo

client = Islo()  # picks up ISLO_API_KEY

role = client.cloud_roles.create_cloud_role(
    provider="aws",
    role_arn="arn:aws:iam::123456789012:role/IsloAccessRole",
    session_duration_seconds=3600,  # optional — STS session lifetime
)
print(role.external_id)
```

Copy `role.external_id` and paste it into the trust policy you wrote in step 1, then save the IAM role.

> **Tip**
>
> You can also register cloud roles from the dashboard at **Integrations → AWS → Add role**. The dashboard generates the External ID and shows the trust policy snippet you need to paste into AWS.

## 3. Attach the role to a gateway profile

```python
gateway = client.gateway_profiles.create_gateway_profile(
    name="aws-access",
    internet_enabled=True,
    cloud_role=role.id,
)
```

You can attach the same cloud role to multiple gateway profiles, or scope different gateways to different roles for least-privilege access.

## 4. Attach the gateway to a sandbox

```python
client.sandboxes.create_sandbox(
    name="my-sandbox",
    gateway_profile=gateway.id,
)
```

That's it. Inside the sandbox, any AWS SDK will discover credentials automatically.

## Using AWS from inside the sandbox

Any AWS CLI or SDK call just works:

```bash
# AWS CLI without any AWS_* env vars set
aws s3 ls s3://my-bucket/

# boto3
python -c "import boto3; print(boto3.client('s3').list_buckets())"
```

## Example: mount an S3 bucket with mount-s3

[Mountpoint for Amazon S3](https://github.com/awslabs/mountpoint-s3) (`mount-s3`) is AWS's official FUSE client. It uses the default credential chain, so once the gateway is attached, it works without any extra configuration.

Install it via a setup script when the sandbox is created:

```python
from islo.types.setup_script import SetupScript

install_mount_s3 = (
    "set -e && cd /tmp && "
    "curl -fsSL -O https://s3.amazonaws.com/mountpoint-s3-release/latest/x86_64/mount-s3.deb && "
    "sudo apt-get update -y && sudo apt-get install -y ./mount-s3.deb"
)

client.sandboxes.create_sandbox(
    name="my-sandbox",
    gateway_profile=gateway.id,
    setup_scripts=[SetupScript(name="install-mount-s3", script=install_mount_s3)],
)
```

Then mount the bucket once the sandbox is up:

```python
client.sandboxes.exec_in_sandbox(
    sandbox_name="my-sandbox",
    command=["bash", "-lc",
        "sudo mkdir -p /mnt/s3 && "
        "sudo mount-s3 my-bucket /mnt/s3 "
        "--region us-east-1 "
        "--allow-overwrite --allow-delete --allow-other "
        "--uid $(id -u islo) --gid $(id -g islo)"
    ],
)
```

`/mnt/s3` is now the bucket. The `--uid`/`--gid` flags map file ownership to the `islo` user, and `--allow-other` lets `islo` read/write through the root-owned mount.

## Troubleshooting

**`No signing credentials available` / no creds discovered** — the gateway isn't attached to the sandbox, or you're calling AWS too early (e.g. from a setup script, before the sandbox is fully up). Make the call after sandbox creation via `exec_in_sandbox`.

**`AccessDenied` from S3 / DynamoDB / etc.** — the IAM role's permissions policy doesn't grant the action you're attempting. Check CloudTrail in the target AWS account for the exact denied action.

**`AccessDenied` from STS during gateway provisioning** — Islo couldn't assume your role. Verify the trust policy: the `Principal` must match the Islo principal shown in the dashboard, and the `ExternalId` condition must match the value `create_cloud_role` returned.