AWS CodeBuildでセルフホステッド GitHub Actionsランナーを設定する

## 背景
- ソースリポジトリをセルフホステッドのGitLabからGitHubに移行する計画がある
- GitHubには社内からのみアクセスしたいので、GitHub Enterpriseの機能でソースIPを絞る必要がある
- GitHubホステッドランナーはIPアドレスが特定できないため使用不可
- セルフホステッドのGitHub Actionsランナーが必要となる

## 今回の記事の主目的：
セルフホステッドのGitHub Actionsランナーをがっつりとホスティングするのは避けたいので、何らかのサービスに乗りたいと思っていた。
そうしたところ、以下の機能が今年4月にリリースされたということを知り、試してみた。
https://docs.aws.amazon.com/codebuild/latest/userguide/action-runner.html

## ランナーの中でやっていること：
以下のようにJavaのDBテストを実施する（SpringBoot）
- MySQLのコンテナを起動
- actions/checkout
- actions/setup-java
- mvn test

## 大まかな手順：
1. まずは、GitHubのリポジトリにWebhookを登録し、CodeBuildと連携する。（豆蔵さんの記事のまま）

2. ソースIPを絞らずに、JavaのDBテストを実装する

3. ソースIPを絞るために、VPC + Subnet + NATGateway + EIPの構成をcdkで作る

4. 上記のネットワーク資源をCodeBuildと連携する（CodeBuildを編集する）

5. GitHubのOrganizationsでソースIPの絞り込みを行う

以下に、手順に沿って説明していきます。

## 手順詳細

### 1. GitHubのリポジトリにWebhookを登録し、CodeBuildと連携する

こちらは、豆蔵さんの記事が非常に分かりやすいので、リンクを貼っておきます。
https://developer.mamezou-tech.com/blogs/2024/04/29/githubactions-codebuild-runner/

### 2. ソースIPを絞らずに、JavaのDBテストを実装する
SpringBootのアプリでMySQLを使ったテストを実施します。
ここでは、GitHub Actionsのスクリプトを掲載します。

```yaml:github-actions-codebuild-runner.yaml
name: test-codebuild-runner
on:
  push:

jobs:
  build:
    runs-on: codebuild-GitHubActionsExampleRunner-${{ github.run_id }}-${{ github.run_attempt }}
    
    services:
      mysql:
        image: mysql:8
        env:
          MYSQL_ROOT_PASSWORD: password
          MYSQL_DATABASE: database-name
          TZ: 'Asia/Tokyo'
          MYSQL_CHARACTER_SET_SERVER: 'utf8mb4'
          MYSQL_COLLATION_SERVER: 'utf8mb4_unicode_ci'
        ports:
          - 3306:3306
        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=10

    steps:
    - uses: actions/checkout@v4

    - name: Set up JDK 17
      uses: actions/setup-java@v4
      with:
        java-version: '17'
        distribution: 'adopt'
        cache: 'maven'

    - name: Run tests
      run: mvn test
```
### 3. ソースIPを絞るために、VPC + Subnet + NATGateway + EIPの構成をcdkで作る

ここでは、cdkのソースを掲載しておきます。

```typescript:vpc-with-codedeploy-cdk-project-stack.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';

export class VpcWithCodedeployCdkProjectStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // VPCの作成
    const vpc = new ec2.Vpc(this, 'MyVpc', {
      cidr: '10.x.x.x/16',
      maxAzs: 1, // アベイラビリティゾーンの数
      natGateways: 1,
      subnetConfiguration: [
        {
          cidrMask: 24,
          name: 'PrivateSubnet',
          subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
        },
        {
          cidrMask: 24,
          name: 'PublicSubnet',
          subnetType: ec2.SubnetType.PUBLIC,
        },
      ],
    });
    
    // セキュリティグループの作成
    const securityGroup = new ec2.SecurityGroup(this, 'MySecurityGroup', {
      vpc,
      allowAllOutbound: true, // アウトバウンドで全てのIPに送信を許可
      description: 'Allow all outbound traffic',
      securityGroupName: 'MySecurityGroup',
    });

  }
}


```

cdkデプロイしたら、EIPの値をメモします。（後で、GitHubに設定します）

### 4. 上記のネットワーク資源をCodeBuildと連携する（CodeBuildを編集する）

ここでは、1. の手順からの変更点のみを掲載します。（マネジメントコンソールの画面スクショです）

変更するのは、追加設定の部分です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/1a59d09b-5ccf-4b46-1b33-d1262a611c61.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/f37cb811-dc03-5c7e-2d7c-0b15743663ee.png)
説明：
- ネットワーク資源との連携と直接関係ありませんが、ランナーの中でDockerを使うために「特権付与」のチェックをします。（これをチェックしないとDockerInDockerが起動しません）
- VPC、サブネット、セキュリティグループを設定します
- 「VPC設定の確認」を押すと、設定の成否が確認できます（便利です）

### 5. GitHubのOrganizationsでソースIPの絞り込みを行う

こちらは画面キャプチャーなどを載せられないので、設定の手順へのリンクを貼っておきます。
Allow IP ListにEIPの値を追加します。
[手順リンク](https://docs.github.com/ja/enterprise-cloud@latest/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/managing-allowed-ip-addresses-for-your-organization)

## まとめ
この記事では、GitHubリポジトリへの移行に伴い、AWS CodeBuildを利用してセルフホステッドのGitHub Actionsランナーを設定し、ネットワーク設定を行う手順について解説しました。これにより、ソースIPを絞り込む必要がある場合でも、セキュアにビルドを実行することができます。

ホスティングするというよりは、GitHub ActionsとAWS CodeBuildを連携するという感じで、かなりモダンなアーキテクチャーになりました！

## 注意点
実際に二本目のワークフローを組んだ時にハマった点を書いておきます。
### 新しいビルドプロジェクトを作成する際にはGitHubのIPアドレス制御を一時的に外す
新しいビルドプロジェクトを作成する際に、IPアドレス制御を有効なままにすると、webhookの登録に失敗します。これは、AWS側からGitHubへのアクセスがVPCを介さない操作のため、IPアドレス制御を入れてあるとはねられるためです。

### VPCをCodeBuildに紐づける際には、EC2操作権限のあるポリシーをアタッチする必要がある
CodeBuildの生成時に自動的にRoleが作成されていますが、VPCを設定する際には、EC2に対して「リスト, 許可の管理, 書き込み」が可能なポリシーをアタッチする必要があります。これが無いと、SecurityGroupの設定が出来ないという旨のエラーが発生します。


## 参考記事
非常に参考になりました。ありがとうございます！

https://aws.amazon.com/jp/about-aws/whats-new/2024/04/aws-codebuild-managed-github-action-runners/

https://developer.mamezou-tech.com/blogs/2024/04/29/githubactions-codebuild-runner/

https://zenn.dev/yuta28/articles/codebuild-support-github-action-runners