Cloud · AWS Core Services

Cross-account IAM delegation and ExternalId security in data lakes

awsHardawsiamcross-accountsecurity

Interview question

How do you securely configure cross-account IAM role assumption with ExternalId for third-party ETL vendors?

How to answer

The short answer

Enterprise data platforms frequently integrate third-party software-as-a-service (SaaS) tools (such as Fivetran, Databricks, or Snowflake) to extract data from or load data into customer-owned Amazon S3 buckets. Granting these vendors long-lived access keys creates a critical credential compromise risk.

The industry standard security pattern is cross-account IAM role assumption with ExternalId.

The Confused Deputy vulnerability

Suppose Company A and Company B both use the same third-party ETL vendor. The vendor operates an AWS account (AccountVendor: 111122223333).

If Company A grants AccountVendor permission to assume an IAM role (RoleA) in Company A's account without an external identifier:

  • A malicious actor at Company B could configure their vendor pipeline to assume RoleA by guessing its Amazon Resource Name (ARN).
  • The vendor service, operating as an authorized principal, assumes RoleA on behalf of Company B.
  • Company B gains unauthorized read and write access to Company A's private data lake.

This scenario represents the classic Confused Deputy attack.

Remediating with ExternalId

To eliminate this vulnerability, Company A requires an sts:ExternalId in the role trust policy:

JSON
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111122223333:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "companyA-unique-uuid-token-98765"
        }
      }
    }
  ]
}

When the vendor software initiates the sts:AssumeRole API call, it must pass the shared unique secret token in the request header. If another tenant attempts to target Company A's role ARN, the request fails immediately because the tenant does not possess Company A's secret identifier.