TerraformでAmazon API Gatewayを構築する(リソースポリシー編)


はじめに

API Gateway+Terraform記事第4弾。
TerraformのAWSプロバイダの3.16.0で2020/11/18にリソースポリシーの Terraform リソースが使えるようになったので、今回は、IPアドレスによる制限をさっそく試してみる。

Terraform

とはいっても、普通にIAMポリシーを書くだけである。

Condition(IpAddress)を使って許可をしてするよう、こんな感じで定義しよう。

resource "aws_api_gateway_rest_api_policy" "test" {
  rest_api_id = aws_api_gateway_rest_api.test.id
  policy      = data.aws_iam_policy_document.test.json
}

data "aws_iam_policy_document" "test" {
  statement {
    effect = "Allow"

    principals {
      type = "*"
      identifiers = [
        "*",
      ]
    }

    actions = [
      "execute-api:Invoke",
    ]

    resources = [
      "arn:aws:execute-api:${data.aws_region.current.name}:${data.aws_caller_identity.self.account_id}:${aws_api_gateway_rest_api.test.id}/*",
    ]

    condition {
      test     = "IpAddress"
      variable = "aws:SourceIp"

      values = [
        "xxx.xxx.xxx.xxx/32",
      ]
    }
  }
}

なお、resources の部分については、AWS公式の開発者ガイドでは、execute-api:/[ステージ名]/[メソッド]/[リソース名] にすれば良い感じに ARN に変換してくれるよ、と書いてあるのだが、良い感じに変換してもらえるがために、毎回 Terraform の差分として検出されるようになってしまうため、素直に↑のように ARN 形式で書いておこう。

"*" の部分については、上記の通り [ステージ名]/[メソッド]/[リソース名] で書くことも可能。

これで許容されていないIPアドレスでアクセスすると、

{"Message":"User: anonymous is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:ap-northeast-1:************:xxxxxxxxxx/prod/GET/xxxxxxxx"}

な感じでエラーが応答される。

アクセスログを設定している場合は、以下のように 403 応答を返したログが出力される。

{
    "requestId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "ip": "xxx.xxx.xxx.xxx",
    "caller": "-",
    "user": "-",
    "requestTime": "26/Nov/2020:13:51:55 +0000",
    "httpMethod": "GET",
    "resourcePath": "/xxxxxxxx",
    "path": "/prod/xxxxxxxx",
    "status": "403",
    "protocol": "HTTP/1.1",
    "responseLength": "168",
    "integrationLatency1": "-",
    "integrationRequestId": "-",
    "integrationStatus1": "-",
    "integrationErrorMessage": "-",
    "integrationLatency2": "-",
    "integrationStatus2": "-",
    "responseLatency": "1",
    "errorMessage": "User: anonymous is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:ap-northeast-1:************:xxxxxxxxxx/prod/GET/xxxxxxxx"
}

あとは、AWS公式の開発者ガイドに書いてある

API 作成後にリソースポリシーを更新する場合は、更新後のポリシーをアタッチしてから API をデプロイし、変更を伝達する必要があります。ポリシーのみ、更新または保存した場合、API のランタイム動作が変更されることはありません。API のデプロイの詳細については、「Amazon API Gateway での REST API のデプロイ」を参照してください。

が注意点といったところか。

これで、API Gatewayをよりセキュアに運用できるようになった!