Skip to content

Connect AWS to Xplorr: Access Keys and IAM Roles for Cloud Cost Data

Xplorr reads your AWS costs through the Cost Explorer API and your resources through read-only describe calls. It never writes anything to your account: no resource is created, modified or deleted, and every permission below is a read.

There are two ways to connect, and which one you want depends on how many accounts you have.

Best forWhat Xplorr stores
Access keysOne account, or a few unrelated onesThe access key pair for that account, encrypted
IAM roleManaging many accounts, typically as an MSP or a group with several AWS accountsOne set of your keys for the organization, plus each account’s role name

Prefer Terraform or CloudFormation? See Set it up with code.

  • Cost Explorer must be enabled in the account. Open Billing → Cost Explorer in the AWS console once; it takes up to 24 hours to populate the first time. Without it every cost call returns an error.
  • You need the member or admin role in Xplorr. Viewers cannot connect accounts. Whoever connects an account owns it and controls who else in the organization can see it.
  • AWS cost data lags by up to 24 hours. Today’s spend is not final until tomorrow. This is AWS’s own refresh rate, not Xplorr’s.

The simplest path, and the right one unless you are connecting many accounts.

  1. Create a read-only IAM user

    In the AWS console, go to IAM → Users → Create user. Give it a name such as xplorr-readonly. Do not give it console access.

  2. Attach permissions

    Create a customer managed policy from the least privilege policy below and attach it to the user. It holds exactly the calls Xplorr makes.

    If you would rather use an AWS managed policy, ReadOnlyAccess on its own also covers every call Xplorr makes, but it is much broader: it grants read access across almost every AWS service.

    Do not attach CostExplorerFullAccess. It grants ce:*, which includes write actions (creating and deleting anomaly monitors, cost categories and reports, and changing Cost Explorer preferences) that Xplorr never needs.

  3. Create an access key

    Open the user → Security credentials → Create access key → choose Third-party service. Copy the access key ID and the secret; the secret is shown once.

  4. Connect it in Xplorr

    In Xplorr go to Infrastructure → Cloud Accounts and click Connect account. Choose AWS, then Access keys.

    Fill in:

    • Account name: whatever you want to call it in Xplorr

    • AWS account ID: the 12 digit number in the top right of the AWS console

    • Credentials (JSON): the Fill template button gives you the shape:

      {
      "accessKeyId": "AKIAIOSFODNN7EXAMPLE",
      "secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
      "region": "us-east-1"
      }

    Click Test connection first if you want to check the keys without saving anything. Then click Connect.

Use this when you manage several AWS accounts and would rather not create a key pair in each one. You save one set of keys for your Xplorr organization, and Xplorr assumes a role in each account using them.

  1. Create an IAM user for Xplorr to act as

    In the account that will do the assuming (usually your own management account), create an IAM user named xplorr-assumer, with no console access. Instead of the read-only policy, attach a policy that only allows it to assume the roles you are about to create:

    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Effect": "Allow",
    "Action": "sts:AssumeRole",
    "Resource": "arn:aws:iam::*:role/xplorr-readonly"
    }
    ]
    }

    Create an access key for it.

  2. Save those keys once in Xplorr

    In Connect account → AWS → IAM role, enter the access key ID and secret, then click Save base keys. Xplorr checks them against AWS before storing them, and they are reused for every account you connect this way.

    You can change or remove them later from the same place: the banner shows when they last changed, with Replace keys and Remove beside it.

  3. Create the role in each account you want to connect

    In each target account, create a role named xplorr-readonly (or any name, as long as it matches the sts:AssumeRole resource in step 1 and the role name you give Xplorr; role names are case sensitive) with:

    • Trust relationship: the xplorr-assumer user from step 1

      {
      "Version": "2012-10-17",
      "Statement": [
      {
      "Effect": "Allow",
      "Principal": {
      "AWS": "arn:aws:iam::YOUR-ACCOUNT-ID:user/xplorr-assumer"
      },
      "Action": "sts:AssumeRole"
      }
      ]
      }

      Replace YOUR-ACCOUNT-ID with the account holding the user from step 1.

    • Permissions: the least privilege policy below, or the broader AWS managed ReadOnlyAccess. Not CostExplorerFullAccess, which includes write actions.

  4. Optional: add an external ID

    If you add an external ID to the role’s trust policy, enter the same value in Xplorr. It is genuinely optional here, and you choose the value; Xplorr does not generate one. It is most useful when the assuming user is shared.

  5. Connect the account in Xplorr

    Enter the account name, the AWS account ID of the target account, and the role name. Xplorr builds the ARN for you and shows it under the field so you can check it before connecting.

This is the complete list of what Xplorr calls, and the policy we recommend. Every action here corresponds to a call in the code, and nothing Xplorr calls is missing from it. The AWS managed ReadOnlyAccess policy also includes all of these actions, if you prefer a managed policy and accept its much wider read access. Do not use CostExplorerFullAccess: it grants ce:*, write actions included.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CostAndCommitments",
"Effect": "Allow",
"Action": [
"ce:GetCostAndUsage",
"ce:GetCostAndUsageWithResources",
"ce:GetReservationCoverage",
"ce:GetReservationUtilization",
"ce:GetReservationPurchaseRecommendation",
"ce:GetSavingsPlansCoverage",
"ce:GetSavingsPlansUtilizationDetails",
"ce:GetSavingsPlansPurchaseRecommendation"
],
"Resource": "*"
},
{
"Sid": "Commitments",
"Effect": "Allow",
"Action": [
"savingsplans:DescribeSavingsPlans",
"ec2:DescribeReservedInstances",
"rds:DescribeReservedDBInstances",
"elasticache:DescribeReservedCacheNodes"
],
"Resource": "*"
},
{
"Sid": "Credits",
"Effect": "Allow",
"Action": [
"billing:GetCredits",
"billing:GetCreditAllocationHistory"
],
"Resource": "*"
},
{
"Sid": "Inventory",
"Effect": "Allow",
"Action": [
"ec2:DescribeRegions",
"ec2:DescribeInstances",
"ec2:DescribeVolumes",
"ec2:DescribeVpcs",
"ec2:DescribeSubnets",
"ec2:DescribeSecurityGroups",
"ec2:DescribeNatGateways",
"ec2:DescribeInternetGateways",
"elasticloadbalancing:DescribeLoadBalancers",
"tag:GetResources"
],
"Resource": "*"
},
{
"Sid": "IdleDetection",
"Effect": "Allow",
"Action": ["cloudwatch:GetMetricStatistics"],
"Resource": "*"
},
{
"Sid": "Pricing",
"Effect": "Allow",
"Action": ["pricing:GetProducts"],
"Resource": "*"
},
{
"Sid": "Invoices",
"Effect": "Allow",
"Action": ["invoicing:ListInvoiceSummaries"],
"Resource": "*"
},
{
"Sid": "AuditLog",
"Effect": "Allow",
"Action": ["cloudtrail:LookupEvents"],
"Resource": "*"
}
]
}

What each group is for:

GroupUsed by
CostAndCommitmentsAll cost figures, and coverage and utilisation for reservations and Savings Plans
CommitmentsListing what you actually own, which Cost Explorer does not report in full
InventoryThe resource list, and network costs by VPC, NAT gateway and load balancer. tag:GetResources is the Resource Groups Tagging API, which is how Xplorr finds resources across every service without a client per service
IdleDetectionCPU and attachment metrics behind idle EC2 and unattached EBS recommendations. Note this is GetMetricStatistics, not GetMetricData
PricingOn-demand rates for sizing recommendations
InvoicesReconciling Xplorr’s totals against your actual invoice
AuditLogEvery sync makes one cloudtrail:LookupEvents call (the last hour, at most one event) to record whether the CloudTrail audit log is readable, and Cloud Accounts shows a warning on the account when it is not. Anomaly root cause reads these management events to show who changed what before a spend spike

If you omit a group, the feature it powers reports an error rather than silently showing nothing.

If you use the FOCUS billing export or the AWS carbon footprint export, Xplorr reads those from S3 and needs s3:GetObject and s3:ListBucket on those buckets. Neither is required for normal cost data.

The public Xplorrio/cloud-onboarding repository, release v0.0.1, creates the IAM role method for you: the xplorr-readonly role with the least privilege policy above and, in one account, the IAM user xplorr-assumer (no password, no access key) that assumes it. It then prints the values the Connect account form asks for. The console shows the same quick starts under Set up with code on the Connect account form, pre-filled with the role name, region and external ID you typed.

provider "aws" {
region = "us-east-1"
}
module "xplorr" {
source = "git::https://github.com/Xplorrio/cloud-onboarding.git//aws/terraform?ref=v0.0.1"
role_name = "xplorr-readonly"
region = "us-east-1"
# iam_external_id = "..." # optional; generate one with: openssl rand -hex 16
}
output "xplorr_connect_form" {
value = module.xplorr.xplorr_connect_form
}

Apply it with credentials for the account you connect, then print the form values:

Terminal window
terraform init
terraform apply
terraform output -json xplorr_connect_form

No input is required in the default customer_principal trust mode: the module reads the account ID from the credentials you apply with, and role_name and region default to xplorr-readonly and us-east-1. The module README lists every input and has examples for a first account, additional accounts and an AWS Organization. A Terragrunt wrapper is in the same repository.

Then, in Connect account, choose IAM role and fill in:

Xplorr fieldTerraform outputCloudFormation output
IAM user access key ID and secret access keyOnce per Xplorr organization: create an access key for xplorr-assumer in IAM > Users > xplorr-assumer > Security credentials > Create access key > Third-party service, then Save base keysThe same
AWS account IDaws_account_idAwsAccountId
Role namerole_nameRoleName
External IDiam_external_id (leave blank when null)IamExternalId (leave blank when not shown)
RegionregionRegion

No template creates the access key, so the secret never lands in Terraform state or a stack. The role_arn (RoleArn) output matches the ARN the form shows under Role name.

For more accounts, create the user in one account only. In every other account create just the role, trusting that user (create_user = false with trusted_principal_arns, or CreateUser=false with TrustedPrincipalArn), and let the user assume it (user_assumable_role_arns or AdditionalAssumableRoleArns where the user lives). Every template also has an xplorr_principal trust mode; it needs keyless onboarding, which is not available yet, so keep the default.

  1. Xplorr validates the credentials immediately, before saving anything. It has 20 seconds; past that you get an error saying the account was not added and nothing was saved.
  2. If the account is already connected, you get a clear message saying so rather than a duplicate.
  3. On success the account is saved and the first sync starts, backfilling 90 days so last month is complete on the day you connect.
  4. The first sync usually takes 10 to 30 minutes. You get an email when it finishes.

The status column shows Active once the account is connected. A failed sync shows Error with the reason underneath it.

Cost Explorer called with an AWS Organizations management (payer) account’s credentials answers for the whole organization: every member account’s spend is in it. So a management account connected on its own shows the cost of the whole organization, which is what you want if you connect only that one.

If you also connect some member accounts separately, in the same Xplorr organization, their cost would otherwise be counted twice. Xplorr prevents that:

  • A management account’s data leaves out every other AWS account connected in your Xplorr organization, so a connected member’s cost is counted once, under its own account. This applies to costs, network costs, resource costs, Spot spend, Savings Plans and reservation coverage and utilization, and FOCUS export rows.
  • Members that are not connected separately stay inside the management account’s cost.
  • An account marked inactive is not synced, so its cost stays inside the management account rather than disappearing.
  • A management only or member only setup sends the same requests as before.

The exclusion matches on the AWS account ID you entered for each account, so enter it as the 12 digit number, without dashes.

Cloud Accounts shows a note under a management account, for example AWS Organizations management account: its cost includes 3 linked accounts not connected separately. 2 linked accounts connected separately are excluded to avoid double counting. Data Health marks it Management account.

Every night Xplorr compares each account’s stored total with the total AWS reports for the same scope, from one ce:GetCostAndUsage request (daily, unblended cost, not grouped), for the month to date and the previous month. For a management account that request leaves out the separately connected members, the same way the sync does; a member account is filtered to itself. The result appears on Data Health as Matches bill, Bill mismatch with the gap, or Bill not checked with the reason. It needs no permission beyond the policy above.

Because of the exclusion, a management account’s total in Xplorr, and on Data Health, is lower than the organization’s full bill in the AWS console by exactly the connected members’ spend. Add the members’ own totals to compare with the full bill.

ActionWho
Connect an accountMember or admin
Sync, edit or delete an accountAn organization admin, or whoever connected it
Save or rotate the organization’s base AWS keysAdmin
See an account’s dataAdmins see everything; members and viewers see only accounts they have been granted

“No base AWS credentials configured for this organization” You chose the IAM role method without saving the organization keys first. Go back to step 2 of Method 2.

“Account did not answer within 20 seconds, so the account was not added” AWS did not respond in time. Nothing was saved, so retrying is safe. If it keeps happening, check that Cost Explorer is enabled.

Cost data is empty after a successful connection Cost Explorer is enabled but not yet populated. It can take 24 hours on first enable. Verify the policy includes ce:GetCostAndUsage.

Recommendations are missing but costs work Usually a missing cloudwatch:GetMetricStatistics or tag:GetResources. Idle-resource detection and the resource sweep need those specifically.

The account row asks you to add cloudtrail:LookupEvents The last sync was refused the CloudTrail audit log. Add the AuditLog group to the policy; the warning clears after the next sync. Costs and everything else keep syncing without it.

Invoices do not reconcile invoicing:ListInvoiceSummaries is missing, or the account is a member account and the invoice belongs to the payer.

Does Xplorr ever write to my AWS account? No. Every call listed above is a read, and there are no others.

How often does it sync? Once a day by default. You can sync any account on demand from its row in the accounts table.

Does this work for AWS GovCloud or China regions? Not currently. Both use separate partitions with their own endpoints.

Can I connect a member account rather than the payer? Yes, but it only sees its own costs. Connect the payer account for organization-wide figures, or connect each account separately. You can also connect both: members connected separately are left out of the management account’s cost, so nothing is counted twice (see AWS Organizations management accounts).

Today the IAM role method assumes roles as you, using the keys of an IAM user in your account that you save with Xplorr. Keyless onboarding is coming soon: your role will trust Xplorr directly, with an external ID Xplorr generates, and Xplorr will store no credential of yours at all. It is not available yet, so do not create a role that trusts any account other than your own. This page will give the exact trust policy when it ships.

When that lands, both methods will work at once and existing connections will keep syncing. Re-creating a role to trust Xplorr directly will be a deliberate step you take when convenient, not a break.