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

# AWS IAM (Single Account)

*This article applies to AWS connections created after July 2025 (the Domain ID under your Lumos domain shows* `aws-iam_ics`*). If your Domain ID shows* `aws.amazon.com`*, your connection uses the archived pre-July-2025 setup, and the main differences are noted inline below.*

## After this article

You will be able to connect an individual AWS account to Lumos to sync IAM users, groups, roles, and policies, and to provision users, group memberships, and role access, including deactivating and deleting IAM users during offboarding.

## Capabilities

| Functionality | Type | Sync | Provision | Description |
| :- | :- | :- | :- | :- |
| Users | Account | Yes | Yes | IAM user accounts |
| Groups | Permission | Yes | Yes | Groups in IAM |
| Roles | Permission | Yes | Yes | Roles in IAM |
| Policies | Permission | Yes | No | Policies attached to users, groups, or roles |

| Deprovisioning Action | Type | Description |
| :- | :- | :- |
| Deactivate | User | Deactivates the user by attaching a `DenyAllAccess` inline policy |
| Delete | User | Deletes the user and all associated Login Profiles, Access Keys, Signing Certificates, SSH Public Keys, Service Specific Credentials, MFA Devices, Virtual MFA Devices, Inline Policies, Attached Managed Policies, and User-to-Group Associations |

**Activity tracking:** Last Login uses the `PasswordLastUsed` field on the IAM user and reflects the most recent password-based login only (available for users with password-enabled accounts). This capability does not read CloudTrail events. Role access history monitoring uses CloudTrail read access.

## Required plan and roles

* **AWS permissions:** you need elevated AWS IAM permissions to create the cross-account role Lumos assumes.
* **Role permissions (managed policies):** attach `SecurityAudit` and `AWSCloudTrailReadOnlyAccess` to the role. CloudTrail read access powers last-activity and role access history monitoring.
  * Additionally attach this custom policy:

```json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowAccessToIdentityCenter",
      "Effect": "Allow",
      "Action": [
        "iam:ListUsers",
        "iam:GetUser",
        "iam:ListRoles",
        "iam:GetRole",
        "iam:ListGroups",
        "iam:ListGroupsForUser",
        "iam:SimulatePrincipalPolicy",
        "iam:ListPolicies",
        "iam:ListAttachedUserPolicies",
        "iam:ListAttachedRolePolicies",
        "iam:ListAttachedGroupPolicies",
        "iam:AttachUserPolicy",
        "iam:DetachUserPolicy",
        "iam:AddUserToGroup",
        "iam:RemoveUserFromGroup",
        "iam:PutUserPolicy",
        "iam:DeleteUserPolicy",
        "iam:CreateUser",
        "iam:CreateLoginProfile",
        "iam:DeleteUser",
        "iam:GetUserPolicy",
        "iam:GetLoginProfile",
        "iam:DeleteLoginProfile",
        "iam:ListAccessKeys",
        "iam:DeleteAccessKey",
        "iam:ListSigningCertificates",
        "iam:DeleteSigningCertificate",
        "iam:ListSSHPublicKeys",
        "iam:DeleteSSHPublicKey",
        "iam:ListServiceSpecificCredentials",
        "iam:DeleteServiceSpecificCredential",
        "iam:ListMFADevices",
        "iam:DeactivateMFADevice",
        "iam:ListVirtualMFADevices",
        "iam:DeleteVirtualMFADevice",
        "iam:ListUserPolicies",
        "sts:GetCallerIdentity",
        "cloudtrail:LookupEvents"
      ],
      "Resource": "*"
    },
    {
      "Sid": "AccessToSSOProvisionedRoles",
      "Effect": "Allow",
      "Action": [
        "iam:AttachRolePolicy",
        "iam:DeleteRolePolicy",
        "iam:DetachRolePolicy",
        "iam:ListAttachedRolePolicies",
        "iam:GetRole",
        "iam:CreateRole",
        "iam:DeleteRole",
        "iam:PutRolePolicy",
        "iam:UpdateRole",
        "iam:ListRolePolicies",
        "iam:UpdateRoleDescription"
      ],
      "Resource": "arn:aws:iam::*:role/aws-reserved/sso.amazonaws.com/*"
    },
    {
      "Sid": "AccessToSCIMProvider",
      "Effect": "Allow",
      "Action": ["iam:GetSAMLProvider"],
      "Resource": "arn:aws:iam::*:saml-provider/AWSSSO_*_DO_NOT_DELETE"
    }
  ]
}
```

* **Permission purposes:** the `List*` and `Get*` IAM actions and `SecurityAudit` power syncing users, groups, roles, and policies. The write IAM actions (`AttachUserPolicy`, `AddUserToGroup`, `CreateUser`, `Delete*`, `Deactivate*`, and so on) power provisioning, deactivation, and the full credential cleanup performed on user deletion. `cloudtrail:LookupEvents` plus `AWSCloudTrailReadOnlyAccess` power activity tracking. The SSO-scoped statements cover the AWS-reserved roles and SAML provider that Identity Center creates in the account.
* **Pre-July-2025 (Classic) connections:** the custom policy was a smaller deprovisioning-only policy (`iam:DeactivateMFADevice`, `iam:DeleteAccessKey`, `iam:RemoveUserFromGroup`, `iam:DeleteSigningCertificate`, `iam:DeleteVirtualMFADevice`, `iam:DeleteUserPolicy`, `iam:DeleteSSHPublicKey`, `iam:DeleteUser`, `iam:DetachUserPolicy`, `iam:DeleteServiceSpecificCredential`, `iam:DeleteLoginProfile` on Resource `*`) alongside the same two managed policies.

## Read-only access vs provisioning

**Is read-only possible?** Yes. Everything Lumos can do in your account is set by the policies you attach to the role it assumes, and the read and write halves of that permission set are separable. The `List*` and `Get*` IAM actions plus `SecurityAudit` power syncing users, groups, roles, and policies, while the write actions are what enable provisioning. By not providing write scopes, Lumos will be unable to modify access in AWS IAM.

**What read-only requires.** An IAM role with the `SecurityAudit` and `AWSCloudTrailReadOnlyAccess` managed policies attached, plus a reduced version of the custom policy above that keeps only its read actions: the `iam:List*` and `iam:Get*` actions, `iam:SimulatePrincipalPolicy`, `sts:GetCallerIdentity`, and `cloudtrail:LookupEvents`. Leave out the write actions and the `AccessToSSOProvisionedRoles` and `AccessToSCIMProvider` statements. Follow the role creation and trust relationship steps below, attaching the reduced policy in place of the full one.

**What full provisioning requires.** The same role with the complete custom policy above, which adds the write IAM actions (`AttachUserPolicy`, `AddUserToGroup`, `CreateUser`, the `Delete*` and `Deactivate*` actions, and the SSO-scoped role and SAML provider statements) that power provisioning, deactivation, and full credential cleanup on user deletion.

**Watch out for.** Read-only and provisioning use the same role and trust relationship, so switching modes later means editing the role's attached policies rather than reconnecting. Deleting a user requires the write actions and automatically cleans up that user's access keys, MFA devices, and other credentials. If the write policy is incomplete, deletions can fail with a `DeleteConflict` error.

## Instructions

**Phase 1: Create the IAM role in AWS**

You can create the role via the IAM Console (Option A) or Terraform (Option B).

**Option A: AWS Console**

1. In the IAM Console go to **Roles** → **Create Role** → **Another AWS account** and enter Account ID `349123981986`.
2. Enable **Require external ID** and enter a secure value of your choosing.
3. Attach the managed policies `SecurityAudit` and `AWSCloudTrailReadOnlyAccess`, plus the custom policy above.
4. Edit the trust relationship. On the **Name, review, and create** page, click **edit** next to Step 1, and change the value of the AWS key (within `Principal`) to `arn:aws:iam::349123981986:user/global-service-account`.
5. Create the role. The connector uses the default **1 hour** session duration. (Pre-July-2025 connections required **Max session duration** set to 12 hours / 43200s. The Terraform example still sets `max_session_duration = 43200`, which is harmless, and the connector uses 1 hour.)
6. Copy the **role ARN** and your **external ID**.

**Option B: Terraform**

```hcl theme={null}
data "aws_iam_policy" "SecurityAudit" {
  arn = "arn:aws:iam::aws:policy/SecurityAudit"
}

data "aws_iam_policy" "CloudTrailReadOnly" {
  arn = "arn:aws:iam::aws:policy/AWSCloudTrailReadOnlyAccess"
}

resource "aws_iam_policy" "DeprovisionIAMUser" {
  name = "DeprovisionIAMUser"
  policy = jsonencode({
    # Same three statements as the Option A custom policy above:
    # AllowAccessToIdentityCenter  (Resource "*")
    # AccessToSSOProvisionedRoles  (Resource "arn:aws:iam::*:role/aws-reserved/sso.amazonaws.com/*")
    # AccessToSCIMProvider         (iam:GetSAMLProvider, Resource "arn:aws:iam::*:saml-provider/AWSSSO_*_DO_NOT_DELETE")
  })
}

resource "aws_iam_role" "lumos_iam_role" {
  name = "LumosSingleAccountIntegrationRole"
  max_session_duration = 43200

  assume_role_policy = jsonencode({
    Version = "2012-10-17",
    Statement = [{
      Action = "sts:AssumeRole",
      Effect = "Allow",
      Principal = {
        AWS = "arn:aws:iam::349123981986:user/global-service-account"
      },
      Condition = {
        StringEquals = {
          "sts:ExternalId" = "CHOOSE_YOUR_EXTERNAL_ID"
        }
      }
    }]
  })
}

resource "aws_iam_role_policy_attachment" "attach_security_audit" {
  role       = aws_iam_role.lumos_iam_role.name
  policy_arn = data.aws_iam_policy.SecurityAudit.arn
}

resource "aws_iam_role_policy_attachment" "attach_cloudtrail" {
  role       = aws_iam_role.lumos_iam_role.name
  policy_arn = data.aws_iam_policy.CloudTrailReadOnly.arn
}

resource "aws_iam_role_policy_attachment" "attach_deprovision" {
  role       = aws_iam_role.lumos_iam_role.name
  policy_arn = aws_iam_policy.DeprovisionIAMUser.arn
}
```

**Phase 2: Connect in Lumos**

1. Find the AWS IAM (Single Account) card in your Lumos integrations (reconnect an existing card or add a new one).
2. Enter the **role ARN** and **external ID**.
3. Click **Connect**.

## API Endpoints Used

<Note>
  The API endpoints this integration uses are available to logged-in Lumos customers. [Log in](/login) to view them.
</Note>

## Troubleshooting

**Access Denied when assuming the role.** Verify the Service Role ARN is correct. Check the External ID matches the trust policy exactly (it is case-sensitive). Confirm the trust policy includes Lumos account `349123981986`, and verify the role exists.

**Insufficient permissions errors.** Verify `IAMFullAccess` is attached (or a custom policy with all required actions), and that `AWSCloudTrailReadOnlyAccess` is attached for activity tracking.

**DeleteConflict error when deleting a user.** This means the user has attached resources (access keys, MFA devices, and so on), and the integration automatically handles the cleanup.

**Activity tracking not working.** Enable CloudTrail, verify it is logging AssumeRole events, and ensure the service role has CloudTrail read permissions (`AWSCloudTrailReadOnlyAccess`).
