> For the complete documentation index, see [llms.txt](https://docs.balkan.id/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.balkan.id/getting-started/setting-up-your-tenant/application-integrations/direct-application-integrations/aws-application-integration-setup.md).

# AWS Application Integration Setup

### Getting Started <a href="#getting-started" id="getting-started"></a>

There are two supported ways to grant BalkanID access to your account. Pick whichever fits your environment.

#### Requirements <a href="#h_01hq2keprp9cmqqvw4mb7gkdha" id="h_01hq2keprp9cmqqvw4mb7gkdha"></a>

**Option 1: Using an IAM Role**

* IAM Role ARN
* AWS Region
* External ID *(optional, but highly recommended; BalkanID generates this value, see below)*

**Option 2: Using an IAM User**

* Access Key ID
* Secret Access Key
* AWS Region
* A dedicated service account, rather than a personal or employee-named account, for creating this access key *(strongly recommended, see below)*

### Getting the Configuration

#### Option 1: Using an IAM Role <a href="#h_01hkr1hfm8mztsa1kvq5g8yzft" id="h_01hkr1hfm8mztsa1kvq5g8yzft"></a>

We use an IAM User called `balkan-service-user`, which assumes the IAM Role you provide, to connect to your AWS account.

1. Navigate to the AWS Web Console, Roles section.

2. Click **Create role**.

   <figure><img src="https://2975852473-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbVGYwk8aSk5yI1GDPEW9%2Fuploads%2FTGGRDEBuWxzYb5SIZKUT%2Fimage.png?alt=media&amp;token=7d8ca5dc-21d1-45a2-bd45-0fda6a276fb0" alt=""><figcaption></figcaption></figure>

3. Set **Trusted entity type** to **Custom trust policy** and paste the policy below. Leave the

   External ID condition off for now. You will add it after BalkanID generates a value. See [#protecting-your-role-with-an-external-id](#protecting-your-role-with-an-external-id "mention").<br>

   ```json
   {
       "Version": "2012-10-17",
       "Statement": [
           {
               "Sid": "AllowBalkanIDServiceUserAssumeRole",
               "Effect": "Allow",
               "Principal": {
                   "AWS": "arn:aws:iam::015482169847:user/balkan-service-user"
               },
               "Action": "sts:AssumeRole",
               "Condition": {
                   "StringEquals": {
                       "sts:ExternalId": "<paste-external-id-generated-by-balkanid>"
                   }
               }
           }
       ]
   }
   ```

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>Note:</strong> the Account ID above (<code>015482169847</code>) is our shared BalkanID service-user account, used for every customer on this trust policy. After you generate an External ID in BalkanID, add an <code>sts:ExternalId</code> condition so your role stays isolated from other tenants that share the same BalkanID principal.</p></div>

   <figure><img src="https://2975852473-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbVGYwk8aSk5yI1GDPEW9%2Fuploads%2Fb4PMFXPl16BR10oWSEK7%2Fimage.png?alt=media&amp;token=ee448d53-2d34-4a75-bffb-ea4364cd3126" alt=""><figcaption></figcaption></figure>

4. In the **Permissions policies** section, create a customer-managed policy using the JSON in

   [#least-privilege-permissions-policy](#least-privilege-permissions-policy "mention") below, and attach it to this role.<br>

   <figure><img src="https://2975852473-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbVGYwk8aSk5yI1GDPEW9%2Fuploads%2FS4DuJsiSuwdVfReuhXov%2Fimage.png?alt=media&amp;token=6d874b6d-500f-42b4-b54c-7f5aabaa8729" alt=""><figcaption></figcaption></figure>

   <figure><img src="https://2975852473-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbVGYwk8aSk5yI1GDPEW9%2Fuploads%2FlZRwc4AEzy0FukfdQrxh%2Fimage.png?alt=media&amp;token=774b5a86-1b0f-4ff2-881b-b5758b57c302" alt=""><figcaption></figcaption></figure>

5. In the next section, set the IAM Role Name and Description, then click **Create role**.

6. Once created, set **Maximum session duration** to **12 hours**.<br>

   <figure><img src="https://2975852473-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbVGYwk8aSk5yI1GDPEW9%2Fuploads%2F7BExqufkkfePvObNFlhA%2Fimage.png?alt=media&amp;token=f846adfb-0958-44fd-a7fd-aa17d6752619" alt=""><figcaption></figcaption></figure>

7. Copy the ARN from the role's **ARN** field (just above Maximum session duration).

8. Continue to [#h\_01hph1r4emybbss8cnq95442gv](#h_01hph1r4emybbss8cnq95442gv "mention") below.

#### **Protecting your role with an External ID**

An External ID is optional, but highly recommended. On our standard, shared environment, every customer's trust policy names the same `balkan-service-user` principal, so without an External ID the only thing distinguishing your role from any other customer's is the secrecy of your Role ARN. BalkanID mints a tenant-specific value and sends it on `sts:AssumeRole`. You cannot type or paste your own External ID.

1. Finish creating the role and save the integration in BalkanID with the Role ARN and Region

   (see [#h\_01hph1r4emybbss8cnq95442gv](#h_01hph1r4emybbss8cnq95442gv "mention")).

2. On the integration form, next to **External ID**, click **Generate**. BalkanID stores a value

   of the form `balkanid-<uuid>`.<br>

   <figure><img src="https://2975852473-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbVGYwk8aSk5yI1GDPEW9%2Fuploads%2F0O9YqHnA7I152c0KdmvG%2Fimage.png?alt=media&amp;token=9325cc15-b1e0-4936-9602-e9edbad2ff14" alt=""><figcaption></figcaption></figure>

3. Click the copy control on the field.<br>

   <figure><img src="https://2975852473-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbVGYwk8aSk5yI1GDPEW9%2Fuploads%2FF5uoR6F4JpoXMYLNLyJ7%2Fimage.png?alt=media&amp;token=6dbe64a3-c0d3-4912-bcf5-aba10e5b89e3" alt=""><figcaption></figcaption></figure>

4. In AWS, edit the role's **Trust relationships** policy and add the condition below, using the

   copied value. Then save the policy.

5. Sync the integration. If the trust-policy value does not match exactly, `sts:AssumeRole`

   fails with `AccessDenied`.

To replace an existing External ID, click **Rotate** in BalkanID, copy the new value, and update `sts:ExternalId` in the trust policy **before** the next sync. Rotating invalidates the previous value. Leaving External ID empty means BalkanID will not send one (Role ARN only).

If your organization requires isolation stronger than Role ARN + External ID, contact <support@balkan.id> to discuss your options.

#### Option 2: Getting the Access Key and Secret Access Key <a href="#h_01hkr1hfm8mztsa1kvq5g8yzft" id="h_01hkr1hfm8mztsa1kvq5g8yzft"></a>

1. Create a dedicated IAM user for this integration first (AWS Console, Users, Create user, e.g. `balkanid-identitycenter-integration`). Do not generate this access key under your own (or any other individual's) AWS Console user. A key tied to a named human user inherits that person's account lifecycle: if they leave, rotate their password, or lose console access, the integration can break unexpectedly or, worse, keep running on a credential nobody is actively tracking as a live secret. A dedicated service IAM user has a lifecycle you control independently of any individual's employment status.
2. In the **Permissions** step, choose **Attach policies directly**, then **Create policy** to

   open the policy editor in a new tab. Paste the JSON from [#least-privilege-permissions-policy](#least-privilege-permissions-policy "mention") below, name it (for example `BalkanIDLeastPrivilegePolicy`), and save it. Back in the user wizard, refresh the policy list and select it.
3. On this user, go to **Security credentials**, scroll to **Access Keys**.<br>

   <figure><img src="https://2975852473-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbVGYwk8aSk5yI1GDPEW9%2Fuploads%2FQ8UH48lk1HZbAyzjme5j%2Fimage.png?alt=media&amp;token=5cdd6e64-cf56-4b99-8b16-98ddf272b247" alt=""><figcaption></figcaption></figure>
4. Click **Create Access Key**, select **Third-party service** when prompted for a use case, and click **Next**.<br>

   <figure><img src="https://2975852473-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbVGYwk8aSk5yI1GDPEW9%2Fuploads%2F4DexkqD9lmLAdDWzUD4Q%2Fimage.png?alt=media&amp;token=876c88bb-a649-4217-9628-6ec56ff08218" alt=""><figcaption></figcaption></figure>
5. Provide a description and click **Create Access Key**. You'll be shown your credentials.

   <figure><img src="https://2975852473-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbVGYwk8aSk5yI1GDPEW9%2Fuploads%2FSsVtftSN3mVH639TLTai%2Fimage.png?alt=media&amp;token=db0508ca-aad7-44bb-ac1d-2000d8a24408" alt=""><figcaption></figcaption></figure>
6. Make a note of the **Access Key** and **Secret Access Key**. Your **Region** is the AWS Region your AWS Identity Center is configured in. Check the region selector next to your account name in the top-right of the console.<br>

   <figure><img src="https://2975852473-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbVGYwk8aSk5yI1GDPEW9%2Fuploads%2FdZXkDFV62gwy4COk1ZHY%2Fimage.png?alt=media&amp;token=9d1b6628-f048-4b57-b28b-4aad9a3bd165" alt=""><figcaption></figcaption></figure>

Do not generate an External ID on this path. External ID is an `sts:AssumeRole` trust-policy condition. Static access keys never call `AssumeRole`, and BalkanID rejects External ID together with access keys. If your organization can create cross-account IAM roles, prefer Option 1.

### Least-privilege permissions policy

This is the exact list of AWS API calls this extractor makes. Attach it as a customer-managed policy to the role or user you created above. Replace `<AWS_ACCOUNT_ID>` with your account ID.

The policy is split into a **Core** statement (always required) and one statement per **Selective Extraction** entity, so you can remove the statements for entities you don't plan to enable. See [#selective-extraction-permissions](#selective-extraction-permissions "mention") for the full mapping, or check this integration's **Data Sync Preferences** screen in your BalkanID tenant: the **Required API Scopes** panel there lists the exact IAM actions needed for whatever entities you've selected, and updates live as you check or uncheck them.

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "BalkanIDCoreReadOnly",
      "Effect": "Allow",
      "Action": [
        "iam:ListAccountAliases",
        "iam:ListUsers",
        "iam:GetLoginProfile",
        "iam:GenerateCredentialReport",
        "iam:GetCredentialReport"
      ],
      "Resource": "*"
    },
    {
      "Sid": "BalkanIDGroups",
      "Effect": "Allow",
      "Action": [
        "iam:ListGroups",
        "iam:ListGroupsForUser"
      ],
      "Resource": "*"
    },
    {
      "Sid": "BalkanIDGroupsScoped",
      "Effect": "Allow",
      "Action": [
        "iam:GetGroup",
        "iam:ListGroupPolicies",
        "iam:GetGroupPolicy",
        "iam:ListAttachedGroupPolicies"
      ],
      "Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:group/*"
    },
    {
      "Sid": "BalkanIDRoles",
      "Effect": "Allow",
      "Action": "iam:ListRoles",
      "Resource": "*"
    },
    {
      "Sid": "BalkanIDRolesScoped",
      "Effect": "Allow",
      "Action": [
        "iam:GetRole",
        "iam:ListRolePolicies",
        "iam:GetRolePolicy",
        "iam:ListAttachedRolePolicies"
      ],
      "Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/*"
    },
    {
      "Sid": "BalkanIDPolicies",
      "Effect": "Allow",
      "Action": [
        "iam:ListPolicies",
        "iam:ListUserPolicies",
        "iam:ListAttachedUserPolicies"
      ],
      "Resource": "*"
    },
    {
      "Sid": "BalkanIDPoliciesScoped",
      "Effect": "Allow",
      "Action": [
        "iam:GetPolicy",
        "iam:GetPolicyVersion",
        "iam:GetUserPolicy"
      ],
      "Resource": [
        "arn:aws:iam::<AWS_ACCOUNT_ID>:policy/*",
        "arn:aws:iam::<AWS_ACCOUNT_ID>:user/*"
      ]
    },
    {
      "Sid": "BalkanIDAWSManagedPolicies",
      "Effect": "Allow",
      "Action": [
        "iam:GetPolicy",
        "iam:GetPolicyVersion"
      ],
      "Resource": "arn:aws:iam::aws:policy/*"
    },
    {
      "Sid": "BalkanIDMFA",
      "Effect": "Allow",
      "Action": "iam:ListMFADevices",
      "Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:user/*"
    },
    {
      "Sid": "BalkanIDAccessKeys",
      "Effect": "Allow",
      "Action": [
        "iam:ListAccessKeys",
        "iam:GetAccessKeyLastUsed"
      ],
      "Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:user/*"
    },
    {
      "Sid": "BalkanIDInsights",
      "Effect": "Allow",
      "Action": "iam:SimulateCustomPolicy",
      "Resource": "*"
    }
  ]
}
```

> **Why some statements are** `Resource: "*"`**.** Account-wide or list-only actions (like `iam:ListUsers` and `iam:SimulateCustomPolicy`) don't support resource-level scoping. Everything else is scoped to `user/*`, `role/*`, `group/*`, or `policy/*` in your account, except `BalkanIDAWSManagedPolicies`, which scopes to `arn:aws:iam::aws:policy/*` since AWS-managed policies (e.g. `AmazonS3ReadOnlyAccess`) live under AWS's own account, not yours.

You can validate this policy against your account without attaching it to anything, using the IAM policy simulator:

```bash
aws iam simulate-custom-policy \
  --policy-input-list file://balkanid-extractor-policy.json \
  --action-names iam:ListUsers iam:GetLoginProfile iam:ListRoles iam:GetRole \
  --region us-east-1
```

### Lifecycle Management (provisioning) permissions

BalkanID's **Lifecycle Management** feature creates, deletes, and modifies AWS IAM users, groups, roles, and policies directly from BalkanID, for example offboarding a user by deleting their IAM user. It requires the **Direct Provisioning** fulfillment option enabled under Optional Configuration (see [#h\_01hph1r4emybbss8cnq95442gv](#h_01hph1r4emybbss8cnq95442gv "mention")), and the policy below attached in addition to the read-only Access Review policy above. Skip this section if you only use this integration for Access Review.

Attach a customer-managed policy with the exact write actions below, split into one statement per resource type so you can omit statements for actions you don't want to allow.

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "BalkanIDProvisioningUsers",
      "Effect": "Allow",
      "Action": [
        "iam:CreateUser",
        "iam:GetUser",
        "iam:DeleteUser",
        "iam:CreateLoginProfile",
        "iam:UpdateLoginProfile",
        "iam:DeleteLoginProfile",
        "iam:ListUserPolicies",
        "iam:DeleteUserPolicy",
        "iam:ListAttachedUserPolicies",
        "iam:AttachUserPolicy",
        "iam:DetachUserPolicy",
        "iam:ListGroupsForUser",
        "iam:AddUserToGroup",
        "iam:RemoveUserFromGroup",
        "iam:ListAccessKeys",
        "iam:DeleteAccessKey",
        "iam:ListMFADevices",
        "iam:DeactivateMFADevice",
        "iam:DeleteVirtualMFADevice",
        "iam:ListSigningCertificates",
        "iam:DeleteSigningCertificate",
        "iam:ListSSHPublicKeys",
        "iam:DeleteSSHPublicKey",
        "iam:ListServiceSpecificCredentials",
        "iam:DeleteServiceSpecificCredential"
      ],
      "Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:user/*"
    },
    {
      "Sid": "BalkanIDProvisioningGroups",
      "Effect": "Allow",
      "Action": [
        "iam:CreateGroup",
        "iam:DeleteGroup",
        "iam:GetGroup",
        "iam:ListGroupPolicies",
        "iam:DeleteGroupPolicy",
        "iam:ListAttachedGroupPolicies",
        "iam:AttachGroupPolicy",
        "iam:DetachGroupPolicy"
      ],
      "Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:group/*"
    },
    {
      "Sid": "BalkanIDProvisioningRoles",
      "Effect": "Allow",
      "Action": [
        "iam:CreateRole",
        "iam:DeleteRole",
        "iam:ListRolePolicies",
        "iam:DeleteRolePolicy",
        "iam:ListAttachedRolePolicies",
        "iam:AttachRolePolicy",
        "iam:DetachRolePolicy"
      ],
      "Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/*"
    },
    {
      "Sid": "BalkanIDProvisioningServiceLinkedRoles",
      "Effect": "Allow",
      "Action": [
        "iam:CreateServiceLinkedRole",
        "iam:DeleteServiceLinkedRole"
      ],
      "Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/aws-service-role/*"
    },
    {
      "Sid": "BalkanIDProvisioningServiceLinkedRoleDeletionStatus",
      "Effect": "Allow",
      "Action": "iam:GetServiceLinkedRoleDeletionStatus",
      "Resource": "*"
    },
    {
      "Sid": "BalkanIDProvisioningPolicies",
      "Effect": "Allow",
      "Action": [
        "iam:CreatePolicy",
        "iam:DeletePolicy"
      ],
      "Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:policy/*"
    }
  ]
}
```

> **Why** `iam:GetServiceLinkedRoleDeletionStatus` **needs** `Resource: "*"`**.** Deleting a service-linked role is asynchronous: AWS returns a deletion task ID, and this action polls that task by ID, not by role ARN. AWS does not support resource-level permissions for it.
>
> **Service-linked roles live under a fixed path.** AWS always creates them at `role/aws-service-role/<service>/<role-name>`, which is why their Create/Delete statement is scoped to that path instead of `role/*`.

#### Lifecycle Management action to IAM action mapping

| Lifecycle Management action                        | IAM actions called                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Create user (+ initial console password)           | `iam:CreateUser`, `iam:CreateLoginProfile`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| Reset user password                                | `iam:UpdateLoginProfile`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| Delete user                                        | `iam:GetUser`, `iam:ListAttachedUserPolicies`, `iam:DetachUserPolicy`, `iam:ListUserPolicies`, `iam:DeleteUserPolicy`, `iam:ListGroupsForUser`, `iam:RemoveUserFromGroup`, `iam:DeleteLoginProfile`, `iam:ListAccessKeys`, `iam:DeleteAccessKey`, `iam:ListMFADevices`, `iam:DeactivateMFADevice`, `iam:DeleteVirtualMFADevice`, `iam:ListSigningCertificates`, `iam:DeleteSigningCertificate`, `iam:ListSSHPublicKeys`, `iam:DeleteSSHPublicKey`, `iam:ListServiceSpecificCredentials`, `iam:DeleteServiceSpecificCredential`, `iam:DeleteUser` |
| Create group                                       | `iam:CreateGroup`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| Delete group                                       | `iam:ListAttachedGroupPolicies`, `iam:DetachGroupPolicy`, `iam:ListGroupPolicies`, `iam:DeleteGroupPolicy`, `iam:GetGroup`, `iam:RemoveUserFromGroup`, `iam:DeleteGroup`                                                                                                                                                                                                                                                                                                                                                                         |
| Add / remove user to or from a group               | `iam:AddUserToGroup` / `iam:RemoveUserFromGroup`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| Create role or AWS Service Role                    | `iam:CreateRole`, `iam:ListAttachedRolePolicies` (Service Role only, to record initial attachments)                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| Create AWS Service-Linked Role                     | `iam:CreateServiceLinkedRole`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| Delete role or AWS Service Role                    | `iam:ListAttachedRolePolicies`, `iam:DetachRolePolicy`, `iam:ListRolePolicies`, `iam:DeleteRolePolicy`, `iam:DeleteRole`                                                                                                                                                                                                                                                                                                                                                                                                                         |
| Delete AWS Service-Linked Role                     | `iam:DeleteServiceLinkedRole`, `iam:GetServiceLinkedRoleDeletionStatus`                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| Create policy                                      | `iam:CreatePolicy`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| Delete policy                                      | `iam:DeletePolicy`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| Attach / detach a policy to a user, group, or role | `iam:AttachUserPolicy` / `iam:DetachUserPolicy`, `iam:AttachGroupPolicy` / `iam:DetachGroupPolicy`, `iam:AttachRolePolicy` / `iam:DetachRolePolicy`                                                                                                                                                                                                                                                                                                                                                                                              |

**Not supported by this integration:** suspending or reactivating a user (AWS IAM has no concept of a suspended user; BalkanID falls back to deleting the user if you enable that option), updating an existing identity's attributes, and creating or deleting non-IAM resources.

### Optional, early-access permissions

The features below are **not enabled by default** and are rolled out to tenants on request. If you want one of these, contact your BalkanID account team and they'll turn it on for your tenant. Attaching the IAM permissions ahead of time doesn't activate the feature by itself, but is required once it's enabled so extraction doesn't fail with `AccessDenied`.

#### Bedrock Classic agents and AgentCore harnesses

{% hint style="info" %}
**Early Access:** [Agents](/agents/introduction-to-agents.md) discovery must be enabled for your tenant. For what BalkanID surfaces after sync, see [AWS: Agents](/agents/onboarding-agents/discovering-agents-from-integrations/aws-agents.md).
{% endhint %}

To discover Bedrock Classic agents and AgentCore harnesses (Non-Human Identity / Agents inventory), add:

```json
{
  "Sid": "BalkanIDBedrockAgents",
  "Effect": "Allow",
  "Action": [
    "bedrock:ListAgents",
    "bedrock:GetAgent",
    "bedrock-agentcore:ListHarnesses",
    "bedrock-agentcore:GetHarness"
  ],
  "Resource": "*"
}
```

If this isn't enabled for your tenant or you don't attach these permissions, extraction still succeeds. Agent discovery simply skips (logged, not fatal) and every other entity type continues to sync normally.

#### Access keys as first-class credential entities

Part of BalkanID's Non-Human Identity (NHI) capability. In addition to the **Access Keys** statement already in the core policy above, this requires the NHI feature to be enabled for your tenant by your BalkanID account team. Ask them if you want access keys modeled and risk-scored as standalone credential entities rather than just a user attribute.

#### IAM last-accessed data (Access Advisor)

To let BalkanID show when a user, role, group, or policy last accessed an AWS service, add:

```json
{
  "Sid": "BalkanIDLastAccessedScoped",
  "Effect": "Allow",
  "Action": [
    "iam:GenerateServiceLastAccessedDetails",
    "iam:ListPoliciesGrantingServiceAccess"
  ],
  "Resource": [
    "arn:aws:iam::<AWS_ACCOUNT_ID>:user/*",
    "arn:aws:iam::<AWS_ACCOUNT_ID>:role/*",
    "arn:aws:iam::<AWS_ACCOUNT_ID>:group/*",
    "arn:aws:iam::<AWS_ACCOUNT_ID>:policy/*"
  ]
},
{
  "Sid": "BalkanIDLastAccessedJob",
  "Effect": "Allow",
  "Action": [
    "iam:GetServiceLastAccessedDetails",
    "iam:GetServiceLastAccessedDetailsWithEntities"
  ],
  "Resource": "*"
}
```

This is the **AWS Access Advisor** API family, the same feature that powers the "Last accessed" tab in the IAM console, and **not CloudTrail**. `GetServiceLastAccessedDetails*` reads back a previously submitted job by ID rather than by resource, which is why AWS requires `Resource: "*"` for those two actions specifically; `GenerateServiceLastAccessedDetails` and `ListPoliciesGrantingServiceAccess` support the scoped ARNs above. Ask your BalkanID account team to enable "last access time" for your tenant if you want this populated.

#### Deeper cross-account role-chain resolution

```json
{
  "Sid": "BalkanIDRoleChainSimulation",
  "Effect": "Allow",
  "Action": "iam:SimulatePrincipalPolicy",
  "Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/*"
}
```

Used to compute the graph of roles that can be assumed from other roles in your account, so BalkanID can show effective, transitive access. It **only simulates** whether an `sts:AssumeRole` call would be allowed. It never actually calls `AssumeRole`, and no trust-policy changes are needed on the target roles. This ships enabled by default with unlimited chain depth; contact your BalkanID account team if you'd like the depth limited or this turned off entirely for your tenant.

If you don't attach this permission, extraction still succeeds; every user, group, and role logs an `AccessDenied` warning for this specific check (not fatal), and role-chain data simply stays empty. Every other entity type continues to sync normally.

### Selective Extraction permissions

BalkanID's **Selective Extraction** toggles (in the tenant integration form) control which entity types are synced, and each toggle maps directly to a subset of the core policy above. Disable a toggle and the corresponding actions are simply never called, so it's safe to remove the matching policy statement.

| Selective Extraction toggle                          | IAM actions required                                                                                                                                                               | Always on?                                                |
| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| Users                                                | `iam:ListUsers`, `iam:GetLoginProfile`, `iam:GenerateCredentialReport`, `iam:GetCredentialReport`, `iam:ListAccountAliases`                                                        | Yes, cannot be disabled                                   |
| Groups                                               | `iam:ListGroups`, `iam:ListGroupsForUser`, `iam:GetGroup`, `iam:ListGroupPolicies`, `iam:GetGroupPolicy`, `iam:ListAttachedGroupPolicies`, `iam:GetPolicy`, `iam:GetPolicyVersion` | No                                                        |
| Roles / AWS Service Linked Roles / AWS Service Roles | `iam:ListRoles`, `iam:GetRole`, `iam:ListRolePolicies`, `iam:GetRolePolicy`, `iam:ListAttachedRolePolicies`, `iam:GetPolicy`, `iam:GetPolicyVersion`                               | No                                                        |
| Policies                                             | `iam:ListPolicies`, `iam:GetPolicy`, `iam:GetPolicyVersion`, `iam:ListUserPolicies`, `iam:GetUserPolicy`, `iam:ListAttachedUserPolicies`                                           | No                                                        |
| Generic Resources                                    | *(none, derived from already-synced data, no additional API calls)*                                                                                                                | No                                                        |
| Insights                                             | `iam:SimulateCustomPolicy`                                                                                                                                                         | No                                                        |
| MFA Devices                                          | `iam:ListMFADevices`                                                                                                                                                               | No                                                        |
| Access Keys                                          | `iam:ListAccessKeys`, `iam:GetAccessKeyLastUsed`                                                                                                                                   | No, also requires the early-access NHI feature, see above |

Some actions appear under more than one toggle (e.g. `iam:GetPolicy` under both Groups and Roles) because BalkanID resolves attached-policy details as part of both entity types.

**Not required, despite being included in** `IAMReadOnlyAccess`**:** `iam:SimulatePrincipalPolicy` (only used, scoped, for the optional role-chain feature above, not for Insights), and any credential-report-adjacent SSH-key/signing-certificate actions or IAM account-summary/password-policy reads that aren't in the tables above. None of these are called by this extractor.

### Configure AWS in your BalkanID tenant <a href="#h_01hph1r4emybbss8cnq95442gv" id="h_01hph1r4emybbss8cnq95442gv"></a>

1. Login to the BalkanID application and switch to the tenant you would like to add your integration to.

2. Head to *Integrations* > **Add Integration**, select **Amazon Web Services.**

   <figure><img src="https://2975852473-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbVGYwk8aSk5yI1GDPEW9%2Fuploads%2FXRvzAfUdpqlc7iQZT5Na%2Fimage.png?alt=media&amp;token=43dd9897-4221-45f6-b341-f15fd50fa14a" alt=""><figcaption></figcaption></figure>

   <figure><img src="https://2975852473-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbVGYwk8aSk5yI1GDPEW9%2Fuploads%2FQrbOFg9pqGNIsbYaJIVv%2Fimage.png?alt=media&amp;token=5c587845-92e8-4d42-9b23-5d9b780f99ac" alt=""><figcaption></figcaption></figure>

3. Set up the *Primary Application owner (mandatory)* and the *Description*, if any. Set up Secondary Application Owner(s), if any.

4. Configure Selective Extraction toggles (see the table above).<br>

   <figure><img src="https://2975852473-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbVGYwk8aSk5yI1GDPEW9%2Fuploads%2FPh1gsi9exRUDJXeukdYF%2Fimage.png?alt=media&amp;token=8b06abc7-fcf4-4ee1-bbbe-777b68aab20e" alt=""><figcaption></figcaption></figure>

5. In the Direct Integration section provide your Role ARN **or** Access Key + Secret Access Key, and Region obtained above. After you save a Role ARN integration, click **Generate** on **External ID** (highly recommended), copy the value, and add it to the role's trust policy as described in [#protecting-your-role-with-an-external-id](#protecting-your-role-with-an-external-id "mention")<br>

   <figure><img src="https://2975852473-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbVGYwk8aSk5yI1GDPEW9%2Fuploads%2FNZhbyRe1NGZgtQOpJQVW%2Fimage.png?alt=media&amp;token=60c60efc-1131-4492-af12-eecdeed5b4ef" alt=""><figcaption></figcaption></figure>

6. Click on next to move onto *Optional Configuration.*

7. Fill **Optional configuration,** if required. (Turn on direct provisioning if you plan to use the lifecycle managment features).<br>

   <figure><img src="https://2975852473-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbVGYwk8aSk5yI1GDPEW9%2Fuploads%2FWwMwzBtDCwYSplMbZBtP%2Fimage.png?alt=media&amp;token=0d22f002-4d7b-4d31-84c0-31b50ca63edd" alt="" width="563"><figcaption></figcaption></figure>

8. Once you filled in the information, click **Save**. Your integration is now configured and you will see the status of the integration displayed alongside other integrations on the *Integrations* page. When data is available, the integration Status will read **Connected** and the integration Message will read **Data available**.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.balkan.id/getting-started/setting-up-your-tenant/application-integrations/direct-application-integrations/aws-application-integration-setup.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
