Skip to content

AWS Setup

LightPane connects to your AWS account using a cross-account IAM role. This is the same pattern used by Datadog, Wiz, Vanta, and every major cloud SaaS integration. LightPane never stores AWS credentials — it uses temporary STS credentials that expire automatically.

What gets created

A single IAM role in your AWS account with:

  • Trust policy — allows the LightPane AWS account to assume the role
  • AWS managed policySecurityAudit, covering read-only access to security and infrastructure configuration across 40+ services
  • LightPane inline policyLightPaneAdditionalReadOnly, covering the Free Tier, Cost Explorer, Budgets, Savings Plans, account metadata, and CloudWatch metric retrieval APIs that live outside the SecurityAudit namespace
  • External ID — a unique identifier derived from your LightPane user ID to prevent confused deputy attacks

The role can only read configuration, usage, and billing data. It cannot create, modify, or delete any resource in your account, and it cannot read the contents of your S3 objects, Secrets Manager secrets, or DynamoDB items.

Setup with CloudFormation

The fastest way to create the role. LightPane publishes a CloudFormation template at:

https://lightpane.io/cloudformation/lightpane-reader-v2.yaml

and the accounts page drives a one-click flow that pre-fills it:

  1. Log in to app.lightpane.io and open Cloud Accounts → AWS.
  2. Pick a region in the Launch Stack card and click Launch Stack. The AWS CloudFormation console opens in a new tab with the template URL, the LightPane platform account ID, and your External ID all pre-filled.
  3. Confirm and create the stack. It takes about a minute — when the status reads CREATE_COMPLETE, the role exists in your account as LightPaneReader.
  4. Back on the LightPane accounts page, type your 12-digit AWS account ID (it's shown top-right in the AWS console, or as the AccountId output of the stack). LightPane constructs the role ARN from it automatically — you don't need to paste the full ARN.

That's it: name, account ID, region. LightPane has everything it needs.

The template creates this role:

AWSTemplateFormatVersion: '2010-09-09'
Description: LightPane read-only access role

Parameters:
  LightPaneAccountId:
    Type: String
    Description: LightPane platform AWS account ID
  ExternalId:
    Type: String
    Description: Unique External ID from your LightPane account

Resources:
  LightPaneReaderRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: LightPaneReader
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub 'arn:aws:iam::${LightPaneAccountId}:root'
            Action: 'sts:AssumeRole'
            Condition:
              StringEquals:
                'sts:ExternalId': !Ref ExternalId
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/SecurityAudit'
      Policies:
        - PolicyName: LightPaneAdditionalReadOnly
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Sid: FreeTier
                Effect: Allow
                Action:
                  - 'freetier:GetFreeTierUsage'
                Resource: '*'
              - Sid: CostExplorer
                Effect: Allow
                Action:
                  - 'ce:GetCostAndUsage'
                  - 'ce:GetCostAndUsageWithResources'
                  - 'ce:GetCostForecast'
                  - 'ce:GetUsageForecast'
                  - 'ce:GetDimensionValues'
                  - 'ce:GetTags'
                  - 'ce:GetCostCategories'
                  - 'ce:ListCostCategoryDefinitions'
                  - 'ce:GetRightsizingRecommendation'
                  - 'ce:GetSavingsPlansUtilization'
                  - 'ce:GetSavingsPlansCoverage'
                  - 'ce:GetAnomalies'
                  - 'ce:GetAnomalyMonitors'
                  - 'ce:GetAnomalySubscriptions'
                Resource: '*'
              - Sid: Budgets
                Effect: Allow
                Action:
                  - 'budgets:ViewBudget'
                  - 'budgets:DescribeBudgetAction'
                  - 'budgets:DescribeBudgetActionsForAccount'
                  - 'budgets:DescribeBudgetActionsForBudget'
                Resource: '*'
              - Sid: SavingsPlans
                Effect: Allow
                Action:
                  - 'savingsplans:DescribeSavingsPlans'
                  - 'savingsplans:DescribeSavingsPlansOfferings'
                  - 'savingsplans:ListTagsForResource'
                Resource: '*'
              - Sid: AccountInfo
                Effect: Allow
                Action:
                  - 'account:GetAccountInformation'
                  - 'account:GetContactInformation'
                  - 'account:ListRegions'
                Resource: '*'
              - Sid: CloudWatchMetrics
                Effect: Allow
                Action:
                  - 'cloudwatch:GetMetricData'
                Resource: '*'

Outputs:
  RoleArn:
    Value: !GetAtt LightPaneReaderRole.Arn

Manual setup

If you prefer to create the role manually or via CLI:

# 1. Create the role with the trust policy
aws iam create-role \
  --role-name LightPaneReader \
  --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": {"AWS": "arn:aws:iam::LIGHTPANE_ACCOUNT_ID:root"},
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "YOUR_EXTERNAL_ID"
        }
      }
    }]
  }'

# 2. Attach the AWS managed SecurityAudit policy
aws iam attach-role-policy \
  --role-name LightPaneReader \
  --policy-arn arn:aws:iam::aws:policy/SecurityAudit

# 3. Attach the LightPane inline policy for the additional permissions
# (Free Tier, Cost Explorer, Budgets, Savings Plans, account metadata,
# CloudWatch metric retrieval) that aren't covered by SecurityAudit.
# Save the JSON below to lightpane-additional.json first.
aws iam put-role-policy \
  --role-name LightPaneReader \
  --policy-name LightPaneAdditionalReadOnly \
  --policy-document file://lightpane-additional.json

Contents of lightpane-additional.json:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "FreeTier",
      "Effect": "Allow",
      "Action": ["freetier:GetFreeTierUsage"],
      "Resource": "*"
    },
    {
      "Sid": "CostExplorer",
      "Effect": "Allow",
      "Action": [
        "ce:GetCostAndUsage",
        "ce:GetCostAndUsageWithResources",
        "ce:GetCostForecast",
        "ce:GetUsageForecast",
        "ce:GetDimensionValues",
        "ce:GetTags",
        "ce:GetCostCategories",
        "ce:ListCostCategoryDefinitions",
        "ce:GetRightsizingRecommendation",
        "ce:GetSavingsPlansUtilization",
        "ce:GetSavingsPlansCoverage",
        "ce:GetAnomalies",
        "ce:GetAnomalyMonitors",
        "ce:GetAnomalySubscriptions"
      ],
      "Resource": "*"
    },
    {
      "Sid": "Budgets",
      "Effect": "Allow",
      "Action": [
        "budgets:ViewBudget",
        "budgets:DescribeBudgetAction",
        "budgets:DescribeBudgetActionsForAccount",
        "budgets:DescribeBudgetActionsForBudget"
      ],
      "Resource": "*"
    },
    {
      "Sid": "SavingsPlans",
      "Effect": "Allow",
      "Action": [
        "savingsplans:DescribeSavingsPlans",
        "savingsplans:DescribeSavingsPlansOfferings",
        "savingsplans:ListTagsForResource"
      ],
      "Resource": "*"
    },
    {
      "Sid": "AccountInfo",
      "Effect": "Allow",
      "Action": [
        "account:GetAccountInformation",
        "account:GetContactInformation",
        "account:ListRegions"
      ],
      "Resource": "*"
    },
    {
      "Sid": "CloudWatchMetrics",
      "Effect": "Allow",
      "Action": ["cloudwatch:GetMetricData"],
      "Resource": "*"
    }
  ]
}

Replace LIGHTPANE_ACCOUNT_ID and YOUR_EXTERNAL_ID with the values shown in your LightPane account.

Multi-account setup with StackSets

For AWS Organizations with many accounts, deploy the role across all accounts using CloudFormation StackSets:

  1. Deploy the LightPane CloudFormation template as a StackSet from your management account
  2. Target the entire Organization or specific OUs
  3. Enable auto-deployment so new accounts added to the OU get the role automatically
  4. Use a single External ID per Organization

StackSets support drift detection — if someone modifies the role, StackSets can detect and remediate the change.

Policies attached to the role

LightPane's role permissions come from two policies: the AWS-maintained SecurityAudit plus a small LightPane-specific inline policy for the cost and billing namespaces that sit outside the standard AWS service APIs.

SecurityAudit (AWS managed)

arn:aws:iam::aws:policy/SecurityAudit grants read-only access to security and configuration data across 40+ services. It includes Get*, List*, and Describe* actions.

  • Read-only — no create, update, or delete permissions
  • Maintained by AWS — updated regularly as new services launch
  • Used industry-wide — the standard policy for compliance and security tooling
  • Does not include s3:GetObject — LightPane can list your buckets and their configuration but cannot read the contents of your files
  • Does not include secretsmanager:GetSecretValue — LightPane can list your secrets but cannot read their values

LightPaneAdditionalReadOnly (inline)

AWS doesn't ship a managed policy that covers the freetier:, ce:, budgets:, savingsplans:, account:, and cloudwatch:GetMetricData actions LightPane needs. These APIs sit outside the normal per-service Describe and List operations that SecurityAudit covers, so LightPane attaches a small inline policy that explicitly enables the read-only calls it needs:

Namespace Purpose What LightPane uses it for
freetier:GetFreeTierUsage Free Tier month-to-date usage Free Tier Usage pane
ce:Get*, ce:List* Cost Explorer — spend, forecasts, anomalies, Savings Plans coverage Upcoming cost panes
budgets:View*, budgets:Describe* Budgets you've configured Upcoming budget-tracking panes
savingsplans:Describe*, savingsplans:ListTagsForResource Active Savings Plans Upcoming reservation panes
account:Get*, account:ListRegions Account contact metadata and opt-in regions Account name display, region picker
cloudwatch:GetMetricData Bulk metric retrieval for sparklines and aggregate values lambda-radar, nat-traffic, cloudfront, asg-activity, step-functions, ecs-services panes

Like SecurityAudit, every action is a read — no namespace above includes Create, Update, or Delete.

Upgrading from v1

The v1 template named this policy LightPaneCostAndBillingReadOnly and didn't include cloudwatch:GetMetricData. To upgrade an existing v1 stack, run an update-stack against the v2 template URL — CloudFormation will rename the inline policy and add the new statement. No role re-creation or trust changes are needed.

Cost Explorer is a paid API

AWS charges about $0.01 per Cost Explorer call. LightPane's cache tier ensures we make at most one call per resource per 10 minutes on the free tier (and less often on higher tiers), keeping the expected cost well below a penny per user per day. See the tiering documentation for the full velocity table.

Billing APIs are us-east-1 only

The freetier:, ce:, and budgets: namespaces only exist in us-east-1 as regional endpoints, even though they represent data about your whole account. LightPane's discovery Lambda calls them against us-east-1 automatically regardless of which region your linked account defaults to.

The External ID

The External ID prevents confused deputy attacks. LightPane generates a unique ID for each cloud account you link. It is included as a condition in the role's trust policy, ensuring that only LightPane — with the correct External ID — can assume the role.

External ID is not a secret

The External ID is a unique identifier, not an authentication credential. It prevents one LightPane customer from tricking the platform into assuming another customer's role. It does not need to be kept confidential.

Supported regions

LightPane discovers resources in any AWS region. Specify the region in your service requests or access key configuration.

Common regions:

Region Location
eu-west-1 Ireland
eu-west-2 London
eu-central-1 Frankfurt
us-east-1 N. Virginia
us-east-2 Ohio
us-west-2 Oregon
ap-southeast-1 Singapore
ap-northeast-1 Tokyo

Revoking access

Delete the IAM role in your AWS account at any time. LightPane immediately loses access. No action is needed on the LightPane side — the next discovery request will fail with an AccessDenied error, which LightPane handles gracefully.

Hiding or excluding individual resources

The SecurityAudit policy gives LightPane broad read access. If you want to keep specific resources out of LightPane without writing your own custom IAM policy, tag those resources with a lightpane-discovery tag.

Tag contract:

Tag value Effect
no (or exclude) Resource is never read into LightPane. The pane
response includes an excluded.count summary so you can see how many were
filtered, but no detail.
hidden (or count-only) Resource detail is **never returned to the
browser**. The pane response includes a hidden.count summary so you can
audit how many are hidden.
anything else, or no tag Resource is included normally.

Example — hide a specific S3 bucket from LightPane:

aws s3api put-bucket-tagging --bucket my-sensitive-bucket \
    --tagging 'TagSet=[{Key=lightpane-discovery,Value=hidden}]'

Example — fully exclude a Secrets Manager secret:

aws secretsmanager tag-resource \
    --secret-id arn:aws:secretsmanager:eu-west-1:111111111111:secret:legacy-imported-old-api-AbCdEf \
    --tags Key=lightpane-discovery,Value=no

Notes:

  • The filter is applied per resource, with no inheritance. Tagging a VPC with no does not hide the EC2 instances inside it — each instance needs its own tag.
  • Filtering applies to the source-of-truth pane only. If you exclude an EC2 instance, an Auto Scaling Group pane that simply counts members of an ASG will still include it in the count — there's no cascade through cross-service references.
  • Resource types without tag support (some IAM access keys, some VPC sub-objects) cannot be filtered this way. The filter is a no-op for them.
  • The filter operates alongside any per-key service scope you've set on a LightPane access key. Scope says "which service types this key can see"; the tag says "within those, which resources are visible".
  • LightPane logs only counts by default — the ARNs of excluded or hidden resources are not written to LightPane's CloudWatch logs unless you opt your access key in to audit-mode (Business+ feature, not yet available).