Skip to content

Terraform module to set up self-hosted GitHub Actions runners in AWS CodeBuild.

License

Notifications You must be signed in to change notification settings

carlosbustillordguez/terraform-aws-codebuild-github-runners

Repository files navigation

Self-hosted GitHub Actions runners in AWS CodeBuild

Terraform module to set up self-hosted GitHub Actions runners in AWS CodeBuild containers to process GitHub Actions workflow jobs.

This module is mainly based in Self-hosted GitHub Actions runners in AWS CodeBuild and has been configured to support a webhook at the organization level.

To use GitHub Actions self-hosted runners in CodeBuild, update your GitHub Actions workflow YAML file in GitHub.

Table of Contents:

Solution Overview

A CodeBuild project is configured to set up self-hosted GitHub Actions runners in CodeBuild containers to process GitHub Actions workflow jobs. This is done by setting up a webhook using a CodeBuild project, and updating the GitHub Actions workflow YAML to use self-hosted runners hosted on CodeBuild machines.

Self-hosted GitHub Actions runners in AWS CodeBuild

The GitHub self-hosted runners will be created as an ephemeral runner in the repository that made the request event WORKFLOW_JOB_QUEUED and the runs-on setting in your GitHub workflow must set according the expected format by AWS CodeBuild, otherwise the request won't be processed.

The high-level steps to configure a CodeBuild project to run GitHub Actions jobs are as follows:

  1. Create a personal access token to connect the CodeBuild project to GitHub.
  2. Create a CodeBuild project with a webhook and set up the webhook with the WORKFLOW_JOB_QUEUED event filter.
  3. Update your GitHub Actions workflow YAML in GitHub to configure your build environment.

Important Notes

  • By default CodeBuild logs are stored in AWS CloudWatch in the /aws/codebuild/<code_project_name> log group. To change this, set the input_codebuild_logs_config input variable.

  • All resources with tags support, will be tagged with the following tags as default:

    • Terraform: indicates the resources is managed by Terraform. Value true.
    • TerraformWorkspace: indicates the current Terraform's workspace. If no workspace is used, the value is default.

    Additional tags can be defined by setting the tags input variable, e.g.:

    tags = {
      Project = "MyProject"
      TerraformModule = "MyModule"
    }

GitHub Integration

When working with GitHub source CodeBuild webhooks, the CodeBuild service will automatically create (on aws_codebuild_webhook resource creation) and delete (on aws_codebuild_webhook resource deletion) the GitHub repository webhook using its granted OAuth permissions.

The AWS account that Terraform uses to create CodeBuild webhook must have authorized CodeBuild to access GitHub's OAuth API in each applicable region. This is a manual step that must be done before executing this Terraform module. If OAuth is not configured, AWS will return an error similar to ResourceNotFoundException: Could not find access token for server type github.

OAuth can be configured by setting the default source credential for CodeBuild in the working region, e.g.: https://eu-west-1.console.aws.amazon.com/codesuite/codebuild/sourceCredentials/default?provider=github&region=eu-west-1. Three options are available:

  • GitHub App: Connect project to GitHub using an AWS managed GitHub App.
  • Personal access token: Connect project to GitHub using a personal access token.
  • OAuth App: Connect project to GitHub using an OAuth App.

Fined-grained Personal Access Token Permissions

Create a fine-grained personal access token with the following permissions:

  • Repository permissions:

    • Contents: Read-only. Grants access to private repositories.
    • Commit statuses: Read and write. Grants permission to create commit statuses.
    • Webhooks: Read and write. Grants permission to manage webhooks.
    • Administration: Read and write. Grants administration permissions on repositories.
  • Organization permission:

    • Webhooks: Read and write. Grants permission to manage webhooks for an organization.

Then, save the token value in AWS Secrets Manager. The new secret must have the following keys and values (update the <GH_PAT> placeholder with the PAT value):

Key Value
ServerType GITHUB
AuthType PERSONAL_ACCESS_TOKEN
Token <GH_PAT>

and the following tags:

Key Value
codebuild:source
codebuild:source:provider github
codebuild:source:type personal_access_token

Using AWS CLI (update the <GH_PAT> placeholder with the PAT value):

export AWS_REGION="eu-west-1"

aws secretsmanager create-secret \
  --region "$AWS_REGION"\
  --name 'aws-codebuild-github-runners' \
  --description 'GitHub fined-access token' \
  --secret-string '{
                  "ServerType":"GITHUB",
                  "AuthType":"PERSONAL_ACCESS_TOKEN",
                  "Token":"<GH_PAT>"
                  }' \
  --tags Key=codebuild:source,Value='' \
         Key=codebuild:source:type,Value='github' \
         Key=codebuild:source:provider,Value='personal_access_token'

Configuring the CodeBuild Environment

The CodeBuild environment is defined by the codebuild_project_environment input variable. Default values are suitable for most of the cases.

VPC Configuration

This module is designed to create a CodeBuild project inside a VPC and provides access to private resources. The specified VPC must meet the following requirements:

  • The subnet used by the CodeBuild project must provide outbound access. Private subnets with a NAT Gateway are highly recommended.
  • The attached Security Group to the CodeBuild project must provide only outbound access to Internet.

For a full checklist see best practices for VPCs.

Label overrides supported with the CodeBuild-hosted GitHub Actions runner

In your GitHub Actions workflow YAML, you can provide a variety of label overrides that modify your self-hosted runner build. Any builds not recognized by CodeBuild will be ignored but will not fail your webhook request.

CodeBuild allows you to provide multiple overrides in a single label, for example:

runs-on: codebuild-<project-name>-${{ github.run_id }}-${{ github.run_attempt }}-<environment-type>-<image-identifier>-<instance-size>

To override the instance size to BUILD_GENERAL1_MEDIUM, set

runs-on: codebuild-<project-name>-${{ github.run_id }}-${{ github.run_attempt }}-medium

Usage

module "codebuild_github_runners" {
  source = "../"

  codebuild_project_name        = "ghSelfhostedRunners"
  codebuild_project_description = "Uses CodeBuild to run GitHub Self-hosted Runners."
  github_organization_name      = "myorg"
  pat_aws_secret_name           = "aws-codebuild-github-runners"
  aws_region                    = "eu-west-1"

  codebuild_vpc_config = {
    security_group_ids = ["sg-abc"]
    subnets            = ["subnet-abc", "subnet-def", "subnet-ghi"]
    vpc_id             = "vpc-abc"
  }

  tags = {
    Project         = "CodeBuild GitHub Runners"
    TerraformModule = "codebuild_github_runners"
    Environment     = "Integrations"
  }
}

Requirements

Name Version
terraform >=1.5
aws >=5.63.0

Providers

Name Version
aws 5.63.0

Modules

No modules.

Resources

Name Type
aws_codebuild_project.this resource
aws_codebuild_webhook.this resource
aws_iam_policy.base resource
aws_iam_policy.codebuild_cw_logs resource
aws_iam_policy.codebuild_s3_logs resource
aws_iam_policy.codebuild_vpc resource
aws_iam_policy.secret_manager resource
aws_iam_role.codebuild resource
aws_iam_role_policy_attachment.base resource
aws_iam_role_policy_attachment.codebuild_cw_logs resource
aws_iam_role_policy_attachment.codebuild_s3_logs resource
aws_iam_role_policy_attachment.codebuild_vpc resource
aws_iam_role_policy_attachment.secret_manager resource
aws_caller_identity.current data source
aws_secretsmanager_secret.pat data source

Inputs

Name Description Type Default Required
aws_region The AWS region to provision the resources. string n/a yes
codebuild_logs_config CodeBuild logs configuration.
cloudwatch_logs: (Optional) Configuration to store logs on AWS CloudWatch.
- status: Current status of logs in CloudWatch Logs for a build project. Valid values: ENABLED, DISABLED.
- group_name: Group name of the logs in CloudWatch Logs.
- stream_name: Prefix of the log stream name of the logs in CloudWatch Logs.
s3_logs: (Optional) Configuration to store logs on AWS S3.
- status: Current status of logs in S3 for a build project. Valid values: ENABLED, DISABLED.
- location: Name of the S3 bucket and the path prefix for S3 logs. Must be set if status is ENABLED, otherwise it must be empty.
- encryption_disabled: Whether to disable encrypting S3 logs.
object({
cloudwatch_logs = optional(object({
status = string
group_name = string
stream_name = string
}))
s3_logs = optional(object({
status = string
location = string
encryption_disabled = bool
}))
})
{} no
codebuild_project_description The description of the CodeBuild build project. string n/a yes
codebuild_project_environment The CodeBuild environment configuration.
compute_type: (Required) Information about the compute resources the build project will use.
image: (Required) Docker image to use for this build project.
Valid values include Docker images provided by CodeBuild, DockerHub images and full
Docker repository URIs such as those for ECR.
type: (Required) Type of build environment to use for related builds.
image_pull_credentials_type: (Optional) Type of credentials AWS CodeBuild uses to pull images in your build.
privileged_mode: (Optional) Whether to enable running the Docker daemon inside a Docker container.
object({
compute_type = string
image = string
type = string
image_pull_credentials_type = optional(string, "CODEBUILD")
privileged_mode = optional(bool, true)
})
{
"compute_type": "BUILD_GENERAL1_SMALL",
"image": "aws/codebuild/standard:7.0",
"image_pull_credentials_type": "CODEBUILD",
"privileged_mode": true,
"type": "LINUX_CONTAINER"
}
no
codebuild_project_name The name of the CodeBuild build project. string n/a yes
codebuild_vpc_config The VPC configuration to provision the CodeBuild Runners.
security_group_ids: (Required) Security group IDs to assign to running builds.
subnets: (Required) Subnet IDs within which to run builds.
vpc_id: (Required) ID of the VPC within which to run builds.
object({
security_group_ids = list(string)
subnets = list(string)
vpc_id = string
})
n/a yes
github_organization_name The name of the GitHub organization to add the webhook for AWS CodeBuild Runners. string n/a yes
pat_aws_secret_name The name of the AWS Secret Manager secret with the personal access token with access to GitHub. string "" no
tags Tags added to all supported resources. map(any) {} no

Outputs

Name Description
codebuild_webhook_payload_url The CodeBuild endpoint where webhook events are sent.
codebuild_webhook_url The URL to the webhook.

About

Terraform module to set up self-hosted GitHub Actions runners in AWS CodeBuild.

Resources

License

Stars

Watchers

Forks

Packages

No packages published