WAF Web ACLをAPI Gatewayに適用する
AWS WAFは以下の4種類のリソースに適用することができます。
- ALB
- CloudFront
- API Gateway
- AppSync
今回はAPI Gatewayに適用する方法を確認します。
なおWAFをALBに適用する方法については、以下のページをご確認ください。
WAFをCloudFrontに適用する方法については、以下のページをご確認ください。
WAFをAppSyncに適用する方法については、以下のページをご確認ください。
構築する環境
WAF Web ACLを作成します。
地理制限を行います。
具体的にはルールグループを自作し、その中に日本(JP)からのアクセスをブロックするルールを設定します。
作成したWeb ACLをAPI Gatewayに適用します。
API Gatewayを作成し、バックエンドにLambdaを配置します。
ユーザからHTTPリクエストを受けた場合、API Gatewayがエンドポイントとなって、代わりにLambda関数を呼び出し、同関数の実行結果をユーザに返すというシンプルな構成です。
API GatewayはREST APIタイプで作成します。
Lambda関数のランタイム環境はPython3.8とします。
関数の動作ですが、実行すると「Hello form Awstut !」という文字列を返すという単純な内容とします。
CloudFormationテンプレートファイル
上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。
https://github.com/awstut-an-r/awstut-fa/tree/main/053
テンプレートファイルのポイント解説
本ページでは、CloudFrontにWAFを適用する方法を中心に取り上げます。
WAFの基本的な事項については、以下のページをご確認ください。
WAFで地理制限する方法については、以下のページをご確認ください。
REST APIタイプのAPI Gatewayに関する基本的な事項については、以下のページをご確認ください。
(参考)REST APIタイプのAPI Gatewayリソース
以下のAWS公式サイトで言及されている通り、WAFを適用できるAPI GatewayのタイプはREST APIタイプです。
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/http-api-vs-rest.html
Resources:
RestApi:
Type: AWS::ApiGateway::RestApi
Properties:
EndpointConfiguration:
Types:
- EDGE
Name: !Ref Prefix
Deployment:
Type: AWS::ApiGateway::Deployment
DependsOn:
- Method
Properties:
RestApiId: !Ref RestApi
Resource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId: !GetAtt RestApi.RootResourceId
PathPart: !Sub "${Prefix}-resource"
RestApiId: !Ref RestApi
Stage:
Type: AWS::ApiGateway::Stage
Properties:
DeploymentId: !Ref Deployment
RestApiId: !Ref RestApi
StageName: !Sub "${Prefix}-stage"
Method:
Type: AWS::ApiGateway::Method
Properties:
AuthorizationType: NONE
HttpMethod: GET
Integration:
ConnectionType: INTERNET
Credentials: !GetAtt ApiGatewayRole.Arn
IntegrationHttpMethod: POST
Type: AWS_PROXY
Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${FunctionArn}/invocations"
ResourceId: !Ref Resource
RestApiId: !Ref RestApi
Code language: YAML (yaml)
特別な設定は不要です。
リソースの定義において、URLのPATHの一部を「fa-053-resource」と設定します。
ステージの定義において、ステージ名を「fa-053-stage」と設定します。
Web ACL
Resources:
WebACL:
Type: AWS::WAFv2::WebACL
Properties:
DefaultAction:
Allow: {}
Name: !Sub "${Prefix}-WebACL"
Rules:
- Name: !Sub "${Prefix}-WebACL-GeoRestriction"
OverrideAction:
None: {}
Priority: 0
Statement:
RuleGroupReferenceStatement:
Arn: !GetAtt RuleGroup.Arn
VisibilityConfig:
CloudWatchMetricsEnabled: true
MetricName: !Sub "${Prefix}-WebACL-GeoRestriction"
SampledRequestsEnabled: true
Scope: REGIONAL
VisibilityConfig:
CloudWatchMetricsEnabled: true
MetricName: !Ref Prefix
SampledRequestsEnabled: true
Code language: YAML (yaml)
Scopeプロパティがポイントです。
Web ACLをCloudFrontに適用する場合は「CLOUDFRONT」、それ以外のリソースの場合は「REGIONAL」となります。
今回はAPI Gatewayですから後者となります。
Resources:
WebACLAssociation:
Type: AWS::WAFv2::WebACLAssociation
Properties:
ResourceArn: !Sub "arn:aws:apigateway:${AWS::Region}::/restapis/${RestApi}/stages/${StageName}"
WebACLArn: !GetAtt WebACL.Arn
Code language: YAML (yaml)
API GatewayにWAFを適用するためのリソースです。
ResourceArnプロパティで、WAFを適用するAPI Gatewayを指定します。
指定方法は以下のように説明されています。
For an Amazon API Gateway REST API: arn:aws:apigateway:region::/restapis/api-id/stages/stage-name
AWS::WAFv2::WebACLAssociation
ですから上記の要件を満たすために、組み込み関数Fn::Subを使用して、APIのIDとステージ名を埋め込んで設定します。
環境構築
CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。
CloudFormationスタックを作成し、スタック内のリソースを確認する
CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。
各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。
- API Gatewayの名前:fa-053
- API Gatewayのエンドポイント:https://dv68zdrmge.execute-api.ap-northeast-1.amazonaws.com/
- API Gatewayのステージ名:fa-053-stage
- API Gatewayのリソース名:fa-053-resource
- WAFの名前:fa-053-WebACL
AWS Management Consoleからもリソースを確認します。
まずAPI Gatewayを確認します。
ステージのページを見えると、WAFが適用されていることがわかります。
次にWeb ACLを確認します。
Web ACL側からも、このACLがAPI Gatewayに適用されていることがわかります。
動作確認
準備が整いましたので、日本からCloudFrontにアクセスします。
今回アクセスするべきURLは、リソースとステージの情報を組み合わせて定まります。
具体的には以下のURLとなります。
https://dv68zdrmge.execute-api.ap-northeast-1.amazonaws.com/fa-053-stage/fa-053-resource/
アクセスが拒否されました。
日本からアクセスしたため、API Gatewayに到達する前に、WAF Web ACLによってブロックされたということです。
確認のために、地理制限のアクションを変更します。
ルールのアクションをブロックからカウント、つまりルールは生かしつつ、ルールに該当するトラフィック数を数えるだけに変更しました。
改めてAPI Gatewayにアクセスします。
API Gatewayにアクセスできるようになりました。
ルールのアクションがブロックからカウントだけになり、アクセスが可能になったためです。
まとめ
WAF ACLをAPI Gatewayに適用する方法を確認しました。