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

# AWS Integrations

> Connect 4MINDS to AWS services using IAM Role Federation or Amazon Cognito. One-time AWS setup that works across Amazon S3, SageMaker, Bedrock, and Lake Formation.

This guide covers the shared AWS setup for connecting 4MINDS to any AWS-based integration — **Amazon S3**, **Amazon SageMaker**, **Amazon Bedrock**, and **AWS Lake Formation**. The connection mechanics (IAM Role Federation or Amazon Cognito) are the same across all of them; only the IAM permissions policy changes per integration.

***

## Choosing a Connection Method

4MINDS supports two connection methods for AWS:

| Method                                | When to use                                                    | Security model                                                                      |
| ------------------------------------- | -------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| **IAM Role Federation** (recommended) | You want zero long-lived credentials stored in 4MINDS          | Temporary credentials minted on-demand via OIDC + AWS STS (1 hour lifetime)         |
| **Amazon Cognito**                    | Your organization already uses Cognito User Pools for identity | Authenticated Cognito identity assumes an IAM role with Bedrock/S3/etc. permissions |

> Some integrations support additional methods (e.g., Bedrock supports API keys). Those are documented in the integration-specific guides.

***

## AWS Setup (shared across all AWS integrations)

You only need to complete this setup **once per AWS account**, regardless of how many 4MINDS integrations (S3, SageMaker, Bedrock, Lake Formation) you plan to use. When adding a new integration later, you simply attach the appropriate permissions policy to the same IAM role or Cognito authenticated role.

### Step 1: Note Your AWS Region

1. Sign in to the [AWS Management Console](https://console.aws.amazon.com/)
2. The active region appears in the top-right of the AWS console (e.g., `us-east-1`). You'll need to enter this when connecting in 4MINDS
3. Common regions include `us-east-1`, `us-west-2`, `eu-west-1`, `eu-central-1`

### Step 2: Create the IAM Permissions Policy

The policy you attach depends on which 4MINDS integration you're setting up. Skip to the relevant section:

* [Amazon S3 policy](#amazon-s3)
* [Amazon SageMaker policy](#amazon-sagemaker)
* [Amazon Bedrock policy](#amazon-bedrock)
* [AWS Lake Formation policy](#aws-lake-formation)
* [Amazon RDS policy](/rds#rds-iam-permissions-policy)
* [Amazon Redshift policy](/redshift#redshift-iam-permissions-policy)

To create a policy:

1. Go to **AWS Console → IAM** (search for "IAM" in the top search bar)
2. Click **Policies** in the left sidebar
3. Click **Create policy**
4. Click the **JSON** tab (switch from the visual editor)
5. Paste the policy JSON for your integration (see sections below)
6. Click **Next**, name the policy (e.g., `4MINDS-S3-Access`), and click **Create policy**

Keep the policy name handy — you'll attach it in the connection method steps below. You can attach **multiple** 4MINDS policies to the same role if you're connecting to more than one AWS integration.

***

## Connection Method 1: IAM Role Federation (Recommended)

No long-lived credentials are stored. 4MINDS uses OIDC federation to mint short-lived credentials through AWS STS for each request.

### A. Register 4MINDS as an OIDC Identity Provider

1. Go to **AWS Console → IAM → Identity Providers** (left sidebar)
2. Click **Add Provider**
3. Select **OpenID Connect**
4. For **Provider URL**, enter: `https://api.4minds.ai`
5. For **Audience**, enter: `sts.amazonaws.com`
6. Click **Add provider**

You only need to do this once per AWS account.

### B. Create the IAM Role

1. Go to **IAM → Roles** → **Create role**
2. Under **Trusted entity type**, select **Web identity**
3. Under **Identity provider**, select `api.4minds.ai`
4. Under **Audience**, select `sts.amazonaws.com`
5. Click **Next**
6. Attach the permissions policy (or policies) you created in [Step 2](#step-2-create-the-iam-permissions-policy)
7. Click **Next**, enter a **Role name** (e.g., `4MINDS-integration-role`), and click **Create role**
8. **Copy the Role ARN** from the role summary page — it looks like: `arn:aws:iam::123456789012:role/4MINDS-integration-role`

### C. Verify the Trust Policy

1. Open the role you just created
2. Click the **Trust relationships** tab → **Edit trust policy**
3. Confirm it matches this (with your 12-digit AWS account ID):

```json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::<YOUR_ACCOUNT_ID>:oidc-provider/api.4minds.ai"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "api.4minds.ai:aud": "sts.amazonaws.com"
        }
      }
    }
  ]
}
```

> **Note — External ID is not supported for IAM Role Federation.** AWS STS `AssumeRoleWithWebIdentity` (the API this method uses) does not accept an External ID, so adding an `sts:ExternalId` condition to the trust policy will cause **every connection to fail with `AccessDenied`**. Leave the External ID field blank in 4MINDS for this method.
>
> For additional trust hardening, add a condition on a token claim instead. The JWT 4MINDS mints includes `sub` (e.g. `4minds:org:42:user:7`) and, when applicable, `org_id` and `tenant_id`. For example:
>
> ```json theme={null}
> "Condition": {
>   "StringEquals": {
>     "api.4minds.ai:aud": "sts.amazonaws.com",
>     "api.4minds.ai:sub": "4minds:org:42:user:7"
>   }
> }
> ```

### D. Connect in 4MINDS

1. In 4MINDS, open **Integrations** from the main navigation bar and select your integration (e.g., **Amazon S3**)
2. Select the **IAM Role** tab
3. Paste your **IAM Role ARN** (from step B.8)
4. Leave the **External ID** field blank — it is not supported for IAM Role Federation (see the note in [step C](#c-verify-the-trust-policy))
5. Enter your **AWS Region**
6. Fill in any integration-specific fields (see the [Per-Integration Policies & Fields](#per-integration-policies--fields) section)
7. Click **Test Connection**, then **Save Credentials**

***

## Connection Method 2: Amazon Cognito

Use this method if your organization manages AWS access through Amazon Cognito User Pools and Identity Pools.

> **Already have Cognito set up?** Skip to [Gather Your Cognito Details](#gather-your-cognito-details).

### A. Create a Cognito User Pool

1. Go to **AWS Console → Amazon Cognito**
2. Click **Create user pool**
3. Under **Sign-in experience**, check **User name** (and optionally **Email**)
4. Under **Security requirements**, configure your password policy and MFA (select **No MFA** for the simplest setup)
5. Under **Sign-up experience**, uncheck **Enable self-registration**
6. Under **Message delivery**, select **Send email with Cognito**
7. Under **Integrate your app**:
   * **User pool name**: `4MINDS-user-pool`
   * **App client name**: `4MINDS-app-client`
   * **Client secret**: optional — 4MINDS supports both
   * Under **Authentication flows**, ensure **ALLOW\_USER\_PASSWORD\_AUTH** is checked (required)
8. Click **Create user pool**
9. **Copy the User Pool ID** — looks like `us-east-1_aBcDeFgHi`

### B. Get the App Client Details

1. In your new User Pool, go to **App integration**
2. Scroll to **App clients and analytics** and open your app client
3. **Copy the Client ID** — looks like `1abc2def3ghi4jkl5mno6pqr`
4. If you generated a client secret, click **Show client secret** and copy it

### C. Create a User in the Pool

1. In your User Pool, go to **Users** → **Create user**
2. Enter a **User name** (e.g., `4MINDS-service-user`)
3. Enter a **Temporary password** or set a permanent one
4. Click **Create user**

If the user status shows `FORCE_CHANGE_PASSWORD`, complete the password change via AWS CLI before connecting in 4MINDS:

```bash theme={null}
aws cognito-idp admin-set-user-password \
  --user-pool-id us-east-1_aBcDeFgHi \
  --username 4MINDS-service-user \
  --password "YourPermanentPassword123!" \
  --permanent
```

### D. Create a Cognito Identity Pool

The Identity Pool maps authenticated Cognito users to an IAM role.

1. Go to **Amazon Cognito → Identity pools** → **Create identity pool**
2. Under **User access**, select **Authenticated access**
3. Under **Authenticated identity sources**, select **Amazon Cognito user pool**
4. Under **Configure permissions**, select **Create a new IAM role** and name it (e.g., `4MINDS-cognito-auth-role`)
5. Under **Connect identity providers**, enter the **User Pool ID** and **App Client ID** from steps A and B
6. Enter an **Identity pool name** (e.g., `4MINDS-identity-pool`)
7. Click **Create identity pool**
8. **Copy the Identity Pool ID** — looks like `us-east-1:12345678-abcd-1234-efgh-123456789012`

### E. Attach Permissions to the Cognito Authenticated Role

1. Go to **IAM → Roles** and open the role created in step D.4
2. Click **Add permissions → Attach policies**
3. Attach the permissions policy (or policies) you created in [Step 2](#step-2-create-the-iam-permissions-policy)

### Gather Your Cognito Details

| Field                 | Where to find it                       | Example                                          |
| --------------------- | -------------------------------------- | ------------------------------------------------ |
| **User Pool ID**      | Cognito → User Pools → Overview        | `us-east-1_aBcDeFgHi`                            |
| **App Client ID**     | Cognito → User Pools → App integration | `1abc2def3ghi4jkl5mno6pqr`                       |
| **App Client Secret** | Same as above (only if generated)      | `abcdef123456...`                                |
| **Identity Pool ID**  | Cognito → Identity Pools               | `us-east-1:12345678-abcd-1234-efgh-123456789012` |
| **Username**          | Cognito user created in step C         | `4MINDS-service-user`                            |
| **Password**          | Permanent password for that user       | —                                                |

### Connect in 4MINDS

1. Open **Integrations** from the main navigation bar and select your integration
2. Select the **Cognito** tab
3. Fill in all fields from the table above
4. If your app client has a secret, toggle on **App Client Secret** and enter it
5. Enter your **AWS Region** (must match the region of your User Pool and Identity Pool)
6. Fill in any integration-specific fields (see below)
7. Click **Test Connection**, then **Save Credentials**

***

## Per-Integration Policies & Fields

Paste the JSON below into the **JSON** tab when creating a policy in [Step 2](#step-2-create-the-iam-permissions-policy). You can attach multiple policies to the same IAM role or Cognito authenticated role.

### Amazon S3

Connect to Amazon S3 to import datasets and files directly from your S3 buckets.

#### Policy — Broad Access (list all buckets in the account)

```json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ListAllBuckets",
      "Effect": "Allow",
      "Action": "s3:ListAllMyBuckets",
      "Resource": "*"
    },
    {
      "Sid": "ReadBuckets",
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket",
        "s3:GetObject"
      ],
      "Resource": [
        "arn:aws:s3:::*",
        "arn:aws:s3:::*/*"
      ]
    }
  ]
}
```

#### Policy — Least Privilege (restrict to specific buckets)

If you configure **Allowed Buckets** in 4MINDS, you can drop `s3:ListAllMyBuckets` entirely and scope access to just the buckets you expose:

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

| Permission            | Purpose                                                               |
| --------------------- | --------------------------------------------------------------------- |
| `s3:ListAllMyBuckets` | Enumerates all buckets in the account (skip if using Allowed Buckets) |
| `s3:ListBucket`       | Lists objects within a bucket                                         |
| `s3:GetObject`        | Downloads file contents during import                                 |

#### Restricting Access with Allowed Buckets

By default, when 4MINDS opens the S3 browser it calls `s3:ListAllMyBuckets` and shows every bucket in your account. If you'd rather expose only a specific set of buckets — for compliance, tenancy isolation, or just to keep the picker tidy — use the **Allowed Buckets** field.

**How it works:**

* With **Allowed Buckets empty**, 4MINDS lists every bucket the role can see. The IAM policy needs `s3:ListAllMyBuckets`.
* With **Allowed Buckets populated**, 4MINDS never calls `ListAllMyBuckets` — it only probes the buckets you named via `s3:ListBucket`. The IAM policy can drop `ListAllMyBuckets` entirely and scope `s3:ListBucket`/`s3:GetObject` to just those bucket ARNs (see [Policy — Least Privilege](#policy--least-privilege-restrict-to-specific-buckets) above).

**Adding buckets in 4MINDS:**

1. Open **Integrations** → **Amazon S3**
2. Scroll to the **Allowed buckets (optional)** section
3. Click **Add bucket** — a new text input row appears
4. Type the **exact bucket name** (e.g., `prod-datasets`), not the ARN and not a path
5. Click **Add bucket** again to add another row; the button is disabled until the current row has a value
6. To remove a bucket, click the trash icon next to its row
7. Click **Test Connection** to verify the role can `head_bucket` on each name, then **Save Credentials**

**Behavior during connection test:**

* Each allowed bucket is probed with `HeadBucket`. If any one fails, the error message names the specific bucket (e.g., *"Access denied on bucket 'prod-datasets'"*) so you can fix a typo or missing grant without hunting.
* Buckets in other regions are reachable but slower — S3 follows a redirect. For best performance, keep all allowed buckets in the region you specified.

**When to use it:**

* **Multi-tenant AWS accounts** where only a subset of buckets contain data you want in 4MINDS
* **Least-privilege IAM setups** where you want to drop `s3:ListAllMyBuckets` and scope `Resource` to specific ARNs
* **Cleaner UX** when your account has hundreds of buckets and users only care about a handful

**When to leave it empty:**

* You want 4MINDS to auto-discover new buckets as they're created without updating the integration
* You already restrict buckets via IAM — in that case, `ListAllMyBuckets` simply returns the subset the role can see

#### 4MINDS Fields

| Field               | Required | Notes                                                          |
| ------------------- | -------- | -------------------------------------------------------------- |
| **AWS Region**      | Yes      | Region where your buckets live                                 |
| **Default Bucket**  | No       | Pre-selected bucket in the browser UI                          |
| **Allowed Buckets** | No       | Restrict which buckets 4MINDS can see. Leave empty to list all |

***

### Amazon SageMaker

Connect to Amazon SageMaker to create 4MINDS models backed by your deployed SageMaker endpoints.

#### Policy

```json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "SageMakerDiscovery",
      "Effect": "Allow",
      "Action": [
        "sagemaker:ListEndpoints",
        "sagemaker:ListModels",
        "sagemaker:ListTrainingJobs",
        "sagemaker:DescribeEndpoint",
        "sagemaker:DescribeEndpointConfig",
        "sagemaker:DescribeModel"
      ],
      "Resource": "*"
    },
    {
      "Sid": "SageMakerInvoke",
      "Effect": "Allow",
      "Action": "sagemaker:InvokeEndpoint",
      "Resource": "arn:aws:sagemaker:*:*:endpoint/*"
    },
    {
      "Sid": "IdentityVerification",
      "Effect": "Allow",
      "Action": "sts:GetCallerIdentity",
      "Resource": "*"
    }
  ]
}
```

| Permission                                                                | Purpose                                                 |
| ------------------------------------------------------------------------- | ------------------------------------------------------- |
| `sagemaker:ListEndpoints`                                                 | Discovers deployed inference endpoints                  |
| `sagemaker:ListModels`                                                    | Lists registered SageMaker models                       |
| `sagemaker:ListTrainingJobs`                                              | Lists training jobs (used for model lineage)            |
| `sagemaker:DescribeEndpoint` / `DescribeEndpointConfig` / `DescribeModel` | Retrieves endpoint and model metadata                   |
| `sagemaker:InvokeEndpoint`                                                | Sends prompts to a SageMaker endpoint at inference time |
| `sts:GetCallerIdentity`                                                   | Verifies the connection                                 |

> **Least privilege:** Restrict `sagemaker:InvokeEndpoint` to specific endpoint ARNs if you only want 4MINDS to call certain endpoints. Replace the resource with e.g. `arn:aws:sagemaker:us-east-1:123456789012:endpoint/my-endpoint`.

#### 4MINDS Fields

| Field          | Required | Notes                                    |
| -------------- | -------- | ---------------------------------------- |
| **AWS Region** | Yes      | Region where your endpoints are deployed |

***

### Amazon Bedrock

Connect to Amazon Bedrock to use foundation models as 4MINDS models.

#### Policy

```json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "BedrockFoundationModelAccess",
      "Effect": "Allow",
      "Action": [
        "bedrock:ListFoundationModels",
        "bedrock:GetFoundationModel",
        "bedrock:InvokeModel",
        "bedrock:InvokeModelWithResponseStream"
      ],
      "Resource": "*"
    },
    {
      "Sid": "BedrockCustomModelAccess",
      "Effect": "Allow",
      "Action": [
        "bedrock:ListCustomModels",
        "bedrock:GetCustomModel"
      ],
      "Resource": "*"
    },
    {
      "Sid": "IdentityVerification",
      "Effect": "Allow",
      "Action": "sts:GetCallerIdentity",
      "Resource": "*"
    }
  ]
}
```

| Permission                                              | Purpose                                       |
| ------------------------------------------------------- | --------------------------------------------- |
| `bedrock:ListFoundationModels` / `GetFoundationModel`   | Discovers available foundation models         |
| `bedrock:ListCustomModels` / `GetCustomModel`           | Discovers fine-tuned custom models (optional) |
| `bedrock:InvokeModel` / `InvokeModelWithResponseStream` | Runs inference at request time                |
| `sts:GetCallerIdentity`                                 | Verifies the connection                       |

> **Least privilege:** Scope `bedrock:InvokeModel` to specific model ARNs. See the [Bedrock guide](/bedrock#least-privilege-restricting-to-specific-models) for examples.

> **Alternative: API Key.** Bedrock also supports authentication via an API key generated in the Bedrock console — no IAM setup needed. See the [Bedrock guide](/bedrock) for details.

#### 4MINDS Fields

| Field          | Required | Notes                           |
| -------------- | -------- | ------------------------------- |
| **AWS Region** | Yes      | Region where Bedrock is enabled |

***

### AWS Lake Formation

Connect to Lake Formation to query governed tables via AWS Glue and Athena.

#### Policy

```json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "GlueCatalogRead",
      "Effect": "Allow",
      "Action": [
        "glue:GetDatabase",
        "glue:GetDatabases",
        "glue:GetTable",
        "glue:GetTables"
      ],
      "Resource": "*"
    },
    {
      "Sid": "AthenaQuery",
      "Effect": "Allow",
      "Action": [
        "athena:StartQueryExecution",
        "athena:GetQueryExecution",
        "athena:GetQueryResults"
      ],
      "Resource": "*"
    },
    {
      "Sid": "AthenaResultsBucket",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::<your-athena-results-bucket>",
        "arn:aws:s3:::<your-athena-results-bucket>/*"
      ]
    },
    {
      "Sid": "IdentityVerification",
      "Effect": "Allow",
      "Action": "sts:GetCallerIdentity",
      "Resource": "*"
    }
  ]
}
```

Replace `<your-athena-results-bucket>` with the S3 bucket configured as the Athena query results location (Athena → Settings → Query result location).

| Permission                                                             | Purpose                                                 |
| ---------------------------------------------------------------------- | ------------------------------------------------------- |
| `glue:GetDatabase` / `GetDatabases` / `GetTable` / `GetTables`         | Browses the Glue Data Catalog that backs Lake Formation |
| `athena:StartQueryExecution` / `GetQueryExecution` / `GetQueryResults` | Runs SELECT queries against governed tables             |
| `s3:GetObject` / `PutObject` / `ListBucket` on the results bucket      | Reads Athena query results written to S3                |
| `sts:GetCallerIdentity`                                                | Verifies the connection                                 |

> **Lake Formation grants:** The IAM policy above allows the **API calls**. You must also grant the role `SELECT` access on the specific databases/tables in the **Lake Formation → Data permissions** console. Without Lake Formation grants, Athena queries will return no rows.

#### 4MINDS Fields

| Field                       | Required | Notes                                                                               |
| --------------------------- | -------- | ----------------------------------------------------------------------------------- |
| **AWS Region**              | Yes      | Region of the Glue Catalog / Lake Formation                                         |
| **Athena Workgroup**        | No       | Workgroup used for queries (defaults to `primary`)                                  |
| **Athena Results Location** | Yes      | `s3://your-athena-results-bucket/path/` — must match the bucket in the policy above |

***

## Testing Your Connection

After saving credentials in 4MINDS:

1. Click **Test Connection** — validates credentials and permissions
2. Success messages vary by integration (e.g., *"Found 12 bucket(s)"* for S3, *"Found 8 foundation model(s)"* for Bedrock)
3. Click **Save Credentials** to persist

***

## Troubleshooting

| Issue                                                    | Solution                                                                                                                                                                                      |
| -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `AccessDenied` on connection test                        | The IAM policy isn't attached to the role, or the policy is missing a required action                                                                                                         |
| `AccessDenied` on a specific bucket (S3)                 | The bucket is in Allowed Buckets but the policy doesn't include it in its `Resource` — add the bucket ARN or remove it from Allowed Buckets                                                   |
| `NoSuchBucket`                                           | The bucket name in Allowed Buckets is a typo or lives in a different region                                                                                                                   |
| `Unrecognized client`                                    | Wrong AWS region, or the service isn't enabled in that region                                                                                                                                 |
| Role federation fails                                    | Verify the OIDC provider URL is exactly `https://api.4minds.ai` with audience `sts.amazonaws.com`                                                                                             |
| Role federation: `AccessDenied` despite correct provider | Remove any `sts:ExternalId` condition from the trust policy — it is not supported by `AssumeRoleWithWebIdentity` and blocks every connection. Use a `sub`/`tenant_id` claim condition instead |
| Cognito: `FORCE_CHANGE_PASSWORD`                         | Complete the password change via AWS CLI (see [step C](#c-create-a-user-in-the-pool))                                                                                                         |
| Cognito: `NotAuthorizedException`                        | Username or password is wrong, or the app client doesn't have `ALLOW_USER_PASSWORD_AUTH` enabled                                                                                              |
| Lake Formation: queries return no rows                   | Grant the role `SELECT` in **Lake Formation → Data permissions** on the target databases/tables                                                                                               |

***

## Disconnecting

To remove a 4MINDS integration connection:

1. Open **Integrations**, select the integration
2. Click **Disconnect**

This removes stored credentials from 4MINDS. Your AWS resources (IAM roles, OIDC providers, Cognito pools, policies) are not affected — delete them in the AWS Console if no longer needed.
