This script demonstrates how to query an AWS Athena table from a different AWS account by assuming an IAM Role. It uses the AWS SDK for JavaScript v3.
The script performs the following actions:
- Assumes a Cross-Account Role: It uses the AWS Security Token Service (STS) to obtain temporary security credentials by assuming an IAM role in a target AWS account. This is a secure way to grant temporary access to your AWS resources to users from other AWS accounts.
- Executes an Athena Query: Using the temporary credentials, it connects to Amazon Athena and executes a SQL query against a specified database and table.
- Polls for Results: It periodically checks the status of the query until it completes.
- Fetches and Displays Results: Once the query is successful, it retrieves the results from the S3 output location, parses them into a JSON format, and prints them to the console.
- Node.js and Bun (or npm/yarn) installed.
- AWS credentials (
AWS_ACCESS_KEY_IDandAWS_SECRET_ACCESS_KEY) for an IAM user with permission to assume the target role. - An IAM Role in the target account that this script can assume. The role must have:
- A trust relationship that allows the source IAM user to assume it.
- An
ExternalIdcondition in the trust policy for added security. - Permissions to run Athena queries and read the target table.
- Permissions to write query results to the specified S3 bucket (
s3:PutObject,s3:GetObject).
- Clone the Gist or download the
index.jsandpackage.jsonfiles. - Install the dependencies:
bun install
The script is configured using environment variables. You can create a .env file in the root of the project or export them in your shell session.
# Credentials for the IAM user in the source account
AWS_ACCESS_KEY_ID="YOUR_SOURCE_ACCESS_KEY"
AWS_SECRET_ACCESS_KEY="YOUR_SOURCE_SECRET_KEY"
AWS_REGION="us-east-1"
# Configuration for the cross-account role to assume
AWS_ASSUME_ROLE_EXTERNAL_ID="YOUR_UNIQUE_EXTERNAL_ID"
CLIENT_ORG_ID="TARGET_AWS_ACCOUNT_ID"
CLIENT_ROLE_NAME="NAME_OF_THE_ROLE_TO_ASSUME"
# S3 Bucket for Athena query results in the target account
CLIENT_BUCKET="your-athena-results-bucket"
CLIENT_BUCKET_PATH="path/for/results"
# Athena configuration in the target account
CLIENT_ATHENA_DB="your_athena_database"
CLIENT_ATHENA_TABLE="your_athena_table"Once the dependencies are installed and the environment variables are set, run the script with:
bun startThe script will then print the query results to the console in JSON format.
This asynchronous function is responsible for the role assumption.
- It initializes the
STSClient. - It sends an
AssumeRoleCommandwith theRoleArn, aRoleSessionName, and theExternalId. - The
RoleArnis constructed dynamically using theCLIENT_ORG_IDandCLIENT_ROLE_NAMEenvironment variables. - If successful, it returns the temporary
accessKeyId,secretAccessKey, andsessionToken.
This is the main function that orchestrates the process.
- It calls
getTemporaryCredentials()to get the temporary credentials. - It initializes the
AthenaClientusing these temporary credentials. This ensures all subsequent Athena API calls are made with the assumed role's permissions. - It sends a
StartQueryExecutionCommand. The SQL query is hardcoded in this example, but it could be made dynamic. It also specifies the output location for the results in S3. - It enters a
whileloop to poll the query's status usingGetQueryExecutionCommandevery 3 seconds. - If the query state becomes
FAILEDorCANCELLED, it throws an error. - Once the query
SUCCEEDED, it fetches the data usingGetQueryResultsCommand. - The results from Athena are in a specific
ResultSetformat. The script parses this format, using the first row as headers and subsequent rows as data, to build an array of JSON objects. - It includes specific error handling for
InvalidRequestExceptionwhich is common when the assumed role lackss3:PutObjectpermissions on the output S3 bucket.