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

# Custom IAM role to access S3

export const Comments = ({children}) => {
  return <div class="my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border border-zinc-500/20 bg-zinc-50/50 dark:border-zinc-500/30 dark:bg-zinc-500/10" data-callout-type="comments">
      <div class="w-4">
        <svg width="14" height="14" viewBox="0 0 640 640" fill="currentColor" xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" aria-label="Comments">
            <path d="M320 112C434.9 112 528 205.1 528 320C528 434.9 434.9 528 320 528C205.1 528 112 434.9 112 320C112 205.1 205.1 112 320 112zM320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM280 400C266.7 400 256 410.7 256 424C256 437.3 266.7 448 280 448L360 448C373.3 448 384 437.3 384 424C384 410.7 373.3 400 360 400L352 400L352 312C352 298.7 341.3 288 328 288L280 288C266.7 288 256 298.7 256 312C256 325.3 266.7 336 280 336L304 336L304 400L280 400zM320 256C337.7 256 352 241.7 352 224C352 206.3 337.7 192 320 192C302.3 192 288 206.3 288 224C288 241.7 302.3 256 320 256z" />
        </svg>
      </div>
      <div class="text-sm prose min-w-0 w-full">
        {children}
      </div>
    </div>;
};

<Note>
  This guide assumes you have read [Connect and run your first flow](/docs/platform/getting-started/connect-and-first-run).
</Note>

Your tasks might need data in S3 buckets that the default task execution role cannot access. For example, the bucket might reside in a different AWS account than the one where your deployment runs. In this scenario, grant tasks access to the bucket with a custom IAM role.

## Creating the integration

<Badge shape="pill" stroke color="blue">Admin only</Badge>

You must be an administrator of the deployment to create integrations. To create an Amazon S3 integration:

1. Select **Integrations** in the left-hand navigation.

2. Click the **Amazon S3** card.

3. Enter a **Name** and **Description** for the integration.

4. Under **Enter the name of the S3 Bucket**, enter the bucket name. To limit access to a path within the bucket, enter a prefix under **Enter the bucket prefix you would like to provision access to**.

5. Under **What type of access would you like to provision**, select the access level your tasks need: *Read Only*, *Write Only*, or *Read and Write*.

6. Expand **Getting your IAM role ARN?** and follow the instructions to create an IAM role in the account that hosts the bucket. The form provides:

   * A trust policy that allows the task execution role to assume the role, with the task execution role's ARN pre-filled as the principal.
   * The tag key `outerbounds.com/accessible-by-deployment` and value to attach to the role. The tag allows the platform to discover the role.
   * An inline IAM policy scoped to your bucket, prefix, and access level. Attach the policy to the role in the AWS Console.

7. Under **IAM Role ARN**, enter the ARN of the role you created.

8. Click **Add**.

<Frame>
  <img src="https://mintcdn.com/anaconda-29683c67/VD0yQ0tXYWIdTsBU/images/platform/plat_integrations_s3_iam_role.png?fit=max&auto=format&n=VD0yQ0tXYWIdTsBU&q=85&s=3b8ea0cbb7cb8497e7c7930ccb7b8c3f" alt="The Amazon S3 integration form showing Name, Description, S3 bucket, and IAM Role ARN fields" width="1866" height="1082" data-path="images/platform/plat_integrations_s3_iam_role.png" />
</Frame>

## Using the role

Pass the role ARN to the `role` parameter of the [`metaflow.S3` client](https://docs.metaflow.org/api/S3) to access the bucket in your flows:

```python expandable theme={null}
from metaflow import FlowSpec, step, S3

class CustomS3AccessFlow(FlowSpec):
    @step
    def start(self):
        import pandas as pd

        # Read data from an S3 bucket in another account
        with S3(role="<ROLE_ARN>") as s3:
            tmp_data_path = s3.get("s3://<BUCKET_NAME>/<OBJECT_KEY>")
            df = pd.read_csv(tmp_data_path.path)
            self.summary = df.describe()

        self.next(self.end)

    @step
    def end(self):
        print(self.summary)

if __name__ == "__main__":
    CustomS3AccessFlow()
```

<Comments>
  Replace \<ROLE\_ARN> with the ARN of the IAM role you created for the integration.<br />
  Replace \<BUCKET\_NAME> with the name of your S3 bucket.<br />
  Replace \<OBJECT\_KEY> with the key of the object to read.
</Comments>

The **How to use** tab of the integration shows a ready-to-use snippet with the role ARN pre-filled. You can also use the same role ARN with `get_aws_client` for direct S3 access, as described in [Configuring secrets](/docs/platform/guides/security/configuring-secrets#using-a-custom-iam-role).
