はじめに
お仕事で実装を行った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に環境変数を設定する
変数的な外に出せるものはできるだけ外出ししてしまいましょうと言うことで、vars
と secrets
で定義されている変数はすべて環境変数に出してしまいます。


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

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