AWS Chinaを使う場合に注意すること

この記事は [DENSOアドベントカレンダー2020](https://qiita.com/advent-calendar/2020/denso) の4日目の記事です。

今年は仕事でAWS上で構築したものをAWS Chinaでも動作するようにする機会があったのですが、まあそれ自体情報が少ないのと、AWS ChinaとAWSの違いで苦労したので、今後挑戦する方のためにまとめておきます。

## はじめに
### AWS Chinaとは?
中国版のAWS
https://www.amazonaws.cn/en/about-aws/china/
なんですがAWSと似ているようでちょっと違います。

# AWS ChinaとAWSの違いについて
少なくとも以下の違いはありました
1. グローバルで展開されているサービスがAWS Chinaで提供されていないことがある
2. ARNの書きかたが違う
3. コスト管理系のサービスのリージョンが違う

## グローバルで展開されているサービスがAWS Chinaで提供されていないことがある
https://pages.awscloud.com/rs/112-TZM-766/images/H1-07.pdf
にもまとまっていますがAWS Chinaで使用できないサービスがある場合もあります

### 自分たちがすでに使用していたがAWS Chinaで使えなかったとサービスたち
他にもいろいろ違いがありますが
- AWS GuardDuty
- AWS Config のマネージドルールがない(guardduty-enabled-centralized,acm_certificate_expiration_check_enabled)

ちなみにAWS Chinaで提供されているサービスは[AWS Chinaのページ](https://www.amazonaws.cn/en/)から確認できます

## ARNの書きかたが違う
[ARNs for AWS services in China](https://docs.amazonaws.cn/en_us/aws/latest/userguide/ARNs.html)に記載があるように
に
グローバル:```aws```
AWS China:```aws-cn```
となる

###  ARNの書き方が違うせいでTerraform ではこんなエラーが出た
Terraformを使用して構築を自動化していたのですがこのARNの違いによってAWS Chinaでは構築エラーになりました。
以下具体的に遭遇したエラーです。

### ロググループの定義でエラー
```
Error: Error putting IAM role policy lambda_cost-explorer: MalformedPolicyDocument: Partition "aws" is not valid for resource "arn:aws:logs:cn-north-1:*:log-group:/aws/lambda/cost_explorer_slack_notification:*".
        status code: 400, request id: 0413d587-ef1b-43e9-b1dd-1c98ada10e2d
  on modules/cost_explorer/iam.tf line 31, in resource "aws_iam_role_policy" "lambda_for_cost_explorer":
  31: resource "aws_iam_role_policy" "lambda_for_cost_explorer" {
```

もともとのコード
例えばTerraformのコードが以下のようになっていた部分があったのですがこれらが全部AWS Chinaではエラーになりました。

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": ["arn:aws:logs:${var.region}:*:log-group:${aws_cloudwatch_log_group.cost_explorer_slack_notification.name}:*"],=>ここにawsと書いていた
      "Effect": "Allow"
    }
  ]
}

```

修正例

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": ["arn:*:logs:${var.region}:*:log-group:${aws_cloudwatch_log_group.cost_explorer_slack_notification.name}:*"], =>＊にしちゃう
      "Effect": "Allow"
    }
  ]
}
```

大半のサービスは上記置き換えで動作するようになったのですが、S3の定義についてはこのような置き換えではエラーになったりします。

### バケットポリシーでエラー
これはちょっとやっかいロググループみたいに*で置き換えたらエラーになる

```
Error: Error putting S3 policy: MalformedPolicy: Policy has invalid resource
        status code: 400, request id: 6774E20500A4AB30, host id: /6snJ2Mq7154TaCvqhOf5FAnOEFF6V92mgZKtRRRaS+PJo/59Aw3PMLhg7emCya6fHoWzk+6jtI=
  on modules/aws_config/main.tf line 15, in resource "aws_s3_bucket" "aws_config":
  15: resource "aws_s3_bucket" "aws_config" {
```

修正前(もともとのコード)

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AWSConfigBucketPermissionsCheck",
            "Effect": "Allow",
            "Principal": {
                "Service": "config.amazonaws.com"
            },
            "Action": "s3:GetBucketAcl",
            "Resource": ["arn:aws:s3:::${local.config_bucket}"]
        },
        {
            "Sid": "AWSConfigBucketDelivery",
            "Effect": "Allow",
            "Principal": {
                "Service": "config.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": ["arn:aws:s3:::${local.config_bucket}/AWSLogs/${var.account_id}/Config/*"],
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        }
    ]
}
```

こうしないと中国では動かない(ただこれでは中国でしか動かなくなる)

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AWSConfigBucketPermissionsCheck",
            "Effect": "Allow",
            "Principal": {
                "Service": "config.amazonaws.com"
            },
            "Action": "s3:GetBucketAcl",
            "Resource": ["arn:aws-cn:s3:::${local.config_bucket}"]
        },
        {
            "Sid": "AWSConfigBucketDelivery",
            "Effect": "Allow",
            "Principal": {
                "Service": "config.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": ["arn:aws-cn:s3:::${local.config_bucket}/AWSLogs/${var.account_id}/Config/*"],
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        }
    ]
}
```

修正例
バケットポリシーを後付にして作成したバケットからarnを取得するようにする。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AWSConfigBucketPermissionsCheck",
            "Effect": "Allow",
            "Principal": {
                "Service": "config.amazonaws.com"
            },
            "Action": "s3:GetBucketAcl",
            "Resource": ["${aws_s3_bucket.aws_config.arn}"]
        },
        {
            "Sid": "AWSConfigBucketDelivery",
            "Effect": "Allow",
            "Principal": {
                "Service": "config.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": ["${aws_s3_bucket.aws_config.arn}/AWSLogs/${var.account_id}/Config/*"],
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        }
    ]
}
```


### コスト管理系のサービスのリージョンが違う
コスト管理系のサービス(AWS Cost Explorerとか)はAWSだとバージニア北部(us-east-1)ですがAWS ChinaだとNingxia(cn-northwest-1)になります。
詳細は
https://docs.aws.amazon.com/general/latest/gr/billing.html
に記載されている通り
コスト通知の仕組みを実装していてる場合はリージョンが変わるので注意

# まとめ
AWS Chinaを使用する場合に困ったこと、注意すべきことをまとめました。
AWS Chinaを使用することになったときに参考になれば幸いです。