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

# Cloud Storage Aws S3 Customer Owned

> Estimated setup time: 1 hour

Use this guide when your organization owns and manages the S3 bucket. Aampe will read event data from your bucket using one of several authentication methods.

***

## Getting Started

### Step 1: Create Your Bucket

Create an S3 bucket in your AWS account. Share the following with Aampe:

* **Bucket name** (e.g., `acme-events-bucket`)
* **Region** (e.g., `us-east-1`)

### Step 2: Choose an Authentication Method

Aampe supports three methods for accessing your bucket. Choose the one that best fits your security requirements:

| Method                                                                 | Security Level | Best For                                                  |
| ---------------------------------------------------------------------- | -------------- | --------------------------------------------------------- |
| [Cross-Account IAM Role](#option-a-cross-account-iam-role-recommended) | Highest        | Production environments, enterprise security requirements |
| [IAM User Access Keys](#option-b-iam-user-access-keys)                 | Moderate       | Simple setups, quick proofs of concept                    |

***

## Option A: Cross-Account IAM Role (Recommended)

This is the AWS-recommended approach for third-party access. It uses temporary credentials and includes an External ID to prevent the [confused deputy problem](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html).

### How It Works

1. You create an IAM role in your AWS account
2. The role trusts Aampe's AWS account to assume it
3. Aampe assumes the role using temporary credentials
4. An External ID ensures only Aampe can assume the role on your behalf

### Setup Instructions

#### 1. Request Credentials from Aampe

Contact Aampe to receive:

* **Aampe AWS Account ID**
* **External ID** (unique to your organization)

> **Important:** The External ID is generated by Aampe and should not be shared or changed. This prevents other parties from assuming your role through Aampe.

#### 2. Create an IAM Policy

Create an IAM policy with read permissions for your bucket. Name it something like `AampeS3ReadAccess`.

```json theme={null}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Resource": [
                "arn:aws:s3:::<YOUR_BUCKET_NAME>",
                "arn:aws:s3:::<YOUR_BUCKET_NAME>/*"
            ]
        }
    ]
}
```

Replace `<YOUR_BUCKET_NAME>` with your actual bucket name.

#### 3. Create an IAM Role with Cross-Account Trust

Create a new IAM role with the following trust policy:

```json theme={null}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<AAMPE_AWS_ACCOUNT_ID>:root"
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                    "sts:ExternalId": "<EXTERNAL_ID_PROVIDED_BY_AAMPE>"
                }
            }
        }
    ]
}
```

Replace:

* `<AAMPE_AWS_ACCOUNT_ID>` with the Account ID provided by Aampe
* `<EXTERNAL_ID_PROVIDED_BY_AAMPE>` with the External ID provided by Aampe

Name this role something like `AampeS3AccessRole`.

#### 4. Attach the Policy to the Role

Attach the `AampeS3ReadAccess` policy (from step 2) to the `AampeS3AccessRole` (from step 3).

#### 5. Share the Role ARN with Aampe

Provide Aampe with the full role ARN:

```
arn:aws:iam::<YOUR_AWS_ACCOUNT_ID>:role/AampeS3AccessRole
```

### AWS Documentation

* [IAM Tutorial: Delegate access across AWS accounts using IAM roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html)
* [How to use External ID when granting access to third parties](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_third-party.html)

***

## Option B: IAM User Access Keys

This simpler approach grants an Aampe-managed IAM user direct access to your bucket via a bucket policy.

> **Note:** While easier to set up, this method uses long-lived credentials. AWS recommends using IAM roles (Option A) when possible. See [Security best practices in IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html).

### How It Works

1. You create a bucket policy that grants access to an Aampe IAM user
2. Aampe provides the IAM user ARN to include in your policy
3. Aampe accesses your bucket using access keys for that user

### Setup Instructions

#### 1. Request the Aampe User ARN

Contact Aampe to receive the IAM user ARN that will access your bucket.

#### 2. Add a Bucket Policy

Apply the following bucket policy to grant Aampe read access:

```json theme={null}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AampeReadAccess",
            "Effect": "Allow",
            "Principal": {
                "AWS": "<AAMPE_USER_ARN>"
            },
            "Action": [
                "s3:GetObject",
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Resource": [
                "arn:aws:s3:::<YOUR_BUCKET_NAME>",
                "arn:aws:s3:::<YOUR_BUCKET_NAME>/*"
            ]
        }
    ]
}
```

Replace:

* `<AAMPE_USER_ARN>` with the ARN provided by Aampe
* `<YOUR_BUCKET_NAME>` with your bucket name

### AWS Documentation

* [Bucket policies for Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-policies.html)
* [Actions, resources, and condition keys for Amazon S3](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazons3.html)

***

## Step 3: Upload Your Data

Upload event data to your bucket in one of these formats:

* JSON or Newline Delimited JSON (ndJSON) - *Preferred*
* CSV
* Parquet

### File Naming Convention

Use a consistent naming pattern:

* **Daily files:** `events_YYYYMMDD.json` (e.g., `events_20240115.json`)
* **With partitions:** `/year=2024/month=01/day=15/events_20240115.json`

### Data Format

Your event data should follow the [Aampe Data Model](/developer-guide/data-ingest/data-model).

***

## Verification

Once configured, the Aampe team will confirm that we are successfully receiving your data.

***

## Troubleshooting

### Access Denied Errors

* Verify the bucket name in your policy matches exactly (case-sensitive)
* Ensure both bucket-level (`arn:aws:s3:::bucket`) and object-level (`arn:aws:s3:::bucket/*`) resources are included
* Check that the IAM role/user ARN matches what Aampe provided

### Role Cannot Be Assumed

* Verify the External ID matches exactly (for Option A)
* Check that the trust policy Principal matches Aampe's account/user
* Ensure the role has the policy attached (not just created)

***

<Info>
  If these options conflict with your IT policies or you need an alternative approach, contact us at [support@aampe.com](mailto:support@aampe.com). We are happy to work with your security team to find a solution.
</Info>

***

## Related Resources

* [Aampe Data Model](/developer-guide/data-ingest/data-model)
* [AWS S3: Aampe-Owned Bucket](/developer-guide/data-ingest/data-sources/cloud-storage-aws-s3-aampe-owned)
