# Amazon Web Services - Inventory Integration

Amazon Web Services (AWS) is a comprehensive cloud computing platform provided by Amazon. It offers a broad set of on-demand services including compute, storage, databases, networking, and analytics. AWS enables organizations to build, deploy, and operate applications without managing physical infrastructure.

### Details

In order to integrate Relyance AI with AWS for Asset Inventory and AI Discovery, there are two approaches:

1. Individual Account Integration ( Direct Connection)
2. Organization-Wide Integration ( Organization Scan)

#### Individual Account Integration (Direct Connection)

For this approach, you will need the following:

1. **Role ARN** - ARN of the role you create in AWS with required permissions to
2. **External ID** - External ID you specify in AWS IAM Role creation to secure the connection
3. **Region** - Region for which resource explorer setting is set to Aggregator

Note: In AWS Resource Explorer settings, you can set only one region index as an Aggregator. We recommend setting the default region for the account as the Aggregator.

Role assumption in AWS allows entities (like IAM users, services, or even external identities) to take on an IAM role, granting them temporary permissions to perform specific actions on specific resources without having to attach permissions directly to their identity.

By assuming a role, one gets temporary security credentials to act with the permissions of the role, ensuring a flexible and secure way to delegate and segregate duties without distributing long-lived credentials.

There are two necessary preconditions that must be met for a principal (the Relyance AI System, in this case) to assume a role.

1. The entity needs to have permission to use the `sts:AssumeRole` action for the specific role they want to assume.
2. The role must have a trust policy that allows the principal to use it.

#### Organization-Wide Integration (Organization Scan)

And, for the **Organization Scan** (recommended) approach, you will need the following:

1. External ID

- External ID you specify in AWS IAM Role creation to secure the connection
2. **Organization Reader Role ARN** - A role in the management account for organization actions.
3. Delegated Resource Explorer View ARN

- A resource explorer view ARN in the delegated account.
4. Delegated Resource Explorer Reader Role ARN

- A role in the delegated account for querying the resource explorer view.
5. **Assumable Account Reader Role Name** - A role name that will be the role deployed across all the accounts.
6. **Organization Configuration** - which accounts and organizational units are in scope. `*` means everything:

    ```json
    {
      "allowed_aws_account_ids": ["*"],
      "allowed_organization_units": ["*"]
    }
    ```

    Narrow this when only part of the organization should be scanned — it is applied before any account is contacted, so excluded accounts are never touched.

In order to connect to AWS Organization for inventory integration, you will need,

1. **Management Account (The Map)** A OrgReaderRole created in the management account. All the permissions required for this role are listed in the **Configuring AWS via Direct Connect Approach** section, and you can also leverage the CloudFormation template available in the same section.
    - This is to understand the layout of AWS Organizations, listing accounts and OUs, and identify the Delegated Admin.
    - Resource Explorer must have an Aggregator Index enabled here so the Management account’s own resources are visible to the Global View.
2. **Delegated Administrator (DA) Account (The Hub)** A DiscoveryRole created in the DA account to act as the entrypoint for Relyance scanner to query Global Resource Explorer in Management Account. All the permissions required for this role are listed in the Configuring AWS via Direct Connect Approach section, and you can also leverage the CloudFormation template available in the same section. This account must be the **Delegated Administrator** for Resource Explorer with an **Organization-wide View** created.
3. **All Member Accounts** A **GlobalScannerRole** to be created in each member account to discover the resources present in each account. All the permissions required for this role are listed in the Configuring AWS via Direct Connect Approach section, and you can also leverage the CloudFormation template available in the same section. Every account/region must have a **Local Resource Explorer Index** active

### Configuring AWS via Individual Account Integration (Direct Connection) Approach

> **On the CloudFormation templates linked below.** They are hosted as Help Centre
> attachments and currently return "not found" unless you are signed in to the
> Relyance support portal. If a template link does not open for you, either create
> the role from the permission list in this section or use the
> [Terraform module](#manage-this-integration-with-terraform) — the module is
> generated from the same integration catalog the product validates against, so it
> stays in step with the permissions Relyance actually requests.

#### Option - 1 (Recommended):

In this approach an IAM role will be created with the below permissions,

1. **SecurityAudit** - This is an AWS defined policy with the permissions that allows ReadOnly access to multiple services in AWS
2. **Custom Policy**- For Relyance to successfully discover all the services and do AI discovery, below additional permissions are required which are associated with this custom policy
```
bedrock:GetCustomModelDeployment
bedrock:GetModelInvocationJob
bedrock:ListCustomModelDeployments
bedrock:ListModelInvocationJobs
cloudwatch:GetMetricStatistics
glue:GetCrawler
glue:GetDatabase
glue:GetTable
glue:GetTables
lambda:GetEventSourceMapping
lambda:GetFunction
lambda:GetFunctionUrlConfig
resource-explorer-2:GetView
resource-explorer-2:ListViews
resource-explorer-2:Search
```

These fifteen are exactly what **SecurityAudit** does *not* already cover. In
particular it grants `bedrock:GetCustomModel` and `bedrock:ListModelInvocationJobs`
but not the `CustomModelDeployment` and `ModelInvocationJob` variants above, and it
already covers every `s3:GetBucket*`, `ec2:Describe*`, `iam:Get*` and
`sagemaker:Describe*` read Relyance makes — so those do not belong in the custom
policy. This is the same set our [Terraform module](#manage-this-integration-with-terraform)
grants, generated from the integration catalog, so the two cannot drift.

**IAM Role Creation:**

IAM role required for this integration can be created quickly by leveraging the attached [attached CloudFormation template (CFT)](https://support.relyance.ai/hc/article_attachments/44583708318349). CFT takes below as inputs and provides the required output that will have to be provided on the Relyance UI for the integration.

**Inputs for the Cloud Formation Template:**

1. Stack Name - This is required to differentiate the stack on the AWS
2. External ID - This is an unique identifier that is required for assuming the role

**Outputs from the CloudFormation Template:**

1. IAM Role Name
2. IAM Role ARN
3. ExternalID

**Important:** To create the IAM role using Option 1 (Recommended), please use the [attached CloudFormation template (CFT)](https://support.relyance.ai/hc/article_attachments/44583708318349).

#### Option - 2:

In this approach an IAM role will be created with the below permissions, in this method only specific permissions are requested to discover the services.

1. **Custom Policy**- For Relyance to successfully discover all the services and do AI discovery, below permissions are required which are associated with this custom policy
```
cloudwatch:GetMetricStatistics
dynamodb:DescribeContinuousBackups
dynamodb:DescribeTable
dynamodb:ListBackups
dynamodb:ListTagsOfResource
ec2:DescribeInstances
ec2:DescribeSnapshots
ec2:DescribeVolumes
ecs:DescribeServices
ecs:ListServices
eks:DescribeCluster
glue:GetCrawler
glue:GetDatabase
glue:GetTable
glue:GetTables
iam:GetGroup
iam:GetPolicy
iam:GetRole
iam:GetUser
iam:ListPolicies
kafka:DescribeClusterV2
kafka:DescribeConfiguration
kafka:ListNodes
lambda:GetEventSourceMapping
lambda:GetFunction
lambda:GetFunctionUrlConfig
airflow:GetEnvironment
es:DescribeDomain
rds:DescribeDBInstances
rds:DescribeIntegrations
redshift:DescribeClusters
resource-explorer-2:Search
resource-explorer-2:GetView
resource-explorer-2:ListViews
s3:GetAccelerateConfiguration
s3:GetBucketAcl
s3:GetBucketCORS
s3:GetEncryptionConfiguration
s3:GetLifecycleConfiguration
s3:GetBucketLocation
s3:GetBucketLogging
s3:GetBucketOwnershipControls
s3:GetBucketPolicy
s3:GetReplicationConfiguration
s3:GetBucketTagging
s3:GetBucketVersioning
s3:GetBucketWebsite
s3:GetBucketObjectLockConfiguration
s3:GetBucketPublicAccessBlock
s3:GetInventoryConfiguration
s3:ListAllMyBuckets
sagemaker:DescribeEndpoint
sagemaker:DescribeEndpointConfig
sagemaker:DescribeHyperParameterTuningJob
sagemaker:DescribeModel
sagemaker:DescribePipeline
sagemaker:ListTrainingJobs
sagemaker:DescribeTrainingJob
sagemaker:ListModels
sagemaker:ListEndpoints
sagemaker:ListPipelines
bedrock:ListCustomModels
bedrock:ListModelCustomizationJobs
bedrock:ListCustomModelDeployments
bedrock:ListModelInvocationJobs
bedrock:ListProvisionedModelThroughputs
bedrock:ListInferenceProfiles
bedrock:GetCustomModel
bedrock:GetCustomModelDeployment
bedrock:GetInferenceProfile
bedrock:GetModelCustomizationJob
bedrock:GetModelInvocationJob
bedrock:GetProvisionedModelThroughput
```

**IAM Role Creation:**

IAM role required for this integration can be created quickly by leveraging the [attached CloudFormation template (CFT)](https://support.relyance.ai/hc/article_attachments/44583671305741). CFT takes below as inputs and provides the required output that will have to be provided on the Relyance UI for the integration

**Inputs for the Cloud Formation Template:**

1. Stack Name - This is required to differentiate the stack on the AWS
2. External ID - This is an unique identifier that is required for assuming the role

**Outputs from the CloudFormation Template:**

1. IAM Role Name
2. IAM Role ARN
3. ExternalID

**Important:** To create the IAM role using Option 2, please use the [attached CloudFormation template (CFT)](https://support.relyance.ai/hc/article_attachments/44583671305741).

### Configuring AWS via Organization-Wide Integration (Organization Scan) Approach

To connect inventory integration with AWS Organizations, you must configure three specific IAM roles within your AWS environment.

1. OrgReaderRole
2. Delegated Administrator ReaderRole
3. Global Scanner Role

The CloudFormation templates referenced in this section are Help Centre attachments
and have the same sign-in caveat as the ones above; the
[Terraform module](#manage-this-integration-with-terraform) covers the
organization-scan roles as well.

Mandatory prerequisite to meet before creating the roles in the respective accounts,

- **In Management Account:** Go to *Resource Explorer > Settings* and ensure the **Delegated Administrator** is actually registered.
- **In Delegated Admin Account:** Go to *Resource Explorer > Settings* and change one of the indexes to **Aggregator** (only one per Org is allowed).
- **In Delegated Admin Account:** Go to *Resource Explorer > Views* and create a View named RelyanceOrgView. Ensure the "Scope" is set to the **Entire Organization**.
- **In Member accounts:** Ensure each one has a local resource explorer index active

Each role must be configured with a **Trust Relationship** allowing the Relyance platform to assume the role.

1. **Trust Relationship -**
```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::580082088342:user/tenant-prod-access"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "<Enter ExternalId>"
        }
      }
    }
  ]
}
```
2. **OrgReaderRole -**

This role should be created in Management Account only. Policies to be attached for the Role are:
```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "OrgMapping",
      "Effect": "Allow",
      "Action": [
        "organizations:ListAccounts",
        "organizations:ListDelegatedAdministrators",
        "organizations:DescribeOrganization",
        "organizations:ListRoots",
        "organizations:ListOrganizationalUnitsForParent",
        "sso:ListInstances",
        "sso:ListPermissionSets",
        "sso:ListAccountAssignmentsForPrincipal",
        "sso:DescribePermissionSet",
        "identitystore:ListGroups",
        "identitystore:ListGroupMemberships",
        "identitystore:DescribeGroup",
        "identitystore:ListUsers",
        "identitystore:ListGroupMembershipsForMember"
      ],
      "Resource": "*"
    }
  ]
}
```
To create the **OrgReaderRole** within the Management Account, deploy the stack using this CloudFormation Template: [Attachment](https://support.relyance.ai/hc/article_attachments/44590173647117)
3. **Delegated Administrator ReaderRole -**

This role should be created in Delegated Account only. Policies to be attached for the Role are:
```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DiscoveryMapping",
      "Effect": "Allow",
      "Action": [
        "resource-explorer-2:Search",
        "resource-explorer-2:GetView",
        "resource-explorer-2:ListIndexes",
        "resource-explorer-2:ListViews"
      ],
      "Resource": "*"
    }
  ]
}
```
To create the **Delegated Administrator ReaderRole** in the Delegated Administrator Account, deploy the stack using this CloudFormation Template: [Attachment](https://support.relyance.ai/hc/article_attachments/44590173656205) For an explanation on understanding the need for Delegated Administrator account, please refer to the Appendix section.
4. **Global Scanner Role -**

This role should be created in all the member accounts (including Management and Delegated Administrator Account). Custom policies to be attached for the Role are:
```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ResourceExplorerAndTags",
      "Effect": "Allow",
      "Action": [
        "resource-explorer-2:GetView",
        "resource-explorer-2:Search",
        "resource-explorer-2:ListViews",
        "tag:GetTagKeys",
        "tag:GetTagValues",
        "tag:GetResources"
      ],
      "Resource": "*"
    }
  ]
}
```
Along with the above custom policies, this role needs to be associated with **AWS managed ReadOnlyAccess** permission.

To create the **Global Scanner Role**, deploy the stack using this CloudFormation Template: [Attachment](https://support.relyance.ai/hc/article_attachments/44590204864909)

#### In the Relyance AI application:

1. Login to your Relyance account.
2. Navigate to the **Settings** Menu in the bottom left-hand side.
3. Select **Integrations**.
4. Click on the **Vendor** filter.
5. Find the **Amazon Web Services** integration card and click **Add Connection.**
6. In the **Overview** Section, select **Asset Discovery** and **AI Discovery** (if you wish Relyance to discover AI services).
7. Under the

Connection Settings section, fill in the Connection Name, enter the Rescan Frequency, and choose at least one Business Atlas association (required).
8. And in the

Authentication section, choose either

Direct Connection (Individual Account) or Organization Scan (Organization-wide) as per your chosen AWS configuration.
9. Paste these into their respective fields as per the configuration you have chosen:
    1. For **Direct Connect** -
        1. **Role ARN**: The ARN of the role you created in AWS (the CloudFormation template outputs it as *IAM Role ARN*).
        2. **External ID**: The value you have provided as an input to the CloudFormation template.
        3. **Region**: Specify your default AWS region.
    2. For **Organization Scan**,
        1. **External ID:** The unique identifier you define when creating the AWS IAM Role to add an extra layer of security to the cross-account connection.
        2. **Organization Reader Role ARN:** The Amazon Resource Name (ARN) specifically associated with the OrgReaderRole.
        3. **Delegated Resource Explorer View ARN:** The ARN for the organization-wide view located in your delegated account. *How to locate it:* Navigate to **AWS Resource Explorer**> **Views**. Click on the view you created for the organization. You can copy the ARN located at the very top of the summary page.
        4. **Delegated Resource Explorer Reader Role ARN:** The ARN for the ReaderRole residing within the Delegated Administrator account.
        5. **Assumable Account Reader Role Name:** The exact name of the Global Scanner role (the name itself, not the ARN) that will be deployed across all of your AWS accounts.
10. Click **Authenticate**
11. At this point, you should see the following result on the integrations page and Click on Finish.
12. Congratulations, you are now connected to your AWS.

![Screenshot](https://assets.relyanceuat.xyz/images/docs/44583708320269/44583671308557.png)

### Appendix

**Understanding the need for Delegated Administrator account**

The **Management Account** is the "root of trust" for the entire organization. In a well-architected environment, it must be protected as a restricted, low-traffic zone. We require a **Delegated Administrator (DA)** account for the following reasons:

- **Principle of Least Privilege:** Security best practices (and AWS Guardrails) dictate that the Management Account should only be used for billing and organization-level changes. Daily operational tasks—like resource scanning—belong in a Member Account to limit the "blast radius" of the most sensitive credentials in the Org.
- **Operational Decoupling:** AWS Resource Explorer and CloudFormation StackSets are designed to run at scale from a DA. Using a DA allows the Org to maintain visibility without granting a third-party application (or internal tool) permissions that could accidentally modify the Org’s core structure or billing.
- **Service Quotas & API Throttling:** The Management Account shares API quotas across many critical services. Moving high-volume discovery tasks to a DA prevents "noisy neighbor" scenarios where scanning activity impacts critical Org management functions.
- **Compliance & Auditing:** Segregating discovery services into a DA account creates a clean audit trail. It allows Security teams to monitor exactly who is looking at what across the Org without wading through the noise of the Management Account's logs.

Relying on the Management Account for scanning is an anti-pattern. A Delegated Administrator is the AWS-recommended standard for secure, scalable cross-account visibility. As such, our entire setup depends on having a DA, so it’s a required feature to possess.

### Verify the connection is really working

1. **Connected but almost nothing discovered.** Resource Explorer is the
   prerequisite that most often is not met. Exactly one region per account can hold
   the **Aggregator** index, and the region on the connection must be that one —
   without it `resource-explorer-2:Search` returns almost nothing and the scan looks
   like it worked.
2. **Organization Scan finds only some accounts.** Every member account needs its
   own **local** Resource Explorer index, the Delegated Administrator must be
   registered in the management account, and the organization-wide **View** must be
   scoped to the entire organization. Any one of the three missing silently reduces
   coverage instead of failing.
3. **A failure at Authenticate** is the trust policy or the external ID, on
   whichever role the connection names — for Organization Scan that is the
   Organization Reader Role, not the account role.
4. **Individual resource types missing.** SecurityAudit covers most reads; the
   fifteen actions in the custom policy above are what it does not carry. A missing
   entry there removes one resource type from the inventory and leaves the rest
   intact, which is why a partial inventory is worth checking against that list
   rather than re-running the scan.

<!-- terraform-examples:begin (generated from the integration catalog; do not hand-edit) -->

## Manage this integration with Terraform

Connections for this integration can be managed as code with the [Relyance Terraform provider](https://registry.terraform.io/providers/Relyance/relyance/latest). Non-secret fields go in `auth.params`; secret fields go in `auth.secrets_wo`, which is write-only — never stored in Terraform state. Rotate secrets by bumping `auth.secrets_wo_version`.

### AWS IAM role — Direct Connection

```hcl
resource "relyance_integration_connection" "aws_0" {
  vendor = "aws"
  name   = "<your connection name>"

  auth = {
    method = "iam-role-direct"
    params = {
      role_arn = "<role_arn>"
      region_name = "<region_name>"
    }
    # Secret fields are write-only: sent to Relyance, never stored in state.
    secrets_wo = {
      external_id = var.aws_external_id
    }
    secrets_wo_version = 1
  }

  scans = { "assets-discovery" = { enabled = true } }
}
```

### AWS IAM role — Organization Scan

```hcl
resource "relyance_integration_connection" "aws_1" {
  vendor = "aws"
  name   = "<your connection name>"

  auth = {
    method = "iam-role-organization-scan"
    params = {
      org_reader_role_arn = "<org_reader_role_arn>"
      delegated_resource_explorer_view_arn = "<delegated_resource_explorer_view_arn>"
      delegated_resource_explorer_reader_role_arn = "<delegated_resource_explorer_reader_role_arn>"
      assumable_account_reader_role_name = "<assumable_account_reader_role_name>"
      organization_config = jsonencode({
        allowed_aws_account_ids = [
          "*"
        ]
        allowed_organization_units = [
          "*"
        ]
        disallowed_aws_account_ids = []
        disallowed_organization_units = []
        s3 = {
          allowed_data_inspection_buckets = []
          allowed_inventory_buckets = []
          disallowed_data_inspection_buckets = []
          filter_last_accessed = []
          intelligent_tiers = []
          storage_class = []
        }
      })
    }
    # Secret fields are write-only: sent to Relyance, never stored in state.
    secrets_wo = {
      external_id = var.aws_external_id
    }
    secrets_wo_version = 1
  }

  scans = { "assets-discovery" = { enabled = true } }
}
```

<!-- terraform-examples:end -->
