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 contextPurposeRepresentative actions
FineGrainedEC2PermissionsRunner lifecycle: launch a just-in-time instance for a queued job, then terminate itec2:RunInstances, ec2:CreateFleet, ec2:CreateLaunchTemplate, ec2:TerminateInstances, ec2:CreateImage, ec2:CreateTags
SpotServiceLinkedRolePermissionsSpot capacity: create and maintain the EC2 Spot service-linked roleiam:CreateServiceLinkedRole, iam:PassRole scoped to AWSServiceRoleForEC2Spot
NetworkPermissionsDiscovery: read the network objects a stack needs, and manage the endpoints the stack createsec2:DescribeRegions, ec2:DescribeVpcs, ec2:DescribeSubnets, ec2:CreateVpcEndpoint
StoragePermissionsCache and telemetry: the S3 objects behind the cache action and runner system logs, plus EBS snapshotss3:PutObject, s3:GetObject, s3:PutLifecycleConfiguration, ec2:CreateSnapshot
CloudFormationPermissionsUpgrades: raise change set requests when a connection or stack template moves to a new versionCloudFormation 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 removedWhat stops workingWhat still works
FineGrainedEC2PermissionsInstances no longer launch, so jobs sit in the queue; running instances are no longer terminated by WarpBuild, so capacity has to be reclaimed by handExisting stack, cache bucket, dashboard configuration
SpotServiceLinkedRolePermissionsRunner sets configured for spot capacity fail to acquire instancesOn-demand capacity types, if the service-linked role already exists in the account
NetworkPermissionsImport mode stack creation cannot enumerate VPCs, subnets, route tables, and security groups; endpoint management for the stack breaksRunners on a stack that is already created, until an endpoint changes
StoragePermissionsCache reads and writes fail, runner system logs stop being pushed, bucket lifecycle configuration cannot be appliedJob execution itself, at cold-cache speed
CloudFormationPermissionsConnection and stack template upgrades cannot be raised as change sets, so every template move becomes a manual applyEverything 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.com

The 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.

QuestionConnection role (warpbuild-<integration-id>)Runner instance profile
Who uses itThe WarpBuild control plane, to launch and terminate instancesThe EC2 runner instance, and therefore your workflow steps
Who creates itThe CloudFormation connection stack that you applyYou, with aws iam create-role and aws iam create-instance-profile
Where it is configuredThe cloud connection in the WarpBuild dashboardPer runner, under Custom Runner configuration and the Instance Profile ARN field
How many existOne per cloud connectionAs many as you want, scoped per workload
What a compromised build step reaches through itNothing; the role is held by the control planeExactly the policy you attached, and nothing more
Effect of removing itRunners stop launchingJobs 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.