GitHubに格納しているコードをS3バケットにバックアップするGitHub Actionsを実装してみた


はじめに

お仕事で実装を行ったTerraformのコードは、いうまでもなくGitHubのプライベートリポジトリで管理をしているのですが、セキュリティ対策やDRといった観点で、GitHubのリポジトリ以外の場所にも保管しろという話がありまして、どうしようかと考えた上で、AWSのリージョン障害の場合も考慮して、現在使用しているリージョンとは別のリージョンにS3バケットを作成してそこにバックアップを取得するという形になりました。

要件

要件は以下の通りです。

  • 自動でバックアップ取得を行いたいので、リポジトリの main ブランチにマージされたタイミングをトリガにしてGitHub Actionsを発火させてバックアップを実行したい
  • もしもバックアップに失敗した時に備えてS3バケット側でもバージョン管理はできるようにしたい。

S3バケットをTerraformで作成する

これは言うまでもなくいつものお手軽なS3バケットを作成するためのTerraformのコードになります。大阪リージョンに構成することもちょっと考えましたが、まぁ東京リージョンでもいいでしょってことで、お決まりのパブリックブロックアクセスを設定して、バージョニングを有効にしています。

# ================================================================================
# S3 Bucket for Source Code Backup
# ================================================================================
resource "aws_s3_bucket" "source_backup_tokyo" {
  bucket = "${local.project}-${local.env}-s3-github-backup-tokyo-bucket"

  tags = {
    Name = "${local.project}-${local.env}-s3-github-backup-tokyo-bucket"
  }
}

resource "aws_s3_bucket_ownership_controls" "source_backup_tokyo" {
  bucket = aws_s3_bucket.source_backup_tokyo.id

  rule {
    object_ownership = "BucketOwnerPreferred"
  }
}

resource "aws_s3_bucket_acl" "source_backup_tokyo" {
  bucket = aws_s3_bucket.source_backup_tokyo.id
  acl    = "private"

  depends_on = [
    aws_s3_bucket_ownership_controls.source_backup_tokyo,
  ]
}

resource "aws_s3_bucket_public_access_block" "source_backup_tokyo" {
  bucket = aws_s3_bucket.source_backup_tokyo.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_s3_bucket_server_side_encryption_configuration" "source_backup_tokyo" {
  bucket = aws_s3_bucket.source_backup_tokyo.bucket

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

resource "aws_s3_bucket_versioning" "source_backup_tokyo" {
  bucket = aws_s3_bucket.source_backup_tokyo.id

  versioning_configuration {
    status = "Enabled"
  }
}

GitHub Actionsを実装する

うちの会社では main ブランチに最終的な成果物をマージするという運用になっているので、GitHubの main ブランチにマージをしたタイミングでバックアップ用のGutHub Actionsが自動的に発火するように実装をかけています。

ちなみに読んでいただければ分かる通りで、OpenID Connectを使うことによってIAMのアクセスキーやシークレットキーのような秘匿情報を使わなくても済むように実装をしています。

name: Backup Repository to S3

on:
  push:
    branches:
      - main

jobs:
  backup:
    runs-on: ubuntu-latest

    permissions:
      id-token: write
      contents: read

    env:
      AWS_REGION: ${{ vars.AWS_REGION }}
      AWS_ROLE_BACKUP_ARN: ${{ secrets.AWS_ROLE_BACKUP_ARN }}
      BUCKET_NAME: ${{ vars.BUCKET_NAME }}

    steps:
      - name: checkout
        uses: actions/checkout@v4

      - name: zip
        run: |
          REPO_NAME=${GITHUB_REPOSITORY#*/}
          git ls-files -z | xargs -0 zip "${REPO_NAME}.zip"

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          role-to-assume: ${{ env.AWS_ROLE_BACKUP_ARN }}
          role-session-name: GithubActions@${{ github.sha }}
          aws-region: ${{ env.AWS_REGION }}

      - name: Upload to S3
        run: |
          REPO_NAME=${GITHUB_REPOSITORY#*/}
          aws s3 cp "${REPO_NAME}.zip" "s3://${{ env.BUCKET_NAME }}/${REPO_NAME}.zip" --storage-class STANDARD --region $AWS_REGION

GitHubに環境変数を設定する

変数的な外に出せるものはできるだけ外出ししてしまいましょうと言うことで、varssecrets で定義されている変数はすべて環境変数に出してしまいます。

あとは、実際に何がしかのコードを実装して、main ブランチにマージをしてあげれば、以下のような形で自動的にコードをバックアップ先のS3バケットに aws s3 cp してくれるという仕組みになっています。

そもそも実装したコードをGitHub上のリポジトリに置いているのだから、そこまで考えなくてもいいんじゃないの? と言う話が漏れ聞こえてくるかもしれませんが、いざということを考えた時に、保険として資産であるコードをバックアップしておくというのは決して悪い話ではないのかなと思います。

それほど作業量を要する実装でもないので、ぜひ試してみてください。

カテゴリー: AWS, Work タグ: , , パーマリンク