Running AWS at the Edge — IAM Roles Anywhere
The Edge Computing Challenge Link to heading
Traditional AWS authentication relies on long-lived access keys or assumes you’re running within AWS infrastructure. Storing access keys on servers is insecure — and hardcoding them in application code is even worse. So what happens when you need secure AWS access from:
- On-premises servers
- Edge computing devices
- CI/CD pipelines in other clouds
- IoT devices at remote locations
- Hybrid cloud environments
Enter IAM Roles Anywhere - AWS’s solution for extending IAM roles beyond the AWS boundary using X.509 certificates.
By the end of this article, you’ll have a working setup where an edge device authenticates to AWS using a certificate from a free, self-hosted CA — no access keys anywhere.
What is IAM Roles Anywhere? Link to heading
IAM Roles Anywhere lets workloads outside AWS assume IAM roles using X.509 certificates instead of long-lived access keys.
Key benefits:
- No more long-lived credentials stored on edge devices
- Certificate-based authentication with automatic rotation
- Fine-grained permissions using existing IAM policies
- Audit trail through CloudTrail integration
- Temporary credentials that expire automatically
Core Concepts Link to heading
Trust Anchor — This is the root of trust. You register a Certificate Authority (CA) with AWS. IAM Roles Anywhere will only accept credentials signed by a CA you’ve registered here. Think of it as telling AWS: “I vouch for any certificate signed by this CA.”
Profile — A Profile maps a certificate to an IAM role (or set of roles) with an optional permission boundary. When a workload presents a valid certificate, the Profile determines what role it can assume and what the maximum permissions are. You can have multiple Profiles — for example, one for read-only edge devices and one for devices that need to write to S3.
Credential Helper — The aws_signing_helper binary is a tool you run on the external workload. It handles the cryptographic handshake: presenting the certificate, signing the request, and exchanging it for temporary AWS credentials. It integrates directly with the AWS credential provider chain.
Setting Up step-ca Link to heading
Instead of paying $400/month for AWS Private CA, we’ll use step-ca — an open-source CA server that runs anywhere. It handles certificate issuance, renewal, and the full PKI lifecycle for free.
For this tutorial we’ll run everything on localhost. In production you’d host step-ca on a dedicated machine reachable by your devices. Install the step CLI and step-ca:
# macOS
brew install step
# Linux (Debian/Ubuntu)
wget https://dl.smallstep.com/cli/docs-cli-install/latest/step-cli_amd64.deb
sudo dpkg -i step-cli_amd64.deb
wget https://dl.smallstep.com/certificates/docs-ca-install/latest/step-ca_amd64.deb
sudo dpkg -i step-ca_amd64.deb
Step 1 — Initialize the CA Link to heading
step ca init
The wizard will prompt you for:
- A name for your CA (e.g.,
my-edge-ca) - A DNS name or IP where the CA will be reachable — use
localhostfor this tutorial - A port — use
9000(ports below 1024 require root on macOS) - A password to protect the CA private key
This generates a root certificate, an intermediate certificate, and a config file under ~/.step/.
Step 2 — Start the CA Server Link to heading
step-ca $(step path)/config/ca.json
Step 3 — Issue a Certificate for Your Workload Link to heading
Issue a certificate for the edge device. The Common Name identifies the device and will appear as the session name in CloudTrail logs, so use something meaningful:
step ca certificate edge-device-01 device.crt device.key \
--ca-url https://localhost:9000 \
--root $(step path)/certs/root_ca.crt
This creates device.crt and device.key. Restrict permissions on the private key:
chmod 600 device.key
Step 4 — Export the Certificate Bundle Link to heading
step-ca signs device certificates with the intermediate CA, not the root. AWS must verify the full chain (device → intermediate → root), so registering only the root cert will cause an “Untrusted signing certificate” error. Export both:
cat $(step path)/certs/root_ca.crt $(step path)/certs/intermediate_ca.crt
The next section uses this combined PEM output to register the Trust Anchor via the AWS CLI.
Setting Up IAM Roles Anywhere Link to heading
Step 1 — Create the Trust Anchor Link to heading
BUNDLE=$(cat $(step path)/certs/root_ca.crt $(step path)/certs/intermediate_ca.crt)
aws rolesanywhere create-trust-anchor \
--name "my-edge-ca" \
--source "sourceType=CERTIFICATE_BUNDLE,sourceData={x509CertificateData=$BUNDLE}" \
--enabled \
--region us-east-1
Note the trustAnchorArn in the output — you’ll need it for the next step.
Step 2 — Create the IAM Role Link to heading
Save the following as trust-policy.json, substituting your Trust Anchor ARN:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "rolesanywhere.amazonaws.com"},
"Action": ["sts:AssumeRole", "sts:TagSession", "sts:SetSourceIdentity"],
"Condition": {
"ArnEquals": {
"aws:SourceArn": "<TRUST-ANCHOR-ARN>"
}
}
}]
}
The condition locks this role to your specific Trust Anchor — no other trust anchor can assume it. Then create the role and attach a policy:
aws iam create-role \
--role-name EdgeDeviceRole \
--assume-role-policy-document file://trust-policy.json
aws iam attach-role-policy \
--role-name EdgeDeviceRole \
--policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess
Keep permissions as narrow as possible — grant only what the workload actually needs.
Step 3 — Create the Profile Link to heading
aws rolesanywhere create-profile \
--name "edge-device-profile" \
--role-arns "<ROLE-ARN>" \
--duration-seconds 3600 \
--enabled \
--region us-east-1
Note the profileArn in the output.
Step 4 — Test the Credential Helper Link to heading
With all three ARNs in hand, verify everything works:
aws_signing_helper credential-process \
--certificate /path/to/device.crt \
--private-key /path/to/device.key \
--trust-anchor-arn <TRUST-ANCHOR-ARN> \
--profile-arn <PROFILE-ARN> \
--role-arn <ROLE-ARN>
You should see a JSON response with a temporary AccessKeyId, SecretAccessKey, and SessionToken. If you get “Untrusted signing certificate”, double-check that your Trust Anchor bundle includes both the root and intermediate CA certs.
Real-World Use Case — Edge Device Fleet Link to heading
Imagine you’re running a fleet of edge devices in the field — sensors, cameras, or industrial controllers — each needing to push data to S3 or publish to an SNS topic. The traditional approach is to bake an access key into each device — hard to rotate across a fleet, and a single compromised device exposes credentials shared by every other device.
With IAM Roles Anywhere, each device gets its own unique certificate issued by step-ca at provisioning time. The setup looks like this:
- Each device has a certificate with a unique Common Name (e.g.,
sensor-device-042). This becomes the session name in CloudTrail, so every API call is traceable to a specific device. - The certificate is valid for 24 hours and renewed automatically by the
stepCLI before expiry — no manual rotation. - If a device is decommissioned or physically destroyed, the private key is gone with it — no one can authenticate using that device’s credentials.
- Each device assumes the same
EdgeDeviceRole, but because sessions are scoped per certificate, you can use IAM condition keys likeaws:PrincipalTagto write policies that restrict each device to its own S3 prefix.
Note: If a device is lost rather than destroyed, revoke its certificate at the CA level immediately. With 24-hour certificates the exposure window is bounded, but revocation cuts it to zero. This is a major advantage over long-lived access keys, which remain valid indefinitely until manually deleted.
The end result: a fleet where every device has short-lived, automatically rotating credentials, full per-device auditability in CloudTrail, and a single revocation point if anything goes wrong.
Caveat: Each edge device needs network connectivity to your step-ca server — both at initial provisioning to receive its certificate, and every 24 hours to renew it. If step-ca is unreachable, a device can’t renew and will lose AWS access once its certificate expires. For truly remote or intermittently connected devices, consider pre-provisioning certificates with a longer validity period, or ensuring step-ca is reachable via VPN or a dedicated network path.
Cleanup Link to heading
When you’re done, tear down the AWS resources to avoid any lingering costs or open trust relationships.
# Delete the Profile
aws rolesanywhere delete-profile \
--profile-id <PROFILE-ID> \
--region us-east-1
# Delete the Trust Anchor
aws rolesanywhere delete-trust-anchor \
--trust-anchor-id <TRUST-ANCHOR-ID> \
--region us-east-1
# Detach the policy before deleting the role
aws iam detach-role-policy \
--role-name EdgeDeviceRole \
--policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess
# Delete the IAM Role
aws iam delete-role \
--role-name EdgeDeviceRole
If you’re done with step-ca entirely, stop the server and remove the config:
# Stop the CA server (Ctrl+C in the terminal where it's running, or:)
pkill step-ca
# Remove all step-ca data
rm -rf $(step path)