Terraformのバックエンド用のS3バケットは、Terraformで管理してはいけない

新規にAWSアカウントを取得するにあたって、極力AWSリソースの管理はterraformに寄せようと思ったのだが、ふとterraformのtfstateファイルを置くS3は、terraform管理していいのか気になった。ので、調べてみた。

公式ソース

結論としてはタイトルどおりなわけだが、公式に言及されていた。

www.terraform.io

Terraform is an administrative tool that manages your infrastructure, and so ideally the infrastructure that is used by Terraform should exist outside of the infrastructure that Terraform manages.

雑にGoogle翻訳してみる。

Terraformはインフラストラクチャを管理する管理ツールです。したがって、Terraformで使用されるインフラストラクチャは、Terraformが管理するインフラストラクチャの外部に存在する必要があります。

というわけで、Terraformのバックエンド用のS3バケットを、Terraformの管理対象にするのはやめたほうがよさそう。

さらに読み進めると、次のように書いてある。

This can be achieved by creating a separate administrative AWS account which contains the user accounts used by human operators and any infrastructure and tools used to manage the the other accounts.

雑にGoogle翻訳してみる。

これは、人間のオペレータが使用するユーザアカウントと、他のアカウントを管理するために使用されるインフラストラクチャとツールを含む別の管理 AWSアカウントを作成することで実現できます。

Terraformのバックエンド用のS3バケットの管理をするためのアカウントを作れと言っている。AWS Organizationsと組み合わせればできそうである。

雑にS3バケットを作成する

AWS Organizationsを使えばできそうだが、それすらメンドウなら、雑にS3バケットを作ろう。もちろん、AWSコンソールから作ってもいいのだが、AWSアカウントを取得するたびにやることになるので、シェルスクリプト化しておく。

なお、これを動かすためには、事前にAWS CLIはインストールする必要がある。

#!/bin/sh

set -ex

BUCKET_NAME=$1
LEGION=${2:-ap-northeast-1}

# バケットの作成
# リージョンを指定しないとエラーになるので明示的に指定している
# https://dev.classmethod.jp/cloud/aws/jaws-ug-cli-1/
aws s3api create-bucket --bucket $BUCKET_NAME --create-bucket-configuration LocationConstraint=$LEGION

# バケットのバージョニング設定
# 何かやらかしたときに、復元できるようにしておく
aws s3api put-bucket-versioning --bucket $BUCKET_NAME --versioning-configuration Status=Enabled

# バケットのデフォルト暗号化設定
# http://tech.withsin.net/2017/12/05/s3-bucket-encryption/
aws s3api put-bucket-encryption --bucket $BUCKET_NAME --server-side-encryption-configuration '{
  "Rules": [
    {
      "ApplyServerSideEncryptionByDefault": {
        "SSEAlgorithm": "AES256"
      }
    }
  ]
}'

aws s3api get-bucket-location --bucket $BUCKET_NAME
aws s3api get-bucket-versioning --bucket $BUCKET_NAME
aws s3api get-bucket-encryption --bucket $BUCKET_NAME

適当にinit_terraform_bucket.shとかってファイルに保存して実行する。

./init_terraform_bucket.sh my-cloudtrail-bucket

これで、毎回ポチポチしなくても済むようになった。