Beacon evaluates AWS accounts against the CIS AWS Foundations Benchmark and additional controls spanning IAM, S3, networking, encryption, logging, and tagging, covering all enabled regions in the account. No agent is deployed in the customer account. Beacon assumes a read-only cross-account IAM role using AWS STS, so no long-term secrets are ever stored.
Beacon uses cross-account role assumption (AWS STS AssumeRole) to access each customer account. The customer creates a read-only IAM role in their account and grants Beacon's AWS principal permission to assume it. Beacon never stores AWS access keys or secret access keys, only the customer's role ARN and a per-connection external ID.
The IAM role Beacon assumes carries only the SecurityAudit and ViewOnlyAccess AWS managed policies. These policies grant broad read access for compliance scanning but grant no write, delete, or administrative permissions.
Every Beacon AWS connection is issued a unique external ID. The IAM role's trust policy must include an sts:ExternalId condition matching this value. This prevents a confused-deputy attack where a third party tricks Beacon into assuming a role it was not intended to access.
There are two ways to provision the IAM role. The CloudFormation path is faster and less error-prone; the manual path is available if the customer's environment restricts CloudFormation.
Beacon generates a pre-signed CloudFormation launch URL that deploys a stack containing the IAM role, trust policy, and external ID condition in a single click. No manual JSON editing is required.
Request an onboarding token
Use the guided wizard in Beacon (or call POST /api/clients/aws/onboarding-token). The response returns the externalId, the beaconPrincipalArn, and a pre-signed cfnLaunchUrl.
Launch the CloudFormation stack
Share the cfnLaunchUrl with the customer (or open it yourself if you have cross-account access). The customer signs in to their AWS console and clicks Create stack. The stack takes roughly 30 seconds to complete.
Copy the role ARN
After the stack reaches CREATE_COMPLETE, open the Outputs tab and copy the BeaconRoleArn value.
Save the connection in Beacon
Edit the client in Beacon (Clients → select client → Edit). Paste the role ARN into the AWS role ARN field. The external ID is pre-populated automatically. Click Save changes.
Use this path if the customer's environment does not permit CloudFormation stacks deployed from an external URL, or if they prefer Terraform or manual provisioning.
Retrieve Beacon's principal ARN and external ID
Call POST /api/clients/aws/onboarding-token to obtain beaconPrincipalArn and externalId. The external ID is unique to this connection, do not reuse it across accounts.
Create the IAM role with a trust policy
In the customer's AWS account, go to IAM → Roles → Create role. Choose Another AWS account and enter Beacon's account ID (from the principal ARN). After creation, update the trust policy to the following, replacing the placeholders with the actual values:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "<beaconPrincipalArn>"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "<externalId>"
}
}
}
]
}
Attach the required AWS managed policies
Attach both of the following AWS managed policies to the role:
arn:aws:iam::aws:policy/SecurityAudit
Read security-relevant configuration across all services: IAM, S3, CloudTrail, Config, GuardDuty, and more.
arn:aws:iam::aws:policy/job-function/ViewOnlyAccess
Read resource lists and metadata across all regions: EC2, RDS, EBS, VPC, and global services.
Save the connection in Beacon
Edit the client in Beacon (Clients → select client → Edit). Paste the role ARN into the AWS role ARN field. The external ID is pre-populated. Click Save changes.
Do not add any additional policy permissions beyond SecurityAudit and ViewOnlyAccess. Beacon's scanner is designed to operate within these read-only bounds and does not require write access of any kind.
Beacon scans all enabled regions in the AWS account. Global services (IAM, CloudFront, Route 53) are evaluated once per scan; regional services (EC2, RDS, EBS, VPC, CloudTrail, S3 bucket location, GuardDuty, KMS) are evaluated in each enabled region in parallel.
AWS-REGION-001, Unauthorised region detected. Beacon compares the set of enabled regions against an approved-regions list you maintain per client. If a region is enabled in the account but not on the approved list, Beacon raises a finding. Use the Approve region action on the finding (or call POST /api/clients/{id}/connection/regions/approve) to add it to the approved list and resolve the finding.
The approved-regions list is per-connection and persists across scans. Adding a new region to the list does not trigger an immediate re-scan, the finding resolves on the next scheduled or manually triggered scan.
Beacon's AWS checks map to the CIS AWS Foundations Benchmark and include additional controls across the following domains:
IAM
Root account MFA, hardware MFA on root, access key age, password policy strength, unused credentials, and privileged policy attachment checks.
S3
Public access block settings (account-level and per-bucket), bucket-level ACLs, server-side encryption defaults, versioning, and MFA Delete enforcement.
Networking / EC2 / EBS
VPC flow logs enabled, no unrestricted inbound SSH/RDP in security groups, default VPC in use, EBS volume encryption by default, and public AMI checks.
Encryption / RDS
RDS instance encryption at rest, automated backups enabled, multi-AZ configuration for production instances, and KMS key rotation.
Logging / monitoring / GuardDuty
CloudTrail enabled and multi-region, log file validation on, CloudTrail S3 bucket not publicly accessible, CloudWatch metric filters and alarms for key API calls, and GuardDuty enabled per region.
Tagging
Required-tag compliance on EC2 instances, RDS instances, and S3 buckets against the tag policy configured per client.
Region drift
AWS-REGION-001: enabled regions not on the approved list trigger a finding, surfacing shadow infrastructure before it accumulates.
Checks that cannot be evaluated because a service is not enabled in the account (for example, GuardDuty not activated in a region, or no RDS instances present) are recorded with a status of unknown rather than fail, so they do not unfairly penalise the compliance score.
Once the AWS connection is saved, a Sync now button appears on the client detail page. Beacon also runs scans automatically on the configured schedule (global default: every 6 hours). You can override the scan frequency per client on the client edit form.
During each AWS scan, Beacon:
Most common cause: the IAM role's trust policy does not include the sts:ExternalId condition, or the external ID value does not match. Re-check the trust policy and ensure the StringEquals condition value exactly matches the external ID shown in Beacon.
AccessDenied on AssumeRole — The Beacon principal ARN is not listed in the trust policy, or the external ID condition does not match. Verify the trust policy in the customer's account and confirm you are using the correct Beacon principal ARN from the onboarding token.
AccessDenied on API calls after AssumeRole — One or both of the required managed policies is missing. Confirm both SecurityAudit and ViewOnlyAccess are attached to the role in the customer's account.
NoSuchEntityException on role ARN — The role ARN is incorrect or the role was deleted. Verify the ARN in the customer's IAM console and update it in the Beacon client edit form.
Scan stuck in "syncing" state — A large number of enabled regions or a throttle burst may cause the regional fan-out to run long. Beacon retries throttled requests automatically. If the scan does not complete within 15 minutes, contact support.
Beacon connects Azure, AWS, and Google Cloud the same agentless, read-only way. See the other per-cloud setup guides, or review the security model.