API GatewayをVPC内のプライベートアクセスのみに限定
AWSのAPI Gatewayを通信がインターネットに出ていかずにVPCの中だけに限定するには、以下の設定が必要です。
- API Gateway用のVPCエンドポイント作成
- API GatewayのリソースポリシーでVPCエンドポイントからのアクセスのみに制限
- API GatewayのEndpoint TypeをPrivateに設定
1と2があればできると勘違いしていて、3を対応せずに接続できず、ハマっていました。
参考
3をせずにcurlコマンドでAPIアクセスすると、次のようなレスポンスになります。
> GET /Prod/hello HTTP/1.1 > Host: xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com > User-Agent: curl/7.68.0 > Accept: */* > < HTTP/1.1 403 Forbidden < Server: Server < Date: Tue, 08 Dec 2020 08:39:10 GMT < Content-Type: application/json < Content-Length: 23 < Connection: keep-alive < x-amzn-RequestId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx < x-amzn-ErrorType: ForbiddenException < x-amz-apigw-id: XXXXXXXXXXXXXXXX {"message":"Forbidden"}
API Gatewayが403を返すときには x-amzn-ErrorType
を見て、AWSドキュメントでトラブルシューティングすればよいようです。
2と3をCloudFormationのテンプレートファイルで記述すると、次のようになります。
AWSTemplateFormatVersion: '2010-09-09' Parameters: ApiGatewayVpce: Type: String # vpce-... Resources: SampleApiGateway: Type: AWS::ApiGateway::RestApi Properties: ... EndpointConfiguration: Types: - PRIVATE Policy: Version: 2012-10-17 Statement: - Effect: Deny Principal: "*" Action: execute-api:Invoke Resource: "execute-api:/*" Condition: StringNotEquals: "aws:sourceVpce": !Ref ApiGatewayVpce - Effect: Allow Principal: "*" Action: execute-api:Invoke Resource: "execute-api:/*" SampleApiGatewayDeployment: Type: AWS::ApiGateway::Deployment Properties: RestApiId: !Ref SampleApiGateway StageName: Prod