[1hでできる]TerraformでS3バケットを作成し静的コンテンツを公開する手順

## はじめに
- TerraformでS3バケットを作成してコンテンツを公開する手順です。
- 前提条件はAWSを利用できることです。

## 目次
1. なにをするか
1. 手順

## なにをするか
- 本記事で対象としていないこと
-　S3バケットに自動で静的コンテンツをアップロードすること
-　静的コンテンツの作成（Nuxtの場合は、2章の"静的コンテンツをアップロードし公開"に記載しています。）

- 本記事で触れていること
-　Terraformをインストール 
-　プロバイダ(AWS)とプロファイルの設定
-　HCLでAWS S3の設定を記述
-　TerraformコマンドでAWSにS3を構築
-　静的コンテンツをアップロードし公開

## 手順
#### Terraformのインストール
Homebrewをインストール
```terminal
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
$ echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zshrc
$ source ~/.zshrc
$ brew -v
```

tfenvをインストール
→tfenvはterraformのバージョン管理ツール
→Homebrewみたいにzshにパス追加すると便利です。
```terminal
$ brew install tfenv
$ tfenv -v
```

Terraformをインストール
→バージョンは最新版を利用しよう（1.0.6は結構古い
```terminal
$ tfenv install 1.0.6
$ tfenv use 1.0.6
$ terraform -v
```

#### プロバイダ(AWS)とプロファイルの設定
aws-cliインストール
```terminal
$ brew install awscli
$ aws --version
```

IAMユーザを作成
→AWSコンソールからIAMユーザを作成してAdministratorAccessを付与する。
→アクセスキーとシークレットアクセスキーを発行する。

作成したIAMユーザの認証keyを登録する。
```terminal
$ aws configure --profile terraform-user
```
→対話型に入力を行い設定

sshキーを作成して権限を制限
```terminal
$ ssh-keygen -t rsa -f id_rsa_terraform
$ sudo chmod 600 id_rsa_terraform.pub
```

#### HCLでAWS S3の設定を記述
まず、基本的にTerraformでどんな設定をすれば良いか、その書き方は以下を参照する。以下はResource: aws_s3_bucketの設定方法を示している
>Terraform Registry Resource: aws_s3_bucket
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket


#### TerraformコマンドでAWSにS3を構築
同一ディレクトリで、code .でVScodeを開き、HCLでs3バケット作成および公開のためのtfを記述していきます。
HCLとは、HashiCorp(Terraformを提供している）によって作られた設定言語のことです。
```terraform:main.tf
module "s3" {
  source = "./module/s3"
}
```
```terraform:terraform.tf
terraform {
  required_version = ">= 0.15"

  required_providers {
    aws = ">=3.44.0"
  }
}

provider "aws" {
  region  = "AWSのリージョン"
  profile = "プロファイルを設定した(IAMユーザの認証Keyを登録した)ユーザ名"
}
```
```terraform:module/s3/aws_s3_bucket.tf

#今回は任意でnuxtappというリソース名とします。
#リソースはresourceブロック単位で設定します。
#構文としては、resource "<リースの種類>" "<リソース名>" {設定内容}となります。

resource "aws_s3_bucket" "nuxtapp" {
  bucket = "ayumu-sample-bucket"
}
resource "aws_s3_bucket_website_configuration" "nuxtapp-website" {
  bucket = aws_s3_bucket.nuxtapp.bucket
  index_document {
    suffix = "index.html"
  }
}
resource "aws_s3_bucket_ownership_controls" "nuxtapp-ownership-controls" {
  bucket = aws_s3_bucket.nuxtapp.id

  rule {
    object_ownership = "ObjectWriter"
  }
}
resource "aws_s3_bucket_acl" "nuxtapp-acl" {
  depends_on = [aws_s3_bucket_ownership_controls.nuxtapp-ownership-controls]
  bucket     = aws_s3_bucket.nuxtapp.id
  acl        = "public-read"
}
resource "aws_s3_bucket_public_access_block" "nuxtapp_public_access_block" {
  bucket                  = aws_s3_bucket.nuxtapp.id
  block_public_acls       = false
  block_public_policy     = false
  ignore_public_acls      = false
  restrict_public_buckets = false
}

resource "aws_s3_bucket_policy" "nuxtapp-policy" {
  bucket = aws_s3_bucket.nuxtapp.id
  policy = <<POLICY
{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Sid":"PublicReadGetObject",
      "Effect":"Allow",
      "Principal": "*",
      "Action":["s3:GetObject"],
      "Resource":["arn:aws:s3:::${aws_s3_bucket.nuxtapp.bucket}/*"]
    }
  ]
}
POLICY
}
```
aws_s3_bucket.tsでは、S3バケットを作成し、静的コンテンツをパブリックに公開する設定を記述しています。
具体的には、以下を設定しています。
- バケットの作成
- ホスティング設定
- ACLの設定
- バケットの公開設定
- バケットポリシーの設定


#### TerraformコマンドでAWSにS3を構築
つづいて、tfの記述が終わったので、Terraformコマンドを実行して環境を構築していきます。
```terraform
$ terraform init
```
Terraformプロジェクトを初期化します。つまり、使用するプロバイダ(例:AWS, Google Cloud, Azureなど)のプラグインをダウンロードし、必要な設定を行います。プロジェクトのセットアップ時に一度だけ実行すればよいです。
```terraform
$ terraform plan
```
Terraformがどのような操作を行うのかを示す"計画"を作成します。これはシミュレーションのようなもので、どのリソースが作成され、変更され、削除されるのかを確認できます。これにより、applyコマンドを実行する前に予期しない操作を避けることができます。
```terraform
$ terraform apply
```
このコマンドは、実際にインフラストラクチャを作成・更新・削除します。具体的には、planコマンドで表示された"計画"に従って操作を行います。このコマンドを実行すると、Terraformはあなたに計画の確認を求め、承認した場合のみ操作を実行します。

applyが通ったらAWSコンソールからS3を開き、バケットを見てみましょう。作成できてれいばokです。

#### 静的コンテンツをアップロードし公開
AWSコンソールからS3を開き、作成したバケットの設定を開き、静的コンテンツをアップロードします。
Nuxtのプロジェクトであれば、yarn generateコマンドで静的コンテンツ化(buildして)したものが、distディレクトリに作成されるので、distの中身をドラッグしてアップロードします。
アップロードが完了したらバケットのプロパティの最下部にホスティングコンテンツのURLが発行されているのでそちらを押下し、コンテンツにアクセスできれば完了となります。

ここまでで、タイトルにある”TerraformでS3バケットを作成しホスティングコンテンツを公開”が完了しました。

＜補足：作成物の削除＞
ちなみに、Terraformで作成したものは、以下のコマンドで削除できます。注意点は静的コンテンツは手動で削除する必要があります。AWSコンソールからS3を開いてアップロードしたコンテンツは削除しておきましょう。
```terraform
$ terraform destroy
```
実行したら、AWSコンソールで確認しましょう。削除できてたらokです。

## おわりに
- 最近、Terraformを触り始めたので良い勉強になりました。
- 他にもTerraformで色々試しましたが、とりあえず今回はS3の設定方法を残しておきます。
- 今後はGithub actionsと連携してコンテンツのアップロードまで自動化できるようにしたいです。