IAM Permissions for BYOC on AWS
WarpBuild BYOC on AWS asks for one IAM role, grouped into five named policy contexts. What each context does, how to narrow it, and what breaks if you cut it.
WarpBuild BYOC on AWS asks for one IAM role in your account, created by a CloudFormation template that you apply yourself, with its permissions grouped into five named policy contexts so a security reviewer can read them one block at a time. That role governs what WarpBuild may do to your account; a separate instance profile, which you create and attach per runner, governs what your GitHub Actions job steps may do once an instance is running.
This page walks the five contexts by purpose, maps each one to the moment in the job lifecycle where it is exercised, states what stops working when a context is removed, and separates the two identities so a review can approve them independently. The full policy document is expanded in the AWS BYOC configuration guide, and the account-level view of the setup is on BYOC runners on AWS for GitHub Actions.
Overview
Connecting an AWS account creates a single IAM role named warpbuild-<integration-id>. That role is the entire access surface WarpBuild holds in your account. BYOC runs on AWS, GCP, and Azure, and the AWS path is the one described here.
| Policy context | Purpose | Representative actions |
|---|---|---|
FineGrainedEC2Permissions | Runner lifecycle: launch a just-in-time instance for a queued job, then terminate it | ec2:RunInstances, ec2:CreateFleet, ec2:CreateLaunchTemplate, ec2:TerminateInstances, ec2:CreateImage, ec2:CreateTags |
SpotServiceLinkedRolePermissions | Spot capacity: create and maintain the EC2 Spot service-linked role | iam:CreateServiceLinkedRole, iam:PassRole scoped to AWSServiceRoleForEC2Spot |
NetworkPermissions | Discovery: read the network objects a stack needs, and manage the endpoints the stack creates | ec2:DescribeRegions, ec2:DescribeVpcs, ec2:DescribeSubnets, ec2:CreateVpcEndpoint |
StoragePermissions | Cache and telemetry: the S3 objects behind the cache action and runner system logs, plus EBS snapshots | s3:PutObject, s3:GetObject, s3:PutLifecycleConfiguration, ec2:CreateSnapshot |
CloudFormationPermissions | Upgrades: raise change set requests when a connection or stack template moves to a new version | CloudFormation change set actions |
Read the expanded document in the configuration guide before the review meeting. It lists the statements for the EC2, spot, network, and storage contexts and describes the CloudFormation context alongside them, so the reviewer sees the literal template rather than a summary of it.
Architecture
The permissions look broad on paper because they are exercised across one short lifecycle. Following a single job makes the grouping easier to defend.
GitHub queues a job whose runs-on label matches one of your custom runner sets. WarpBuild reads which instance types are available in your region and availability zones, launches an instance from a launch template in your stack, tags it, registers a just-in-time runner against your GitHub organization, and terminates the instance when the job ends. During the job, the cache action and the runner telemetry writer read and write objects in the stack S3 bucket. Nothing in that sequence holds state between jobs, and every instance is discarded at the end.
Each context therefore fails in a specific way rather than degrading the whole system.
| Context removed | What stops working | What still works |
|---|---|---|
FineGrainedEC2Permissions | Instances no longer launch, so jobs sit in the queue; running instances are no longer terminated by WarpBuild, so capacity has to be reclaimed by hand | Existing stack, cache bucket, dashboard configuration |
SpotServiceLinkedRolePermissions | Runner sets configured for spot capacity fail to acquire instances | On-demand capacity types, if the service-linked role already exists in the account |
NetworkPermissions | Import mode stack creation cannot enumerate VPCs, subnets, route tables, and security groups; endpoint management for the stack breaks | Runners on a stack that is already created, until an endpoint changes |
StoragePermissions | Cache reads and writes fail, runner system logs stop being pushed, bucket lifecycle configuration cannot be applied | Job execution itself, at cold-cache speed |
CloudFormationPermissions | Connection and stack template upgrades cannot be raised as change sets, so every template move becomes a manual apply | Everything on the current template version |
The last row is the one teams underestimate. Template versions carry fixes: stacks created before CloudFormation template v1.4 can hit ECR authentication timeouts for runners in public subnets, and the fix is a stack upgrade through the WarpBuild dashboard. Cutting the CloudFormation context does not block that upgrade forever, though it does move the work to your team.
Configuration
Two customization paths are supported, and both are documented in the configuration guide.
Edit before you apply. Modify the CloudFormation template on the AWS redirect page before applying the connection role stack. This is the path for teams whose policy forbids applying a vendor template as published.
Edit after creation. Modify the role once it exists. It follows the warpbuild-<integration-id> format, so it is straightforward to target from your own IAM tooling or from a drift detector.
Resource scoping is the other lever. WarpBuild tags every resource it provisions with managed-by: warpbuild, which lets you write AWS IAM tag-based access control conditions that keep the role inside resources WarpBuild created. Resource naming follows fixed patterns as well, which the same conditions can key on: S3 buckets are warpbuild-*, EC2 instances and EBS volumes are warp-*, and launch templates are tmpl-warp-*.
Attaching an instance profile to a runner takes one explicit grant. The iam:PassRole statement already in the connection template points at the EC2 Spot service-linked role ARN, so it does not cover your runner role.
aws iam put-role-policy \
--role-name warpbuild-<integration-id> \
--policy-name PassRolePolicy \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::<account-id>:role/ci-runner-role",
"Condition": {
"StringEquals": {
"iam:PassedToService": "ec2.amazonaws.com"
}
}
}
]
}'Confirm the grant landed before you point a workflow at the runner:
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::<account-id>:role/warpbuild-<integration-id> \
--action-names iam:PassRole \
--resource-arns arn:aws:iam::<account-id>:role/ci-runner-role \
--context-entries ContextKeyName=iam:PassedToService,ContextKeyType=string,ContextKeyValues=ec2.amazonaws.comThe full walkthrough, from creating the role through selecting it on a runner, is on attach an IAM instance profile to AWS BYOC runners.
Terraform support exists for BYOC on AWS, and it starts one layer above this. The provider reads an existing stack and manages runner images and custom runner sets; the connection role stays a CloudFormation object that you apply and own.
Operations
Keeping the two identities separate is what makes an ongoing review cheap. One is reviewed when the connection is created or upgraded. The other is reviewed whenever a workload changes.
| Question | Connection role (warpbuild-<integration-id>) | Runner instance profile |
|---|---|---|
| Who uses it | The WarpBuild control plane, to launch and terminate instances | The EC2 runner instance, and therefore your workflow steps |
| Who creates it | The CloudFormation connection stack that you apply | You, with aws iam create-role and aws iam create-instance-profile |
| Where it is configured | The cloud connection in the WarpBuild dashboard | Per runner, under Custom Runner configuration and the Instance Profile ARN field |
| How many exist | One per cloud connection | As many as you want, scoped per workload |
| What a compromised build step reaches through it | Nothing; the role is held by the control plane | Exactly the policy you attached, and nothing more |
| Effect of removing it | Runners stop launching | Jobs lose AWS access while runners keep launching |
WarpBuild injects no permissions into runner workloads. A job holds exactly the permissions carried by the instance profile you attached, so a deploy runner and a pull request test runner can hold different AWS authority under one stack. The security hardening guide carries least-privilege policy examples for the two common cases, ECR push and S3 artifact upload, plus the IMDSv2 requirement that closes the request-forgery path to instance credentials.
For a shorter version of this page to paste into a review ticket, see what permissions does BYOC need in my AWS account. For the rest of the review surface, network posture and metadata settings included, work through the security checklist for BYOC runners on AWS.
Two operational habits are worth setting up on day one. First, treat the connection role as a reviewable artifact: diff it after every stack or connection upgrade, because permissions are updated when new features need them. Second, alert on iam:PassRole policy changes for the connection role, since that single statement is what decides which runner roles can be attached.
Costs split along the same line as permissions. WarpBuild charges $0.002 per runner minute for BYOC Linux runners and $0.002 per runner minute for BYOC Windows runners, and your own AWS account is billed directly for EC2, EBS, and data transfer at your account rates, including any discounts you already hold (WarpBuild pricing, checked 2026-08-13).
For the compliance question that follows this one in most reviews: SOC 2 Type 2, with trust.warpbuild.com as the linked evidence. On AWS BYOC the Linux and Windows sets are the ones this role launches.
FAQ
How many IAM roles does WarpBuild BYOC on AWS need?
One role in your account per cloud connection, named warpbuild-<integration-id> and created by the CloudFormation connection stack. Runner instance profiles are separate roles that you create and attach per runner, and WarpBuild never creates them for you.
Can I remove permissions from the WarpBuild connection role?
Yes. Edit the CloudFormation template on the AWS redirect page before you apply it, or edit the role after it is created. Each policy context maps to a function, so removing one disables that function rather than degrading it: cutting StoragePermissions, for example, stops cache reads and writes and runner system logs.
Why does the connection role include iam:PassRole?
The PassRole statement in the connection template is scoped to the EC2 Spot service-linked role ARN. Attaching an instance profile to your runners needs a second PassRole grant, scoped to your own runner role and conditioned on iam:PassedToService equals ec2.amazonaws.com.
Start with $10 in free credits
Change the runner label in your workflow and keep the rest of your GitHub Actions setup. Runner time is billed per minute.