[JAWS-UG CLI] ACM入門 #3 SES incomingの設定

これは<A HREF="http://qiita.com/zakky/items/29cf8095f6faa24f216b" target=_blank>AWS Certificate Manager (ACM)入門ハンズオン資料</A>の一部です。
最初から続けて行っている場合「0.準備」の各項は作業不要です。<A HREF="#1-ses-incoming用s3バケットの作成">第1項へ進んでください</A>。


前提条件
========

ドメインを取得済みであること。
Amazon SESでドメイン認証済みであること。


0. 準備
=======


0.1. リージョンの決定
---------------------

SESが東京リージョンには無いため、今回はバージニア(us-east-1)リージョンで作業します。

```bash:変数の設定:
export AWS_DEFAULT_REGION='us-east-1'
```

0.2. ドメイン名の変数への格納
---------------

変数へドメイン名を格納します。
ここでは example.tk とします。自分のドメイン名に読み替えてください。

```bash:コマンド:
DOMAINNAME="example.tk" && echo ${DOMAINNAME}
```

```text:結果(例):
      example.tk
```


1. SES Incoming用S3バケットの作成
=================

1.1. S3バケットの作成
-----------------

S3バケット名を ドメイン名.sesincoming とします。

```bash:コマンド:
SES_S3_BUCKET=${DOMAINNAME}.sesincoming
aws s3 mb s3://${SES_S3_BUCKET}
```
```text:結果(例):
      make_bucket: example.tk.sesincoming
```

1.2. S3バケットポリシーの作成
-----------------

SESがS3バケットへ書き込めるよう認証済みユーザを書き込み可能に設定します。
（このバケットは認証のために一時的に使用するため広範囲な権限設定でしのいでいますが、本番環境で使用する場合は権限を絞ってください）

バケットポリシーを定義するファイル名を s3-policy.json とします。

```bash:コマンド
FILE_S3_BUCKET_POLICY='s3-policy.json'
cat << EOF > ${FILE_S3_BUCKET_POLICY}
{
  "Version":"2012-10-17",
  "Statement":[{
      "Sid":"AddPerm",
      "Effect":"Allow",
        "Principal": "*",
      "Action":["s3:PutObject"],
      "Resource":["arn:aws:s3:::${SES_S3_BUCKET}/*"]
    }
  ]
}
EOF

cat ${FILE_S3_BUCKET_POLICY}
```
```text:結果(例):
      {
        "Version":"2012-10-17",
        "Statement":[{
            "Sid":"AddPerm",
            "Effect":"Allow",
              "Principal": "*",
            "Action":["s3:PutObject"],
            "Resource":["arn:aws:s3:::example.tk.sesincoming/*"]
          }
        ]
      }
```

JSONファイルを作成したら、フォーマットが壊れてないか必ず確認します。

```bash:コマンド:
jsonlint -q ${FILE_S3_BUCKET_POLICY}
```
```text:結果:
      返り値なし
```

1.3. S3バケットポリシーの適用
-----------------

```bash:コマンド:
aws s3api put-bucket-policy \
  --bucket ${SES_S3_BUCKET} \
  --policy file://${FILE_S3_BUCKET_POLICY}
```
```text:結果:
      返り値なし
```


1.4. S3バケットポリシーの確認
-----------------

```bash:コマンド:
aws s3api get-bucket-policy \
  --bucket ${SES_S3_BUCKET}
```
```text:結果(例):
      {
          "Policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"AddPerm\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:PutObject\",\"Resource\":\"arn:aws:s3:::example.tk.sesincoming/*\"}]}"
      }
```




2. SES Incomingの設定
=================

2.1. SES受信ルールセットの作成
-----------------

同名のルールセットが無いか確認します。
ルールセット名を S3spool とします。

```bash:コマンド:
SES_RULE_SET_NAME='S3spool'
aws ses describe-receipt-rule-set --rule-set-name ${SES_RULE_SET_NAME}
```
```text:結果:
      An error occurred (RuleSetDoesNotExist) when calling the DescribeReceiptRuleSet operation: Rule set does not exist: S3spool
```
このようにエラーが出るのが正しい状況です。
何か別の物が表示された場合は１行目 SES_RULE_SET_NAME 変数の値を適宜変更してやり直してください。

ルールセットの作成

```bash:コマンド:
aws ses create-receipt-rule-set --rule-set-name ${SES_RULE_SET_NAME}
```
```text:結果:
      返り値なし
```

ルールセットの確認

```bash:コマンド:
aws ses describe-receipt-rule-set --rule-set-name ${SES_RULE_SET_NAME}
```
```text:結果(例):
      {
          "Rules": [],
          "Metadata": {
              "CreatedTimestamp": "2016-10-12T07:41:42.030Z",
              "Name": "S3spool"
          }
      }
```

2.2. SES受信ルールの作成
-----------------

admin@ドメイン名 宛の電子メイルを受信したらS3バケットへ保存する受信ルールを作成します。
まずは電子メイルアドレスを変数へ格納します。

```bash:コマンド:
SES_RCPT="admin@${DOMAINNAME}" && echo ${SES_RCPT}
```
```text:結果(例):
      admin@example.tk
```

ルール名を S3spool-admin とします。
同名のルールが無いか確認します。

```bash:コマンド:
SES_RULE_NAME="S3spool-admin"
aws ses describe-receipt-rule \
         --rule-set-name ${SES_RULE_SET_NAME} \
         --rule-name ${SES_RULE_NAME}
```
```text:結果(例):
      An error occurred (RuleDoesNotExist) when calling the DescribeReceiptRule operation: Rule does not exist: S3spool-admin
```

このようにエラーが出るのが正しい状況です。
何か別の物が表示された場合は１行目 SES_RULE_NAME 変数の値を適宜変更してやり直してください。

次に、受信ルールを記載したJSONファイルを作成します。

```bash:コマンド:
cat << EOF > ses.json
{
        "Name": "${SES_RULE_NAME}",
        "Enabled": true,
        "TlsPolicy": "Optional",
        "Recipients": [
          "${SES_RCPT}"
        ],
        "Actions": [
          {
            "S3Action": {
              "BucketName": "${SES_S3_BUCKET}"
            }
          }
        ],
        "ScanEnabled": true
}
EOF
cat ses.json
```
```text:結果(例):
      {
              "Name": "S3spool-admin",
              "Enabled": true,
              "TlsPolicy": "Optional",
              "Recipients": [
                ""
              ],
              "Actions": [
                {
                  "S3Action": {
                    "BucketName": "example.tk.sesincoming"
                  }
                }
              ],
              "ScanEnabled": true
      }
```

JSONファイルを作成したら、フォーマットが壊れてないか必ず確認します。

```bash:コマンド:
jsonlint -q ses.json
```
```text:結果:
      返り値なし
```

SESへ受信ルールを作成します。

```bash:コマンド:
aws ses create-receipt-rule --rule-set-name ${SES_RULE_SET_NAME} \
         --rule ${SES_RULE_NAME} \
         --rule file://ses.json
```
```text:結果:
      返り値なし
```

受信ルールをアクティブにします。作成しただけでは無効でアクティブにする必要があります。

```bash:コマンド:
aws ses set-active-receipt-rule-set \
         --rule-set-name ${SES_RULE_SET_NAME}
```
```text:結果:
      返り値なし
```

設定内容の確認

```bash:コマンド:
aws ses describe-active-receipt-rule-set
```
```text:結果(例):
      {
          "Rules": [
              {
                  "Name": "S3spool-admin",
                  "Recipients": [
                      "admin@example.tk"
                  ],
                  "Enabled": true,
                  "ScanEnabled": true,
                  "Actions": [
                      {
                          "S3Action": {
                              "BucketName": "example.tk.sesincoming"
                          }
                      }
                  ],
                  "TlsPolicy": "Optional"
              }
          ],
          "Metadata": {
              "CreatedTimestamp": "2016-10-12T07:41:42.030Z",
              "Name": "S3spool"
          }
      }
```

出力結果を確認します。
Recipients に受信したい電子メイルアドレスがあるか、
Enabled と ScanEnabled が true になっているか、
BucketName に保存先のS3バケット名が書かれているか確認します。