第6回 The Twelve-Factor App on AWS & Django（AWSで初期設定をしようー後編）

# 目次
- [第1回 The Twelve-Factor App on AWS & Django（The Twelve-Factor Appとは）](https://qiita.com/satsuma0711/items/3b928d0e5670a633f9d8)
- [第2回 The Twelve-Factor App on AWS & Django（バックエンドAPIを作ろう）](https://qiita.com/satsuma0711/items/850d57ad1557d0f8dddb)
- [第3回 The Twelve-Factor App on AWS & Django（フロントエンドSPAを作ろう）](https://qiita.com/satsuma0711/items/67d35253a237c976415f)
- [第4回 The Twelve-Factor App on AWS & Django（AWSのアカウントを作成しよう）](https://qiita.com/satsuma0711/items/1482be82882652e6d314)
- [第5回 The Twelve-Factor App on AWS & Django（AWSで初期設定をしようー前編）](https://qiita.com/satsuma0711/items/6107113d33775f560fc3)
- 第6回 The Twelve-Factor App on AWS & Django（AWSで初期設定をしようー後編）　←　今回


# はじめに
[前回](https://qiita.com/satsuma0711/items/6107113d33775f560fc3)の記事で、アカウントや請求周りの設定を行い、アカウントの不正利用を防止できるよう設定しました。

今回はAWSの初期設定の後半として、AWSにいくつかあるセキュリティ関連のサービスを有効化して、セキュリティ対策を実施しましょう。AWSのマネジメントコンソールから設定することも可能ですが、できるだけAWSでの設定をコードとして残し管理しやすくしたいので、Terraformを使って設定したいと思います。

# IAMユーザーでクレデンシャルを発行
まず、TerraformからAWSを操作できるように、AWSへのアクセスキーを作成します。前回の記事で作成した管理者のIAMユーザー（admin）でAWSのマネジメントコンソールにログインします。

ログインできたら、右上のメニューから「Security credentials」をクリックします。

「My security credentials」画面に遷移するので、「Access keys for CLI, SDK, & API access」で「Create access key」ボタンをクリックします。

![credentials_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/d3d40278-a5d2-19e0-a1fc-3ecf9447d2c6.png)

アクセスキーとシークレットアクセスキーを発行できました。「Download .csv file」ボタンをクリックして、アクセスキーとシークレットアクセスキーを記載したCSVファイルをダウンロードします。なくさないよう、漏らさないよう厳重に管理しましょう。

![credentials_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/81afd333-fc7e-41f5-afdf-06ca28a9b5bd.png)

AWS CLIのインストールし、発行したアクセスキーとシークレットアクセスキーを識別しやすくなるよう名前つきプロファイルで設定します。

```
# AWS CLIをインストール
$ brew install awscli

# 名前付きプロファイルでアクセスキーとシークレットアクセスキーを設定
$ aws configure --profile [profile name]
AWS Access Key ID [None]: xxxxxxxxxx
AWS Secret Access Key [None]: xxxxxxxxxx
Default region name [None]: ap-northeast-1
Default output format [None]: json

# エラーなく実行できればインストール&設定完了
$ aws s3 ls --profile [profile name]
```

以上でPCからAWSへアクセスできるようになりました。

# Terraformのインストール

Terraformをインストールします。

```
# HashiCorpのHomeBrewパッケージを全て集めたリポジトリであるhashicorp/tapをインストール
$ brew tap hashicorp/tap

# Terraformをインストール
$ brew install hashicorp/tap/terraform

# バージョンを確認
$ terraform -v
Terraform v1.0.11
on darwin_amd64
```

Terraformのバージョンが表示できたら、インストールは完了になります。


# Terraformのtfstateファイルを配置するS3バケットを作成
Terraformは現在のAWSリソースの状態をtfstateファイルで保持していて、デフォルトではローカル環境にtfstateファイルを生成しますが、チーム開発の場合、チームで共有できるようにリモートに配置します。AWSではS3とDyanamoDBが選択できます。今回はS3に配置することにし、配置するためのS3バケットを作成します。

下記は自分の設定に書き換えて下さい。

```
[profile name]：アクセスキーとシークレットアクセスキーを指定した際のプロファイルの名前
[account id]：AWSのアカウントID
[bacuket name]：Terraformのtfstateファイルを配置するS3バケットの名前
```

自分の設定に書き換えてAWS CLIからS3バケットを作成します。

```
# 意図しないS3バケットの公開を防ぐために、アカウントのパブリックアクセスをブロックします
$ aws s3control put-public-access-block --profile [profile name] --account-id [account id] --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true

# バケットを作成します
$ aws s3api create-bucket --profile [profile name] --region ap-northeast-1 --bucket [bacuket name] --create-bucket-configuration LocationConstraint=ap-northeast-1

# バケットの暗号化を有効にします
$ aws s3api put-bucket-encryption --profile [profile name] --region ap-northeast-1 --bucket [bacuket name] --server-side-encryption-configuration "{\"Rules\": [{\"ApplyServerSideEncryptionByDefault\":{\"SSEAlgorithm\": \"AES256\"}}]}"

# バケットのバージョン管理を有効にします
$ aws s3api put-bucket-versioning --profile [profile name] --region ap-northeast-1 --bucket [bacuket name] --versioning-configuration Status=Enabled 
```

以上、S3バケットを作成して、Terraformを実行する準備が整いました。

# Terraformを使ってAWSのセキュリティサービスを有効化
Terraformを使ってAWSのセキュリティサービスを有効にします。

Terraformのフォルダ&ファイル構成は全体として最終的に以下になります。実際のソースは[Github](https://github.com/satsuma0711/sample-ecs-todo-app/tree/main/infrastructure/aws/terraform)にアップしました。

基本的にAWSリソースは環境ごとに同様な構成で構築することになると思うので、AWSリソースの定義は使い回しできるよう、`infrastructure/aws/terraform/modules`配下にリソースごとにフォルダを作成して定義しています。そして、環境ごとの設定は`infrastructure/aws/terraform/environments`配下に環境ごとにフォルダを作成して環境ごとに使用するリソースの定義を行い、modulesフォルダを呼び出して使い回しています。

```
sample-ecs-todo-app
├── backend
├── frontend
└── infrastructure
    └── aws
        └── terraform
            ├── environments
            │   ├── global
            │   │   ├── accessanalyzer-main.tf
            │   │   ├── config-main.tf
            │   │   ├── detective-main.tf
            │   │   ├── guardduty-main.tf
            │   │   ├── main.tf
            │   │   ├── providers.tf
            │   │   ├── securityhub-main.tf
            │   │   ├── terraform.log
            │   │   ├── terraform.tfvars
            │   │   └── variables.tf
            │   ├── dev
            │   │   └── main.tf
            │   │   └── variables.tf
            │   ├── stg
            │   │   └── main.tf
            │   │   └── variables.tf       
            │   └── prod
            │       └── main.tf
            │       └── variables.tf
            └── modules
                ├── accessanalyzer
                │   ├── main.tf
                │   └── variables.tf
                ├── cloudtrail
                │   ├── main.tf
                │   └── variables.tf
                ├── config
                │   ├── main.tf
                │   └── variables.tf
                ├── detective
                │   ├── main.tf
                │   └── variables.tf
                ├── guardduty
                │   ├── main.tf
                │   └── variables.tf
                └── s3
                    ├── bucket_policy.json
                    ├── main.tf
                    ├── outputs.tf
                    └── variables.tf
```

今回Terraformを使って有効化するAWSのセキュリティサービスは以下になります。簡単に説明したいと思います。

## AWS CloudTrail
AWSの監査サービスで、AWSのAPIへの操作ログを取得できます。90日以内であれば設定していなくても作成・変更・削除の操作ログを取得していますが、90日以上保持したい場合は「証跡」を作成することで全ての操作ログを保存できますので、基本的に設定しましょう。

そして、攻撃者はアカウントの保有者が普段使いしないリージョンでサーバーを立ち上げることが多いので、全てのリージョンで設定しましょう。

![cloudtrail_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/bf70ec1a-6512-32c6-d9cd-128c1659ee47.png)

## Amazon GuardDuty
AWSの驚異検出サービスでCloudTrailでのAPIコールログやVPC Flow Logsなどの通信ログを継続的に監視し不正な操作を自動的に検出します。具体的には例えば以下を検知できます。

- コインマイニング
- IAM Userの不正ログイン
- ポートスキャン

30日間は無料で利用でき、料金の見積もり機能もあるので、一旦有効化して料金が高かったら無効化すれば良いと思います。

![guardduty_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/ce981109-c387-98e8-aeb9-662dc422b7ca.png)

## AWS Config
AWSリソースの構成変更を追跡・監査する構成管理のサービスで、対象のAWSリソースの変更履歴を保存できます。

また、Configルールを使用することで、設定したルールにAWSリソースが準拠していることを継続的にモニタリングできます。例えば以下のルール

- AWSアカウントでAWS CloudTrailが有効になっている
- 使用中のセキュリティグループが、制限のないSSHトラフィックの着信を拒否している
- Amazon Elastic Block Store (EBS) の暗号化がデフォルトで有効になっている

があり、Configルールと修復アクション機能を組み合わせて設定することで通知したり自動で修復したりすることもできます。アカウント作成直後はConfigを有効化するだけで良いと思いますが、より厳密な運用が必要な場合はConfigルールや修復アクション機能の利用も検討しましょう。

![config_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/82989388-a2bb-da9d-b3c9-be8533787556.png)

## IAM Access Analyzer
AWSリソースに関連付いているポリシー（IAMポリシーやバケットポリシー）を検査し、外部からアクセスできるポリシーの有無を解析します。サポートしているAWSリソースは以下になります。

- Amazon Simple Storage Service バケット
- AWS Identity and Access Management ロール
- AWS Key Management Service キー
- AWS Lambda の関数とレイヤー
- Amazon Simple Queue Service キュー
- AWS Secrets Manager シークレット

新規または更新したポリシーを継続的に監視し、約30分以内に分析して解析結果を提示します。利用料金は無料なので、リージョンごとに設定する必要はありますが、積極的に利用しましょう。

![access-analyzer_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/10b1d97c-e3f9-71fe-e216-1aec49cc0ebc.png)


## Amazon Detective
不審なアクティビティを検知してからの分析や調査をより効率的に実施できるようにするサービスで、以下のログを解析します。

- (Amazon VPC) Flow Logs
- AWS CloudTrail ログ
- Amazon GuardDuty
- Amazon Elastic Kubernetes Service (Amazon EKS) 監査ログ

不審なアクティビティを検知して実際に調査を開始してもなかなかログが多いので根本原因にたどり着くまでに時間がかかってしまうことが多くあります。

しかし、Amazon Detectiveを使えば一覧で全体を確認し、詳細もドリルダウンすることで確認できます。30日間の無料トライアルと料金の見積もり機能もありますので、試しに使って許容範囲であれば是非利用しましょう。

![detective_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/c4999a7d-ca1f-4624-c963-4e7033502be8.png)

## AWS Security Hub
セキュリティのベストプラクティスによるチェックを行い、サービス横断的にセキュリティアラートを集約・一元管理し、重要度や推奨する対処方法を一覧で確認することができます。複数のサービスで発生したセキュリティアラートを別々に管理するのに比べて一元的に管理できるので作業を大幅に効率化できます。

有効なAWSサービスからのセキュリティアラートを取り込むので、AWS Config＆Amazon GuardDuty＆IAM Access Analyzerの有効化を初めに行う必要があります。

上記セキュリティサービスと同様、30日間の無料トライアルと料金の見積もり機能もありますので、試しに使って問題なければどんどん利用しましょう。

![securityhub_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/dd0117fc-48b5-667f-6a2e-6610b9183549.png)

## Terraformの実行
上記GithubからTerraformのファイルをコピーした場合、tfstateファイルの配置場所の設定を変更します。

```:infrastructure/aws/terraform/environments/global/main.tf
terraform {
  backend "s3" {
    bucket = "[上記で作成したS3バケット名]"
    key    = "[S3バケットにおけるtfstateファイルのパス]"
    region = "ap-northeast-1"
  }

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "3.75.1"
    }
  }
}
```

以上で準備が整いました。以下のコマンドを実行して上記AWSのセキュリティサービスを有効化して下さい。

```:bash
# ワークスペースの初期化（Terraformの必要なモジュールをダウンロードなど）
$ terraform init

# Terraformによる実行計画を参照
$ terraform plan

# tfファイルからAWSリソースを作成
$ terraform apply
```

前回と今回でAWSの初期設定とセキュリティ周りの設定が完了しました。次回以降は実際にアプリを運用するインフラの構築を行いたいと思います。