Skip to content

nova-iris/terraform-codebuild-runner

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

AWS CodeBuild GitHub Actions Runner

A production-ready Terraform module that provisions AWS CodeBuild projects as GitHub Actions self-hosted runners. This module provides a cost-effective, scalable, and secure alternative to traditional self-hosted runners.

Features

  • βœ… Repository & Organization Support: Runners for specific repositories or entire GitHub organizations
  • βœ… Secure Token Management: Support for AWS Secrets Manager or direct token input
  • βœ… Flexible Configuration: Multiple compute types, custom buildspecs, and environment variables
  • βœ… Security Hardened: Least privilege IAM policies, network isolation, and input validation
  • βœ… Monitoring & Logging: CloudWatch dashboards, alarms, and configurable log retention
  • βœ… VPC Integration: Private network deployment with security group management
  • βœ… Scalable Architecture: Configurable runner count and concurrent job support

Quick Start

⚠️ Security Warning

NEVER hardcode GitHub tokens in Terraform files or commit them to version control. Use one of these secure approaches:

πŸ” Recommended: OIDC Authentication (Production)

module "github_secure_runner" {
  source = "your-repo/terraform-codebuild-runner/aws"
  
  github_organization     = "your-org-name"
  github_token_secret_arn = aws_secretsmanager_secret.github_token.arn
  enable_github_oidc     = true
  
  runner_name    = "my-secure-runner"
  runner_count   = 3
  compute_type   = "BUILD_GENERAL1_LARGE"
  runner_labels  = ["self-hosted", "linux", "x64", "secure"]
  
  vpc_id     = "vpc-1234567890abcdef0"
  subnet_ids = ["subnet-12345678", "subnet-87654321"]
  
  tags = {
    Project     = "GitHub Actions Runners"
    Environment = "Production"
    AuthMethod  = "OIDC"
  }
}

πŸ”’ Secure: Environment Variables

variable "github_token" {
  description = "GitHub personal access token"
  type        = string
  sensitive   = true
}

module "github_repo_runner" {
  source = "your-repo/terraform-codebuild-runner/aws"
  
  github_repository_url = "https://github.com/your-org/your-repo"
  github_token          = var.github_token
  
  runner_name    = "my-repo-runner"
  runner_count   = 2
  compute_type   = "BUILD_GENERAL1_MEDIUM"
  runner_labels  = ["self-hosted", "linux", "x64"]
  
  vpc_id     = "vpc-1234567890abcdef0"
  subnet_ids = ["subnet-12345678", "subnet-87654321"]
  
  tags = {
    Project     = "GitHub Actions Runners"
    Environment = "Production"
  }
}

Set token securely:

# Method 1: Environment variable
export TF_VAR_github_token="ghp_your_token_here"

# Method 2: terraform.tfvars (NEVER commit to git)
echo 'github_token = "ghp_your_token_here"' > terraform.tfvars

πŸ”‘ Secrets Manager Approach

resource "aws_secretsmanager_secret" "github_token" {
  name                    = "github-actions-runner-token"
  recovery_window_in_days = 0
}

# Set secret value securely (not in Terraform)
# aws secretsmanager put-secret-value --secret-id ${aws_secretsmanager_secret.github_token.id} --secret-string "ghp_your_token_here"

module "github_org_runner" {
  source = "your-repo/terraform-codebuild-runner/aws"
  
  github_organization     = "your-org-name"
  github_token_secret_arn = aws_secretsmanager_secret.github_token.arn
  
  runner_name    = "my-org-runner"
  runner_count   = 3
  compute_type   = "BUILD_GENERAL1_LARGE"
  runner_labels  = ["self-hosted", "linux", "x64"]
  
  vpc_id     = "vpc-1234567890abcdef0"
  subnet_ids = ["subnet-12345678", "subnet-87654321"]
  
  tags = {
    Project     = "GitHub Actions Runners"
    Environment = "Production"
  }
}

Requirements

  • Terraform >= 1.0
  • AWS Provider >= 4.0
  • AWS account with appropriate permissions
  • GitHub personal access token with repo scope (repository) or admin:org scope (organization)

Usage

1. GitHub Actions Workflow

Once deployed, use the runner in your GitHub Actions workflows:

name: Build
on: [push]

jobs:
  build:
    runs-on: [self-hosted, linux, x64]
    steps:
      - uses: actions/checkout@v4
      - name: Run on CodeBuild runner
        run: echo "Hello from self-hosted runner!"

2. Matrix Strategy

name: Matrix Build
on: [push]

jobs:
  test:
    runs-on: [self-hosted, linux, x64]
    strategy:
      matrix:
        node-version: [16, 18, 20]
    
    steps:
      - uses: actions/checkout@v4
      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm test

Examples

Inputs

Name Description Type Default Required
github_repository_url GitHub repository URL for repository-level runners string null NoΒΉ
github_organization GitHub organization name for organization-level runners string null NoΒΉ
github_token GitHub personal access token string null NoΒ²
github_token_secret_arn AWS Secrets Manager secret ARN containing GitHub token string null NoΒ²
runner_name Name prefix for the runner string "github-actions-runner" No
runner_count Number of concurrent runners to provision number 1 No
compute_type CodeBuild compute type string "BUILD_GENERAL1_SMALL" No
image Docker image to use for the runner string "aws/codebuild/standard:6.0" No
buildspec Custom buildspec content string null No
vpc_id VPC ID where the runner will be deployed string - Yes
subnet_ids Subnet IDs where the runner will be deployed list(string) - Yes
environment_variables Additional environment variables map(string) {} No
runner_labels Additional labels for the runner list(string) [] No
runner_group Runner group for organization-level runners string "Default" No
concurrent_jobs Number of concurrent jobs per runner number 1 No
enable_cloudwatch_logs Enable CloudWatch logging bool true No
log_retention_days Number of days to retain CloudWatch logs number 30 No
enable_github_oidc Enable GitHub OIDC integration for tokenless authentication bool false No
github_oidc_provider_url GitHub OIDC provider URL string "https://token.actions.githubusercontent.com" No
github_oidc_audience GitHub OIDC audience string "sts.amazonaws.com" No
tags Tags to apply to all resources map(string) {} No

ΒΉ Either github_repository_url or github_organization must be provided
Β² Either github_token or github_token_secret_arn must be provided

Compute Types

Type vCPU Memory Use Case
BUILD_GENERAL1_SMALL 2 3 GB Simple builds, tests
BUILD_GENERAL1_MEDIUM 4 8 GB Medium builds, compilation
BUILD_GENERAL1_LARGE 8 16 GB Large builds, complex tasks
BUILD_GENERAL1_2XLARGE 16 64 GB Heavy workloads, containers

Outputs

Name Description
codebuild_project_name Name of the CodeBuild project
codebuild_project_arn ARN of the CodeBuild project
iam_role_arn ARN of the IAM role for the CodeBuild project
security_group_id ID of the security group for the runner
github_oidc_role_arn ARN of the GitHub OIDC role (if OIDC is enabled)
github_oidc_provider_arn ARN of the GitHub OIDC provider (if OIDC is enabled)

Security Features

πŸ” OIDC Authentication (Recommended)

  • Tokenless authentication using GitHub's OIDC provider
  • Temporary credentials with automatic expiration
  • Repository-specific access control
  • Audit trail for all authentication attempts
  • No persistent secrets to manage or rotate

πŸ”’ Secrets Management

  • AWS Secrets Manager integration for secure token storage
  • Encrypted storage using AWS KMS
  • Automatic rotation capability
  • Fine-grained access policies
  • Access logging and monitoring

πŸ›‘οΈ Least Privilege IAM

  • Regional restrictions for EC2 operations
  • Resource-specific ARNs rather than wildcards
  • Explicit deny statements for sensitive services
  • Conditional access based on resources
  • Minimal required permissions only

πŸ” Network Security

  • VPC integration with configurable subnets
  • Security groups with proper egress rules
  • Private network deployment support
  • VPC endpoints for private communication
  • Network isolation and segmentation

πŸ“Š Security Monitoring

  • CloudWatch logging with configurable retention
  • Security alerts and notifications
  • Audit trails with CloudTrail integration
  • Build failure monitoring
  • Resource usage tracking

Security Best Practices

⚠️ Critical Security Rules

  1. NEVER hardcode GitHub tokens in Terraform files
  2. NEVER commit .tfvars files containing secrets to version control
  3. NEVER share GitHub tokens in plain text
  4. ALWAYS use OIDC authentication for production workloads
  5. ALWAYS rotate tokens regularly (every 90 days)
  6. ALWAYS use the principle of least privilege

πŸ”‘ Secure Token Management

Option 1: OIDC Authentication (Recommended)

# GitHub Actions workflow
permissions:
  id-token: write
  contents: read

steps:
  - name: Configure AWS Credentials
    uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: ${{ vars.OIDC_ROLE_ARN }}
      aws-region: us-east-1

Option 2: Environment Variables

# Set token in environment
export TF_VAR_github_token="ghp_your_token_here"

# Or use .tfvars file (NEVER commit to git)
echo 'github_token = "ghp_your_token_here"' > terraform.tfvars

Option 3: AWS Secrets Manager

# Create secret
aws secretsmanager create-secret \
  --name github-actions-runner-token \
  --description "GitHub token for runners"

# Set secret value securely
aws secretsmanager put-secret-value \
  --secret-id github-actions-runner-token \
  --secret-string "ghp_your_token_here"

πŸ—οΈ Infrastructure Security

IAM Role Security

resource "aws_iam_role" "codebuild_role" {
  name = "${var.runner_name}-codebuild-role"
  
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Principal = {
          Service = "codebuild.amazonaws.com"
        }
        Action = "sts:AssumeRole"
      }
    ]
  })
}

Network Security

resource "aws_security_group" "runner_sg" {
  name        = "${var.runner_name}-sg"
  description = "Security group for GitHub Actions runner"
  vpc_id      = var.vpc_id

  # Restrictive egress rules
  egress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

πŸ” Security Monitoring

CloudWatch Alarms

resource "aws_cloudwatch_metric_alarm" "build_failure_alarm" {
  alarm_name          = "${var.runner_name}-build-failure-alarm"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 2
  metric_name         = "FailedBuilds"
  namespace           = "AWS/CodeBuild"
  period              = 300
  statistic           = "Sum"
  threshold           = 1
  
  dimensions = {
    ProjectName = var.runner_name
  }
}

Audit Logging

# Monitor OIDC usage
aws logs filter-log-events \
  --log-group-name /aws/cloudtrail \
  --filter-pattern "AssumeRoleWithWebIdentity"

# Check for suspicious activity
aws logs filter-log-events \
  --log-group-name /aws/codebuild/your-runner-name \
  --filter-pattern "ERROR|FAILED|DENIED"

πŸ”„ Token Rotation

Automated Rotation Setup

# Create Lambda function for token rotation
aws lambda create-function \
  --function-name github-token-rotator \
  --runtime python3.9 \
  --role your-lambda-role-arn \
  --handler lambda_function.lambda_handler \
  --zip-file fileb://rotate-token.zip

# Set up CloudWatch Events for monthly rotation
aws events put-rule \
  --name github-token-monthly-rotation \
  --schedule-expression "cron(0 0 1 * ? *)"

# Add Lambda target
aws events put-targets \
  --rule github-token-monthly-rotation \
  --targets "Id"="1","Arn"="your-lambda-function-arn"

Monitoring & Logging

CloudWatch Resources

  • Log Groups: Configurable retention (1-365 days)
  • Dashboards: Build metrics, duration, success/failure rates
  • Alarms: Build failure notifications
  • Metrics: Build count, duration, success rates

Accessing Logs

# View runner logs
aws logs tail /aws/codebuild/your-runner-name --follow

# Check build status
aws codebuild batch-get-projects --names your-runner-name

Advanced Configuration

Custom Buildspec

buildspec = <<-EOT
version: 0.2

phases:
  install:
    runtime-versions:
      nodejs: 18
      python: 3.11
    commands:
      - echo "Installing custom tools..."
  
  pre_build:
    commands:
      - pip install -r requirements.txt
  
  build:
    commands:
      - npm run build
      - npm test
  
  post_build:
    commands:
      - echo "Build completed successfully"
EOT

Custom Environment Variables

environment_variables = {
  NODE_VERSION = "18"
  PYTHON_VERSION = "3.9"
  DOCKER_VERSION = "20.10"
  CUSTOM_VAR = "custom-value"
}

Advanced VPC Configuration

vpc_id     = "vpc-1234567890abcdef0"
subnet_ids = ["subnet-12345678", "subnet-87654321"]

# Additional security groups
security_group_ids = [
  aws_security_group.additional_sg.id,
  aws_security_group.runner_sg.id
]

Cost Optimization

Right-Sizing Runners

  • Use BUILD_GENERAL1_SMALL for simple tasks
  • Monitor build times and adjust compute types
  • Scale runner count based on demand

Build Caching

Enable local caching in custom buildspecs:

cache:
  type: LOCAL
  modes:
    - LOCAL_CUSTOM_CACHE
    - LOCAL_SOURCE_CACHE

Monitoring Costs

  • Set up CloudWatch billing alerts
  • Monitor CodeBuild usage patterns
  • Track runner utilization rates

Troubleshooting

Common Issues

GitHub Token Problems

# Verify token permissions
curl -H "Authorization: token YOUR_TOKEN" https://api.github.com/user

# Check repository access
curl -H "Authorization: token YOUR_TOKEN" https://api.github.com/repos/owner/repo

Network Connectivity

# Check security group rules
aws ec2 describe-security-groups --group-ids your-sg-id

# Test connectivity to GitHub
curl -I https://github.com

Build Failures

# Check CloudWatch logs
aws logs tail /aws/codebuild/your-runner-name --follow

# Check CodeBuild project status
aws codebuild batch-get-projects --names your-runner-name

IAM Permissions

# Check IAM role
aws iam get-role --role-name your-runner-codebuild-role

# Test role permissions
aws iam simulate-principal-policy --policy-source-arn your-role-arn --action-names "logs:CreateLogGroup"

Development

Prerequisites

  • AWS CLI configured with appropriate credentials
  • Terraform installed locally
  • GitHub personal access token for testing

Testing

# Clone repository
git clone https://github.com/your-org/terraform-codebuild-runner.git
cd terraform-codebuild-runner

# Test repository example
cd examples/github-repo
terraform init
terraform plan

# Test organization example
cd ../github-org
terraform init
terraform plan

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Update documentation
  5. Submit a pull request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

Changelog

[v1.0.0] - 2024-01-XX

  • Initial stable release
  • Repository and organization-level runner support
  • Comprehensive security hardening
  • CloudWatch monitoring and dashboards
  • Complete test coverage and documentation

About

Production-ready Terraform module for AWS CodeBuild GitHub Actions runners with OIDC authentication

Resources

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages