Amplify Gen2をIP制限しながら利用したい

# 概要
皆さん、Amplifyは利用していますか？  
Amplifyは、素早く多機能なWebアプリケーションを構築できる便利なサービスで、適切に活用すれば従来のWebサーバー管理から解放され、効率的にWebサービスを公開できます。  
一方、企業のセキュリティポリシーなどでは、往々にしてセキュリティ要件でサービスをインターネットに公開しないこと・公開する場合はソースIP制限などを講じること、などが定められており、AWSのサービスにおいても無邪気に利用すると思わぬところでセキュリティ違反となることがあります。  
このようなセキュリティポリシーに準拠するため、VPC内にリソースを作成できるサービスであれば、インターネットゲートウェイの制御やWAFを用いたソースIP制限が適用可能です。
しかし、AmplifyはVPC内にリソースを作成するサービスではなく、またAmplifyの裏で複数のサービスが作成・利用されることから、それぞれのリソースに応じたインターネット公開制限・ソースIP制限設定が必要になります。  
本記事では**Amplify Gen2**について、インターネット公開制限・ソースIP制限しながら利用する方法を確認します。

# Amplify Gen2の機能

Amplify Gen2の機能の詳細や使い方については本記事では立ち入りません。
公式ドキュメントをご確認ください。

https://docs.amplify.aws/react/

| 機能 | 利用されるサービス  | IP制限に用いる機能/サービス |
| --- | --- | --- |
| Hosting | (S3, CloudFront)  | WAF |
| Authentication | Cognito  | WAF |
| Data | AppSync, DynamoDB  | WAF, リソースポリシー |
| Storage | S3  | パブリックアクセスブロック, バケットポリシー |
| Function | Lambda  | Function URL |


＊ 上記の機能以外にAI機能に関しても提供が開始されていますが、本記事では扱わないことにします。
(別記事で取り扱うかもしれません)

# ソースIP制限の設定
## Hosting
Amplify Gen2の場合、Hosting機能については自分のAWSアカウントに何かリソースが作成されるわけではなくAWS側で管理されます。  
ですが、AWS側で管理されるからといって利用者側で何も設定が出来ないわけではなく、ソースIP制限についてはWAFのアタッチが可能です。

https://docs.aws.amazon.com/ja_jp/amplify/latest/userguide/WAF-integration.html

Amplify HostingへのWAFの設定方法の詳細については既にWeb上に多くの情報がありますので詳細は割愛しますが、以下のように設定が可能です。

![スクリーンショット 2025-05-20 185927.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/2dd82dd1-862d-4bbe-bc5c-b7dff443c1ce.png)


ここで設定したWAFは、WAFのコンソールからも確認可能です。

![スクリーンショット 2025-05-20 190138.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/c268336a-e357-46ff-b20a-d0d84a18010f.png)

## Authentication
### Cognito
Authentication機能では、Cognitoが作成されます。CognitoにはWAFが適用可能ですので、WAFを利用したソースIP制限を行いましょう。  

残念ながらHostingでソースIP制限を行う際に利用したWebACLは流用出来ません*ので、新規作成が必要です。  
＊WebACLのRegionがHostingについてはGlobal, CognitoについてはAmplifyを利用するリージョンとなるため  
また、WebACLのルールはクラシックUIのみに適用されますので、Cognitoのログイン画面はクラシックUIにしておくよう注意が必要です。

> 現在、ウェブ ACL ルールは、ホストされた UI (クラシック) ブランドバージョンを持つユーザープールドメインへのリクエストにのみ適用されます。ManagedLoginVersion を に設定した場合、またはブランドバージョンをマネージドログインに設定した場合、Amazon Cognito はマネージドログインページにルールを適用しません。

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/user-pool-waf.html

CognitoへのWAFアタッチはWAFのコンソール画面・もしくはCognitoの画面から可能です。  

・WAFの画面から行う場合

![スクリーンショット 2025-05-20 200055.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/d6efe4d7-7320-4120-b595-db45f42fa53d.png)


・Cognitoの画面から行う場合
![スクリーンショット 2025-05-20 194355.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/5803aafa-4af0-4f6c-9be6-9266084a7fe1.png)

## Storage
### S3
AmplifyのStorage機能ではストレージとしてS3が利用されますので、S3に対してソースIP制限を実施する必要があります。  
パブリックアクセスブロックを有効にしたうえで、バケットポリシーでソースIP制限を行うことでパブリックエンドポイント経由での操作についても制限しておきましょう。

https://repost.aws/ja/knowledge-center/block-s3-traffic-vpc-ip
```
{  
  "Id": "SourceIP",  
  "Version": "2012-10-17",  
  "Statement": [  
    {  
      "Sid": "SourceIP",  
      "Action": "s3:PutObject",  
      "Effect": "Deny",  
      "Resource": [  
        "arn:aws:s3:::DOC-EXAMPLE-BUCKET",  
        "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"  
      ],  
      "Condition": {  
        "NotIpAddress": {  
          "aws:SourceIp": [  
            "11.11.11.11/32",  
            "22.22.22.22/32"  
          ]  
        }  
      },  
      "Principal": "*"  
    }  
  ]  
}
```

## Data
### AppSync
AmplifyのData機能を利用するとAppSyncとDynamoDBが自動的に作成され、AppSyncはデータ操作(GraphQL操作)のために利用されます。  
AppSyncのエンドポイントにはWAFを適用することが出来ますので、WAFを利用してソースIP制限を行いましょう。

https://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/WAF-Integration.html

AppSyncへのWAF適用はWAFコンソールから行います。(CognitoはCognitoの画面からも可能ですが、AppSyncはWAFの画面からしか行えません。)

![スクリーンショット 2025-05-20 210126.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/9c837535-9d4d-4373-9f99-bd988e2e5df8.png)


![スクリーンショット 2025-05-20 210420.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/b4506017-5563-4d21-934e-eb86e43d41f1.png)

### DynamoDB
DynamoDBは実際のデータを保管するために利用されます。
DynamoDBについてもパブリックエンドポイント経由でデータの操作が可能ですので、この操作について制限をかける必要があります。
DynamoDBはAppSyncやCognitoのようなWAFを適用するパターンではなく、S3のようにリソースベースのポリシーを用いることでソースIP制限が可能です。

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/rbac-examples.html

ソースIP制限の設定例はリソースベースポリシーの例の中の一つとしても記載されています。
```
{
  "Id":"PolicyId2",
  "Version":"2012-10-17",
  "Statement":[
    {
      "Sid":"AllowIPmix",
      "Effect":"Allow",
      "Principal":"arn:aws:iam::111111111111:user/John",
      "Action":"dynamodb:*",
      "Resource":"*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "54.240.143.0/24",
            "2001:DB8:1234:5678::/64"
          ]
        }
      }
    }
  ]
}
```


## Function
### Lambda
LambdaにはFunction URL(関数URL)という機能が存在し、これを有効化しておくとAPI Gatewayなどを利用することなくPublicに公開することが出来ます。  
適切な使い方をすれば便利な機能なのですが、残念ながら本記事でやりたいこととは真逆になるので無効化しましょう。  
Function URLを利用しなくても、Amplifyの機能間で関数の実行は可能です。  

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/urls-configuration.html

Function URL自体を無効化しなくても、リソースベースポリシーで特定のIPのみに制限すればよいのでは？と思いましたが、残念ながらこれは出来ないようです。

https://qiita.com/hayao_k/items/d091081a692f41226d71

# まとめ
本記事ではAmplifyおよびその後ろで利用されるサービスについて、インターネット公開の制限およびソースIP制限を行う方法についてご紹介しました。  
AWSを積極的に活用していきたいが、会社のセキュリティポリシーの特に外部公開に関する部分に引っかかる...というのはよく聞く話ですので、そういった方のお役に立てれば幸いです。