【ハンズオン】MWAAのプライベートネットワークアクセスモードの環境構築

# 背景
プロジェクトにおいてMWAA（Amazon Managed Workflows for Apache Airflow）をプライベートネットワークアクセスモードで構築する機会があったのですが、個人的に割とさらっと行かなかったので、記事にしました。  
CloudFormationの例とかはあるんですが、一旦GUIで一つ一つ組みながら何が必要なのか？それぞれの設定がどう関係しているのか？を知りたかったので、今回は基本GUIベース（2023/8/24時点のAWS management console）で記載しています。  
今回の構成は、VPCの構築～プライベートサブネットのWindowsサーバからAirflow UIが表示されるところまでを対象としています。  

# 構築時に自分がはまったところ
まあ結論から言うとちゃんとドキュメントを読めでしかなかったのですが・・・
- S3のVPCエンドポイントがGatewayタイプになっていなかった
- Airflow UIに接続するためのURLが分からなかった
- 検証用サーバからAirflow UIに接続するために、必要なロールが正しく付与されていなかった

# 構築構成
今回構築した環境の概要は以下の図に示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/15b127c7-0084-d3ee-9509-b82a7876ae69.png)

Airflow UIを参照するまでは以下の流れです。
1. インターネット経由でパブリックサブネット内の踏み台サーバへのRDP
1. プライベートサブネット内のWindows ServerにRDP
1. Airflow UI用のWebトークンを発行し、ブラウザで画面表示

# 構築とAirflowUI表示までの流れ
1. ネットワーク構成の作成
1. IAMロール・ポリシーの作成
1. EC2インスタンスの作成
1. S3の作成
1. MWAAの構築
1. AirflowUIのブラウザ表示

以下上記の流れに従って記載していきます。  
それぞれ各項目で作成するものがどのようにMWAAの環境構築に関わってくるのかも構築時の説明に別途記載していければと思います。
またMWAAのプライベートネットワークアクセスモードで構築する上で必須でなく、あくまでも今回の検証用の設定は項目ごとに「検証用」というマークを付けておきます。
なおVPC、サブネット、ルートテーブル、エンドポイントは[【AWS公式サイト】About networking on Amazon MWAA](https://docs.aws.amazon.com/mwaa/latest/userguide/networking-about.html#networking-about-overview-private)を参考にしています（Private routing without Internet accessの箇所）。

# ネットワーク構成の作成
## VPCの作成
まずは右上の「VPCを作成」ボタンを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/bfe02a6d-ad2b-d3cf-7df2-5c12449def16.png)
「VPCの設定」では以下を入力します。
|項目|内容|
|---|---|
|作成するリソース|VPCのみ|
|名前タグ|mwaa-test|
|IPv4 CIDR ブロック|IPv4 CIDR の手動入力|
|IPv4 CIDR|10.1.0.0/16|
|IPv6 CIDR ブロック|IPv6 CIDR ブロックなし|
|テナンシー|デフォルト|
「タグ」はデフォルトのままにします。
上記入力後、「VPCを作成」ボタンを選択します。
### DNSホスト名、DNS解決の有効化
次にVPC内での「DNSホスト名」、「DNS解決」が初期では無効になっているため有効化します。**この設定はMWAAのプライベートネットワークアクセスモードを作成する上でも必須ですし、VPCエンドポイント（Airflow UIのアクセスも含む）へのアクセス時に必要になってきます。**
作成したVPCにチェックを入れ、「アクション」>「VPCの設定を編集」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/461a8445-65cc-94b2-5a26-f9f8e0655d92.png)
「DNS設定」の項目にて以下のように設定し、最後に「保存」ボタンを選択します。
|項目|内容|
|---|---|
|DNS解決を有効化|チェックあり|
|DNSホスト名を有効化|チェックあり|

## サブネットの作成
次にサブネットを作成していきます。左側のメニューから「サブネット」を選択し、その後画面右上にある「サブネットを作成」を選択して、必要項目を入力し作成していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/6521377a-07b6-0fa6-d655-ec0e36a6d3de.png)
作成するサブネットは全部で3つで、各サブネットの設定は以下を参考に入力して作成していってもらえればと。すべて先ほど作成したVPC内に構築します。
※なおmwaa-test-public-aはあくまでも検証用に作成するものです。
**MWAAのプライベートネットワークアクセスモードの場合、NATGatewayが付与されていないプライベートサブネットが2つ必要で、それぞれ異なるアベイラビリティゾーンに作成する必要があります。**

|サブネット名|項目|内容|備考|
|---|---|---|---|
|mwaa-test-public-a（検証用）|VPC ID| vpc-xxxxxxx(mwaa-test) |カッコ付けで名前が書いてある|
|                  |サブネット名| mwaa-test-public-a | |
|                  |アベイラビリティーゾーン| ap-northeast-1a| |
|                  |IPv4 CIDR ブロック|10.1.1.0/24| |
|mwaa-test-private-a|サブネット名| mwaa-test-private-a | |
|                   |アベイラビリティーゾーン| ap-northeast-1a| |
|                   |IPv4 CIDR ブロック|10.1.2.0/24| |
|mwaa-test-private-c|サブネット名| mwaa-test-private-c | |
|                   |アベイラビリティーゾーン| ap-northeast-1c| |
|                   |IPv4 CIDR ブロック|10.1.3.0/24| |

## インターネットゲートウェイの作成（検証用）
またまた左のメニューから「インターネットゲートウェイ」を選択し、表示された画面の右上にある「インターネットゲートウェイの作成」を選択して、インターネットケートウェイを作成していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/f8899e38-f30d-365c-50e7-c7c2ffb88977.png)
インターネットゲートウェイ作成時に入力する内容は以下の通りです。
|項目|内容|
|---|---|
|名前タグ|mwaa-test-igw|

次に作成したインターネットゲートウェイをVPCにアタッチします。
「アクション」>「VPCにアタッチ」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/c536f0bc-e92c-3823-1d59-01d6687d9647.png)
「使用可能なVPC」の箇所にカーソルを充てると、作成したVPC（mwaa-test）が表示されるため、「vpc-xxxxxx - mwaa-test」を選択します。その後「インターネットゲートウェイのアタッチ」ボタンを選択します。

## ルートテーブルの作成
#### パブリックサブネット用ルートテーブル（検証用）
パブリックサブネット用にインターネットゲートウェイへのルートテーブルを作成し、mwaa-test-public-a（パブリックサブネット）に設定します。
画面左のメニューの「ルートテーブル」を選択後、表示された画面右上の「ルートテーブルを作成」を選択します。
以下の設定内容を入力し、最後に「ルートテーブル作成」ボタンを選択します。
|項目|内容|
|---|---|
|名前|mwaa-test-public-rt|
|VPC|vpc-xxxxxx(mwaa-test)|

次にルートテーブルの一覧から、「mwaa-test-public-rt」を選択し、「アクション」>「ルートを編集」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/c7e5995d-2879-ce64-8747-12c6555a71e6.png)
「ルートを追加」ボタンを選択し、以下の項目をそれぞれ入力後、最後に「変更を保存」ボタンを選択します。

|項目|内容|
|---|---|
|送信先|0.0.0.0/0|
|ターゲット|igw-xxxxxx(mwaa-test-igw)|

作成したルートテーブルをサブネットに紐づけます。
「mwaa-test-public-rt」を選択し、「アクション」>「サブネットの関連付けを編集」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/dc787abb-6880-718b-ebc8-6e1c3a2167e7.png)
その後、先ほど作成したサブネットが3つ表示されるので、「mwaa-test-public-a」にチェックを入れ、「関連付けを保存」ボタンを選択します。

#### プライベートサブネット用ルートテーブル
パブリックサブネット用ルートテーブルと同様にプライベートサブネット用のルートテーブルも作成します。
各種設定内容は以下の通りです。ルートはデフォルトのままで追加はしません。
|項目|内容|
|---|---|
|名前|mwaa-test-private-rt|
|VPC|vpc-xxxxxx(mwaa-test)|

パブリックサブネット用のルートテーブルと同様に、ルートテーブルをサブネットに紐づけするため、再度「サブネット」の画面を開き「mwaa-test-private-c」を選択後、「アクション」>「ルートテーブルの関連付けを編集」を選択し、「mwaa-test-private-rt」に変更します。「mwaa-test-private-a」サブネットも同様のルートテーブルの変更をします。

## セキュリティグループの作成
次に上記の検索バーに「EC2」と入力し、サービスから「EC2」のメニューを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/2d567c5b-5a8e-6c43-2256-46a19b2cce3a.png)
左側のメニューから「ネットワーク&セキュリティ」の分類内にある「セキュリティグループ」を選択します。
画面右上にある「セキュリティグループを作成」ボタンを選択し、必要なセキュリティグループをいくつか作成していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/45fd8af4-b954-1810-975c-7738b4f6cc96.png)
#### MWAA用セキュリティグループ
##### 基本的な詳細
|項目|内容|
|---|---|
|セキュリティグループ名|airflow-sg|
|説明|Security Group for MWAA|
|VPC|vpc-xxxxx(mwaa-test)|
##### インバウンドルール
| タイプ | プロトコル | ポート範囲 | ソース | 説明-オプション |
| --- | --- | --- | --- | --- |
| すべてのトラフィック | すべて | すべて | airflow-sg（sg-xxxx） |  |

アウトバウンドルールはデフォルトのまま

※上記は自分自身をソースとするため、一度暫定的にソースを指定して作成後、インバウンドルールを修正することで作成が可能です。

#### VPC内部用セキュリティグループ
##### 基本的な詳細
|項目|内容|
|---|---|
|セキュリティグループ名|vpc-internal-sg|
|説明|Security Group for VPC internal|
|VPC|vpc-xxxxx(mwaa-test)|
##### インバウンドルール
| タイプ | プロトコル | ポート範囲 | ソース | 説明-オプション |
| --- | --- | --- | --- | --- |
| すべてのトラフィック | すべて | すべて | 10.1.0.0./16 |  |

アウトバウンドルールはデフォルトのまま

#### 踏み台サーバ用セキュリティグループ
##### 基本的な詳細
|項目|内容|
|---|---|
|セキュリティグループ名|public-sg|
|説明|Security Group for bastion server|
|VPC|vpc-xxxxx(mwaa-test)|
##### インバウンドルール
| タイプ | プロトコル | ポート範囲 | ソース | 説明-オプション |
| --- | --- | --- | --- | --- |
| RDP | TCP | 3389 | マイIP |  |

アウトバウンドルールはデフォルトのまま

## VPCエンドポイントの作成
画面左上の検索バーに「VPC」と入力し、「サービス」内に表示された「VPC」メニューを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/ce6e28a3-b500-ed07-9cc2-5c964179cd62.png)
左メニューの「仮想プライベートクラウド」>「エンドポイント」を選択します。また表示された画面の右上にある「エンドポイントを作成」ボタンを選択します。
※合計9個のVPCエンドポイントを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/21ff8976-f94a-5fa0-8a78-04dca8ad375f.png)

各VPCエンドポイントの設定は以下の通りです。
作成するエンドポイントは[【AWS公式サイト】Creating the required VPC service endpoints in an Amazon VPC with private routing](https://docs.aws.amazon.com/mwaa/latest/userguide/vpc-vpe-create-access.html#vpc-vpe-create-view-endpoints-examples)を参考にしています。
|分類|項目|内容|
|---|---|---|
|CloudWatch|名前タグ|vpc-endpoint-to-CloudWatch|
| | サービスカテゴリ | AWSのサービス |
| | サービス | com.amazonaws.ap-northeast-1.monitoring |
| | VPC | vpc-xxxxxx (mwaa-test) |
| | サブネット | ap-northeast-1a |
| | サブネットID | mwaa-test-private-a |
| | サブネット | ap-northeast-1c |
| | サブネットID | mwaa-test-private-c |
| | セキュリティグループ | vpc-internal-sg |
| | ポリシー | フルアクセス |
|CloudWatchLogs|名前タグ|vpc-endpoint-to-CloudWatchLogs|
| | サービスカテゴリ | AWSのサービス |
| | サービス | com.amazonaws.ap-northeast-1.logs |
| | VPC | vpc-xxxxxx (mwaa-test) |
| | サブネット | ap-northeast-1a |
| | サブネットID | mwaa-test-private-a |
| | サブネット | ap-northeast-1c |
| | サブネットID | mwaa-test-private-c |
| | セキュリティグループ | vpc-internal-sg |
| | ポリシー | フルアクセス |
|ECR-api|名前タグ|vpc-endpoint-to-ECR-api|
| | サービスカテゴリ | AWSのサービス |
| | サービス | com.amazonaws.ap-northeast-1.ecr.api |
| | VPC | vpc-xxxxxx (mwaa-test) |
| | サブネット | ap-northeast-1a |
| | サブネットID | mwaa-test-private-a |
| | サブネット | ap-northeast-1c |
| | サブネットID | mwaa-test-private-c |
| | セキュリティグループ | vpc-internal-sg |
| | ポリシー | フルアクセス |
|ECR-dkr|名前タグ|vpc-endpoint-to-ECR-dkr|
| | サービスカテゴリ | AWSのサービス |
| | サービス | com.amazonaws.ap-northeast-1.ecr.dkr |
| | VPC | vpc-xxxxxx (mwaa-test) |
| | サブネット | ap-northeast-1a |
| | サブネットID | mwaa-test-private-a |
| | サブネット | ap-northeast-1c |
| | サブネットID | mwaa-test-private-c |
| | セキュリティグループ | vpc-internal-sg |
| | ポリシー | フルアクセス |
|KMS|名前タグ|vpc-endpoint-to-KMS|
| | サービスカテゴリ | AWSのサービス |
| | サービス | com.amazonaws.ap-northeast-1.kms |
| | VPC | vpc-xxxxxx (mwaa-test) |
| | サブネット | ap-northeast-1a |
| | サブネットID | mwaa-test-private-a |
| | サブネット | ap-northeast-1c |
| | サブネットID | mwaa-test-private-c |
| | セキュリティグループ | vpc-internal-sg |
| | ポリシー | フルアクセス |
|S3|名前タグ|vpc-endpoint-to-S3|
| | サービスカテゴリ | AWSのサービス |
| | サービス | com.amazonaws.ap-northeast-1.s3 **※Gatewayタイプのものを選択すること** |
| | VPC | vpc-xxxxxx (mwaa-test) |
| | ルートテーブル | mwaa-test-private-rt |
| | ポリシー | フルアクセス |
|AirflowAPI|名前タグ|vpc-endpoint-to-airflowapi|
| | サービスカテゴリ | AWSのサービス |
| | サービス | com.amazonaws.ap-northeast-1.airflow.api |
| | VPC | vpc-xxxxxx (mwaa-test) |
| | サブネット | ap-northeast-1a |
| | サブネットID | mwaa-test-private-a |
| | サブネット | ap-northeast-1c |
| | サブネットID | mwaa-test-private-c |
| | セキュリティグループ | vpc-internal-sg |
| | ポリシー | フルアクセス |
|AirflowEnv|名前タグ|vpc-endpoint-to-airflowenv|
| | サービスカテゴリ | AWSのサービス |
| | サービス | com.amazonaws.ap-northeast-1.airflow.env |
| | VPC | vpc-xxxxxx (mwaa-test) |
| | サブネット | ap-northeast-1a |
| | サブネットID | mwaa-test-private-a |
| | サブネット | ap-northeast-1c |
| | サブネットID | mwaa-test-private-c |
| | セキュリティグループ | vpc-internal-sg |
| | ポリシー | フルアクセス |
|AirflowOps|名前タグ|vpc-endpoint-to-airflowops|
| | サービスカテゴリ | AWSのサービス |
| | サービス | com.amazonaws.ap-northeast-1.airflow.ops |
| | VPC | vpc-xxxxxx (mwaa-test) |
| | サブネット | ap-northeast-1a |
| | サブネットID | mwaa-test-private-a |
| | サブネット | ap-northeast-1c |
| | サブネットID | mwaa-test-private-c |
| | セキュリティグループ | vpc-internal-sg |
| | ポリシー | フルアクセス |

※なおAirflow UIへのVPCエンドポイントはMWAA作成時に自動的に作られます。

# IAMロール・ポリシーの作成
IAMロール・ポリシーの作成は[【AWS公式サイト】Amazon MWAA 環境へのアクセス](https://docs.aws.amazon.com/ja_jp/mwaa/latest/userguide/access-policies.html#web-ui-access)を参考にしています。特にPolicyは記載のものを参考にしており、一部自分の環境ように修正しているだけです。

画面左上の検索バーに「IAM」と入力し、「サービス」に表示された「IAM」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/98f15e7a-244c-ffa9-a14c-3f48dfc94eb8.png)
## IAM Policyの作成
### AirflowのWebServerアクセス用ポリシー
左メニューの「アクセス管理」>「ポリシー」を選択し、画面右上の「ポリシーを作成」ボタンを選択します。
「ポリシーエディタ」にて「JSON」を選択し、以下のJSONを入力します。
※なおResource内に記載のある[AWSアカウントID]はそれぞれのAWSアカウントIDに書き換えて下さい。MWAA-Testは、この後「MWAAの構築」で作成するMWAAの名前を記載します。また一番最後のAdminは「Admin、Op、User、ViewerまたはPublic」のうちのロールを記載していまして、今回は一旦Adminとしています。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "airflow:CreateWebLoginToken",
            "Resource": [
                "arn:aws:airflow:ap-northeast-1:[AWSアカウントID]:role/MWAA-Test/Admin"
            ]
        }
    ]
}
```
「次へ」ボタンを選択後、「ポリシー名」は「AmazonMWAAWebServerAccess」、「説明」は「AmazonMWAAWebServerAccess」を入力し、最後に「ポリシーの作成」ボタンを選択します。

### MWAA APIアクセス用ポリシー
左メニューの「アクセス管理」>「ポリシー」を選択し、画面右上の「ポリシーを作成」ボタンを選択します。
「ポリシーエディタ」にて「JSON」を選択し、以下のJSONを入力します。
「"Resource":"arn:aws:kms:\*:[AWSアカウントID]:key/\*"」の箇所は、それぞれのAWSアカウントIDに書き換えて下さい。
※MWAAで利用するKMSキーが定まっている場合、「"Resource":"arn:aws:kms:\*:[AWSアカウントID]:key/\*"」の箇所は「"Resource":"arn:aws:kms:\*:[AWSアカウントID]:key/[キーID]"」を記載して、特定のキーだけのみへのアクセスとします。

```
{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Effect":"Allow",
         "Action":"airflow:*",
         "Resource":"*"
      },
      {
         "Effect":"Allow",
         "Action":[
            "iam:PassRole"
         ],
         "Resource":"*",
         "Condition":{
            "StringLike":{
               "iam:PassedToService":"airflow.amazonaws.com"
            }
         }
      },
      {
         "Effect":"Allow",
         "Action":[
            "iam:CreateServiceLinkedRole"
         ],
         "Resource":"arn:aws:iam::*:role/aws-service-role/airflow.amazonaws.com/AWSServiceRoleForAmazonMWAA"
      },
      {
         "Effect":"Allow",
         "Action":[
            "ec2:DescribeSecurityGroups",
            "ec2:DescribeSubnets",
            "ec2:DescribeVpcs",
            "ec2:DescribeRouteTables"
         ],
         "Resource":"*"
      },
      {
         "Effect":"Allow",
         "Action":[
            "kms:DescribeKey",
            "kms:ListGrants",
            "kms:CreateGrant",
            "kms:RevokeGrant",
            "kms:Decrypt",
            "kms:Encrypt",
            "kms:GenerateDataKey*",
            "kms:ReEncrypt*"
         ],
         "Resource":"arn:aws:kms:*:[AWSアカウントID]:key/*"
      },
      {
         "Effect":"Allow",
         "Action":[
            "s3:GetEncryptionConfiguration"
         ],
         "Resource":"arn:aws:s3:::*"
      },
      {
         "Effect":"Allow",
         "Action":"ec2:CreateVpcEndpoint",
         "Resource":[
            "arn:aws:ec2:*:*:vpc-endpoint/*",
            "arn:aws:ec2:*:*:vpc/*",
            "arn:aws:ec2:*:*:subnet/*",
            "arn:aws:ec2:*:*:security-group/*"
         ]
      },
      {
         "Effect":"Allow",
         "Action":[
            "ec2:CreateNetworkInterface"
         ],
         "Resource":[
            "arn:aws:ec2:*:*:subnet/*",
            "arn:aws:ec2:*:*:network-interface/*"
         ]
      }
   ]
}
```
「次へ」ボタンを選択後、「ポリシー名」は「AmazonMWAAFullApiAccess」、「説明」は「AmazonMWAAFullApiAccess」を入力し、最後に「ポリシーの作成」ボタンを選択します。

## IAM Roleの作成
画面左側のメニューにて「アクセス管理」>「ロール」を選択します。
その後画面右上にある「ロールを作成」ボタンを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/e0f3f656-e613-33c7-8d77-c52e69dd435f.png)

作成するロールの内容は以下の通りです。
先ほど作成した2つのポリシーをロールに紐づけ、この後作成するEC2インスタンスのロールとします。

|項目|内容|
|---|---|
|信頼されたエンティティタイプ|AWSのサービス|
|ユースケース|一般的なユースケース（EC2）|
|許可ポリシー|AmazonMWAAFullApiAccess, AmazonMWAAWebServerAccess|
|ロール名|MWAA-Test-Role|
|説明|Role for Airflow UI access|
|ステップ 1: 信頼されたエンティティを選択する|デフォルトのまま|
|ステップ 2: 許可を追加する|AmazonMWAAFullApiAccess, AmazonMWAAWebServerAccess|

上記を入力後、「ロールを作成」ボタンを選択します。

# EC2インスタンスの作成（検証用）
画面左上の検索バーに「EC2」と入力し、「サービス」に表示された「EC2」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/4bec7c29-8509-f9ed-0db9-aa10ca2ba44c.png)
左側のメニューの「インスタンス」>「インスタンス」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/34d049a7-dffa-091b-2ca9-3ca2413590a7.png)
画面右上にある「インスタンスの起動」ボタンを選択し、以下の2台のサーバを作成していきます。

### 踏み台サーバの作成
入力内容は以下の通りです。入力後「インスタンスを起動」ボタンを選択します。
|項目|内容|
|---|---|
|名前|Public-bastion|
|OSイメージ|Microsoft Windows Server 2022 Base|
|インスタンスタイプ|t2.micro|
|キーペア名|任意|
|VPC|vpc-xxxxx(mwaa-test)|
|サブネット|mwaa-test-public-a|
|パブリックIPの自動割り当て|有効化|
|ファイアウォール（セキュリティグループ）|既存のセキュリティグループを選択する|
|共通のセキュリティグループ|public-sg|
|ストレージを設定|1x 30 GiB gp2|

### 検証用サーバの作成
入力内容は以下の通りです。入力後「インスタンスを起動」ボタンを選択します。
|項目|内容|
|---|---|
|名前|Private-Windows-Server|
|OSイメージ|Microsoft Windows Server 2022 Base|
|インスタンスタイプ|t2.micro|
|キーペア名|任意|
|VPC|vpc-xxxxx(mwaa-test)|
|サブネット|mwaa-test-private-a|
|パブリックIPの自動割り当て|無効化|
|ファイアウォール（セキュリティグループ）|既存のセキュリティグループを選択する|
|共通のセキュリティグループ|vpc-internal-sg|
|ストレージを設定|1x 30 GiB gp2|

# S3バケット及びフォルダの作成
画面左上の検索バーに「S3」と入力し、「サービス」に表示された「S3」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/1ec18676-c3a8-4cd2-286e-788e11f5dac1.png)
画面右上にある「バケットを作成」ボタンを選択します。
以下の項目を入力後、最後に「バケットを作成」ボタンを選択します。
| 項目 | 内容 |
| --- | --- |
|バケット名|mwaa-test-bucket-[AWSアカウントID]|
|AWSリージョン|ap-northeast-1|
|オブジェクト所有者|ACL無効（推奨）|
|このバケットのブロックパブリックアクセス設定|「パブリックアクセスをすべて ブロック」にチェック|
|バケットのバージョニング|「無効にする」にチェック|
|暗号化タイプ|「SSE-S3」にチェック|
|バケットキー|「有効にする」にチェック|

バケット作成後、「フォルダの作成」ボタンを選択し、dagsという名前のフォルダを作成します。

# MWAAの構築
画面左上の検索バーに「MWAA」と入力し、「サービス」に表示された「マネージドApache Airflow」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211031/856c31c0-3992-84ca-01c3-f71fab786a3c.png)
画面右上に表示された、「環境を作成」ボタンを選択します。
各項目ごとに以下の内容を入力し、MWAAを構築します。
|項目|内容|
|---|---|
|名前|MWAA-Test|
|Airflowバージョン|2.6.3|
|週 1 回のメンテナンスウィンドウ開始 (UTC)|任意|
|S3 バケット|s3://mwaa-test-bucket-[AWSアカウントID]|
|DAGフォルダ|s3://mwaa-test-bucket-[AWSアカウントID]/dags|
|プラグインファイル-オプション |入力なし|
|要件ファイル - オプション |入力なし|
|スタートアップスクリプトファイル - オプション |入力なし|
|Virtual Private Cloud (VPC)|vpc-xxxxxx (mwaa-test)|
|サブネット 1|mwaa-test-private-c|
|サブネット 2|mwaa-test-private-a|
|ウェブサーバーのアクセス|「非公開ネットワーク (インターネットアクセスなし)」にチェック|
|新しいセキュリティグループを作成|チェックを外す|
|Existing security group(s)|sg-xxxxx (airflow-sg)|
|環境クラス| mw1.small |
|最大ワーカー数| 10|
|最小ワーカー数| 1|
|スケジューラ数| 2|
|暗号化設定をカスタマイズする (高度)|未チェック状態にする|
|モニタリング|デフォルトのまま|
|実行ロール|新しいロールを作成|
|ロール名|デフォルトで表示されたものそのまま|

※基本ここに記載されていないものはなければ、デフォルトのまま設定しています。
最後に「環境を作成」ボタンを選択します。

# AirflowUIのブラウザ表示
1. （操作端末：ローカルPC）AWS CLIのダウンロード
ローカルPC上で、https://awscli.amazonaws.com/AWSCLIV2.msiにアクセスし、windows用のインストーラをダウンロードします。
1. （操作端末：ローカルPC）リモートデスクトップ用の
1. （操作端末：ローカルPC）パブリックサブネット内の踏み台サーバへRDPにてアクセスします。
    - 事前にAWSマネジメントコンソールのEC2の「接続」から「RDPクライアント」にある「リモートデスクトップファイルのダウンロード」をローカルPCにダウンロードしておく。
1. （操作端末：踏み台サーバ）プライベートサブネット内の検証用サーバへRDPにてアクセスします。
    - 事前にAWSマネジメントコンソールのEC2の「接続」から「RDPクライアント」にある「リモートデスクトップファイルのダウンロード」をローカルPCにダウンロードしておき、そのファイルをコピー&ペーストで踏み台サーバ上に配置します。
1. （操作端末：検証用サーバ）ローカルPCにあるAWSCLIV2.msiファイルをコピー&ペーストで検証用サーバに格納し、検証用サーバにAWS CLIをインストールします。
1. （操作端末：検証用サーバ）Powershellを起動し、「aws mwaa create-web-login-token --name MWAA-Test」コマンドを実行します。
1. 出力結果の内容から、「https://[WebServerHostname]/aws_mwaa/aws-console-sso?login=true#[WebToken]」という形式でURLを作成し、Webブラウザ上でアクセスすると、Airflowの画面が表示されます。
    - [WebServerHostName]や[WebToken]の内容は、コマンド実行時にJSON形式で出てくるのでダブルクォーテーションなしで置き換えてください。
    - 上記めんどいので以下のようなバッチファイルでURLを作成し、自動的にブラウザを開いてくれるバッチファイルを作りました。
```bat
@echo off
for /f "usebackq" %%i in (`"aws mwaa create-web-login-token --name Resona-MWAA-Test --query WebServerHostname"`) do set WEBSERVERHOSTNAME=%%~i
for /f "usebackq" %%i in (`"aws mwaa create-web-login-token --name Resona-MWAA-Test --query WebToken"`) do set WEBTOKEN=%%~i
start https://%WEBSERVERHOSTNAME%/aws_mwaa/aws-console-sso?login=true#%WEBTOKEN%
pause
```

# 補足
MWAA構築時に実行ロールを作成する設定にしているが、自動作成されたロールとそれに紐づくポリシーは以下のようなものとなっています。

- 名前：AmazonMWAA-MWAA-Test-OJPTQl
- 許可ポリシー：MWAA-Execution-Policy-302dd443-37a6-4f30-8e83-9a97f1c8b44b
- 許可ポリシーの詳細
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "airflow:PublishMetrics",
            "Resource": "arn:aws:airflow:ap-northeast-1:[AWSアカウントID]:environment/MWAA-Test"
        },
        {
            "Effect": "Deny",
            "Action": "s3:ListAllMyBuckets",
            "Resource": [
                "arn:aws:s3:::mwaa-test-bucket-[AWSアカウントID]",
                "arn:aws:s3:::mwaa-test-bucket-[AWSアカウントID]/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject*",
                "s3:GetBucket*",
                "s3:List*"
            ],
            "Resource": [
                "arn:aws:s3:::mwaa-test-bucket-[AWSアカウントID]",
                "arn:aws:s3:::mwaa-test-bucket-[AWSアカウントID]/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:CreateLogGroup",
                "logs:PutLogEvents",
                "logs:GetLogEvents",
                "logs:GetLogRecord",
                "logs:GetLogGroupFields",
                "logs:GetQueryResults"
            ],
            "Resource": [
                "arn:aws:logs:ap-northeast-1:[AWSアカウントID]:log-group:airflow-MWAA-Test-*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:DescribeLogGroups"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": "cloudwatch:PutMetricData",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "sqs:ChangeMessageVisibility",
                "sqs:DeleteMessage",
                "sqs:GetQueueAttributes",
                "sqs:GetQueueUrl",
                "sqs:ReceiveMessage",
                "sqs:SendMessage"
            ],
            "Resource": "arn:aws:sqs:ap-northeast-1:*:airflow-celery-*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "kms:Decrypt",
                "kms:DescribeKey",
                "kms:GenerateDataKey*",
                "kms:Encrypt"
            ],
            "NotResource": "arn:aws:kms:*:[AWSアカウントID]:key/*",
            "Condition": {
                "StringLike": {
                    "kms:ViaService": [
                        "sqs.ap-northeast-1.amazonaws.com"
                    ]
                }
            }
        }
    ]
}
```

# 参考
## MWAA環境構築
- https://docs.aws.amazon.com/mwaa/latest/userguide/networking-about.html#networking-about-overview-private
- https://docs.aws.amazon.com/mwaa/latest/userguide/vpc-vpe-create-access.html#vpc-vpe-create-view-endpoints-examples

## Amazon MWAAのWeb管理画面へのログイン
- https://blog.serverworks.co.jp/mwaa-network
- https://docs.aws.amazon.com/ja_jp/mwaa/latest/userguide/call-mwaa-apis-web.html