{"id":21337,"date":"2021-12-15T11:00:06","date_gmt":"2021-12-15T02:00:06","guid":{"rendered":"https:\/\/www.skyarch.net\/blog\/?p=21337"},"modified":"2021-12-15T11:00:06","modified_gmt":"2021-12-15T02:00:06","slug":"route53-resolver-%e3%82%92%e4%bd%bf%e3%81%a3%e3%81%a6-vpc-endpoint-%e3%81%ae%e5%90%8d%e5%89%8d%e8%a7%a3%e6%b1%ba%e3%81%8c%e6%9c%89%e5%8a%b9%e3%81%aa-vpc-%e3%81%8b%e3%82%89-private%e3%83%bbregional","status":"publish","type":"post","link":"https:\/\/www.skyarch.net\/blog\/route53-resolver-%e3%82%92%e4%bd%bf%e3%81%a3%e3%81%a6-vpc-endpoint-%e3%81%ae%e5%90%8d%e5%89%8d%e8%a7%a3%e6%b1%ba%e3%81%8c%e6%9c%89%e5%8a%b9%e3%81%aa-vpc-%e3%81%8b%e3%82%89-private%e3%83%bbregional\/","title":{"rendered":"Route53 Resolver \u3092\u4f7f\u3063\u3066 VPC Endpoint \u306e\u540d\u524d\u89e3\u6c7a\u304c\u6709\u52b9\u306a VPC \u304b\u3089 Private\u30fbRegional\u30fbEdge API \u306b\u30a2\u30af\u30bb\u30b9\u3057\u3066\u307f\u308b"},"content":{"rendered":"<p><span style=\"color: #ff0000\"><strong>\u672c\u8a18\u4e8b\u3067\u691c\u8a3c\u3057\u305f\u5185\u5bb9\u306f\u5b9f\u9a13\u7684\u306a\u3082\u306e\u3067\u3059\u306e\u3067\u3001\u5b9f\u74b0\u5883\u3078\u5c0e\u5165\u3059\u308b\u969b\u306f\u81ea\u5df1\u8cac\u4efb\u3067\u304a\u9858\u3044\u3057\u307e\u3059\u3002<\/strong><\/span><\/p>\n<h2>\u306f\u3058\u3081\u306b<\/h2>\n<p>VPC Endpoint \u3092\u8a2d\u5b9a\u3057\u3066\u3044\u308b\u74b0\u5883\u3067\u3001API Gateway \u306e Regional API \u307e\u305f\u306f Edge API \u306b\u30a2\u30af\u30bb\u30b9\u3059\u308b\u3068 403 \u30a8\u30e9\u30fc\u304c\u767a\u751f\u3059\u308b\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002<br \/>\n\u3053\u308c\u306f VPC Endpoint \u306e Private DNS \u304c\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u6a5f\u80fd\u3057\u3066\u767a\u751f\u3057\u307e\u3059\u3002<br \/>\n\u203b\u4ee5\u964d\u306e\u56f3\u3067\u3001\u6ce2\u7dda\u77e2\u5370\u306f\u540d\u524d\u89e3\u6c7a\u306e\u6d41\u308c\u3092\u8868\u3057\u3066\u3044\u307e\u3059<br \/>\n<a href=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/1_reason-of-403.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-21338\" src=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/1_reason-of-403-1024x605.png\" alt=\"\" width=\"728\" height=\"430\" srcset=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/1_reason-of-403-1024x605.png 1024w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/1_reason-of-403-300x177.png 300w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/1_reason-of-403-768x454.png 768w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/1_reason-of-403-728x430.png 728w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/1_reason-of-403.png 1221w\" sizes=\"auto, (max-width: 728px) 100vw, 728px\" \/><\/a><\/p>\n<p>\u3053\u308c\u3092\u89e3\u6d88\u3059\u308b\u306b\u306f\u3001\u30ab\u30b9\u30bf\u30e0\u30c9\u30e1\u30a4\u30f3\u3067 Regional \/ Edge API \u306b\u30a2\u30af\u30bb\u30b9\u3059\u308b\u304b\u3001<br \/>\n<a href=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/2_access-via-custom-domain.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-21339\" src=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/2_access-via-custom-domain-1024x605.png\" alt=\"\" width=\"728\" height=\"430\" srcset=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/2_access-via-custom-domain-1024x605.png 1024w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/2_access-via-custom-domain-300x177.png 300w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/2_access-via-custom-domain-768x454.png 768w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/2_access-via-custom-domain-728x430.png 728w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/2_access-via-custom-domain.png 1221w\" sizes=\"auto, (max-width: 728px) 100vw, 728px\" \/><\/a><\/p>\n<p>Private DNS \u3092\u7121\u52b9\u306b\u3057\u3066\u3001Private API \u3068 VPC Endpoint \u3092\u95a2\u9023\u4ed8\u3051\u3059\u308b\u3053\u3068\u3067\u751f\u6210\u3055\u308c\u308b\u4ee5\u4e0b\u306e\u3088\u3046\u306aURL\u3092\u4ecb\u3057\u3066 Private API \u306b\u30a2\u30af\u30bb\u30b9\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002<br \/>\n<code>https:\/\/{rest-api-id}-{vpce-id}.execute-api.{region}.amazonaws.com\/{stage}<\/code><br \/>\n<a href=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/3_disable-private-dns.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-21340\" src=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/3_disable-private-dns-1024x663.png\" alt=\"\" width=\"728\" height=\"471\" srcset=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/3_disable-private-dns-1024x663.png 1024w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/3_disable-private-dns-300x194.png 300w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/3_disable-private-dns-768x498.png 768w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/3_disable-private-dns-728x472.png 728w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/3_disable-private-dns.png 1221w\" sizes=\"auto, (max-width: 728px) 100vw, 728px\" \/><\/a><\/p>\n<p><a href=\"https:\/\/aws.amazon.com\/jp\/premiumsupport\/knowledge-center\/api-gateway-vpc-connections\/\" target=\"_blank\" rel=\"noopener\">VPC \u304b\u3089 API Gateway API \u306b\u63a5\u7d9a\u3059\u308b\u3068\u304d\u306b HTTP 403 Forbidden \u30a8\u30e9\u30fc\u304c\u767a\u751f\u3059\u308b\u306e\u306f\u4f55\u6545\u3067\u3059\u304b?<\/a><br \/>\n<a href=\"https:\/\/docs.aws.amazon.com\/ja_jp\/apigateway\/latest\/developerguide\/apigateway-private-api-test-invoke-url.html\" target=\"_blank\" rel=\"noopener\">\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 API \u3092\u547c\u3073\u51fa\u3059\u65b9\u6cd5<\/a><\/p>\n<p>\u3057\u304b\u3057\u3001<\/p>\n<ul>\n<li>Regional \/ Edge API \u306b\u30ab\u30b9\u30bf\u30e0\u30c9\u30e1\u30a4\u30f3\u3092\u7528\u610f\u3059\u308b\u306e\u306f\u96e3\u3057\u3044\u304c (\u5916\u90e8\u30b7\u30b9\u30c6\u30e0\u306a\u3069)<\/li>\n<li>VPC Endpoint ID \u304c\u542b\u307e\u308c\u306a\u3044\u30b7\u30f3\u30d7\u30eb\u306a URL \u3067 Private API \u306b\u30a2\u30af\u30bb\u30b9\u3057\u305f\u3044<\/li>\n<\/ul>\n<p>\u3068\u3044\u3046\u5834\u5408\u3092\u8003\u616e\u3057\u3066\u3001Route53 Resolver \u306e Outbound Rule \u3092\u4f7f\u3063\u3066\u3053\u308c\u3092\u5b9f\u73fe\u3067\u304d\u306a\u3044\u304b\u691c\u8a3c\u3057\u3066\u307f\u307e\u3057\u305f\u3002<br \/>\n\u691c\u8a3c\u306b\u5229\u7528\u3057\u305f CloudFormation \u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306f\u3001\u672c\u8a18\u4e8b\u306e\u672b\u5c3e\u306b\u8f09\u305b\u307e\u3057\u305f\u3002<\/p>\n<h2>\u691c\u8a3c\u3057\u3066\u307f\u305f<\/h2>\n<p>VPC Endpoint \u3068 Route53 Resolver Outbound Rule \u306e\u6709\u7121\u3067\u30d5\u30a7\u30fc\u30ba1, 2, 3 \u306b\u5206\u3051\u307e\u3057\u305f\u3002<\/p>\n<h3>\u30d5\u30a7\u30fc\u30ba1<\/h3>\n<p>\u30d5\u30a7\u30fc\u30ba1 \u306f\u3001VPC Endpoint \u3082 Outbound Rule \u3082\u7121\u3044\u72b6\u614b\u3067\u3059\u3002<br \/>\n<a href=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-21346\" src=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase1-1024x605.png\" alt=\"\" width=\"728\" height=\"430\" srcset=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase1-1024x605.png 1024w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase1-300x177.png 300w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase1-768x454.png 768w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase1-728x430.png 728w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase1.png 1221w\" sizes=\"auto, (max-width: 728px) 100vw, 728px\" \/><\/a><\/p>\n<p>\u56f3\u4e2d\u306e VPC Lambda \u306f\u5404 API \u306b\u30a2\u30af\u30bb\u30b9\u3057\u3001API \u304c\u4f7f\u3063\u3066\u3044\u308bIP\u30a2\u30c9\u30ec\u30b9\u3068 API \u306e\u30ec\u30b9\u30dd\u30f3\u30b9\u3092\u8868\u793a\u3057\u307e\u3059\u3002<br \/>\nVPC Lambda \u3092\u30c6\u30b9\u30c8\u5b9f\u884c\u3059\u308b\u3068\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3057\u305f\u3002<br \/>\n<a href=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-21347\" src=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase1-1024x308.png\" alt=\"\" width=\"728\" height=\"219\" srcset=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase1-1024x308.png 1024w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase1-300x90.png 300w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase1-768x231.png 768w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase1-728x219.png 728w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase1.png 1346w\" sizes=\"auto, (max-width: 728px) 100vw, 728px\" \/><\/a><\/p>\n<p>\u30d5\u30a7\u30fc\u30ba1\u306e\u56f3\u306e\u901a\u308a\u3001<\/p>\n<ul>\n<li>Regional \/ Edge API \u306b Public IP \u3067\u30a2\u30af\u30bb\u30b9\u3057\u3001<\/li>\n<li>Private API \u306e\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u306e\u540d\u524d\u89e3\u6c7a\u304c\u51fa\u6765\u3066\u3044\u306a\u3044<\/li>\n<\/ul>\n<p>\u3068\u3044\u3046\u3053\u3068\u304c\u5206\u304b\u308a\u307e\u3059\u3002<\/p>\n<h3>\u30d5\u30a7\u30fc\u30ba2<\/h3>\n<p>\u30d5\u30a7\u30fc\u30ba2\u306b\u306f\u3001Private DNS \u304c\u6709\u52b9\u5316\u3055\u308c\u305f VPC Endpoint \u304c\u914d\u7f6e\u3055\u308c\u3066\u3044\u307e\u3059\u3002<br \/>\n<a href=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-21350\" src=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase2-1024x605.png\" alt=\"\" width=\"728\" height=\"430\" srcset=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase2-1024x605.png 1024w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase2-300x177.png 300w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase2-768x454.png 768w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase2-728x430.png 728w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase2.png 1221w\" sizes=\"auto, (max-width: 728px) 100vw, 728px\" \/><\/a><\/p>\n<p>VPC Lambda \u3092\u30c6\u30b9\u30c8\u5b9f\u884c\u3059\u308b\u3068\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3057\u305f\u3002<br \/>\n<a href=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-21351\" src=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase2-1024x316.png\" alt=\"\" width=\"728\" height=\"225\" srcset=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase2-1024x316.png 1024w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase2-300x93.png 300w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase2-768x237.png 768w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase2-728x225.png 728w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase2.png 1290w\" sizes=\"auto, (max-width: 728px) 100vw, 728px\" \/><\/a><\/p>\n<p>\u30d5\u30a7\u30fc\u30ba2\u306e\u56f3\u306e\u901a\u308a\u3001<\/p>\n<ul>\n<li>\u5168\u3066\u306e API \u306b Private IP \u3067\u30a2\u30af\u30bb\u30b9\u3057\u3001<\/li>\n<li>Regional \/ Edge API \u3078\u306e\u30a2\u30af\u30bb\u30b9\u306f Forbidden \u3068\u306a\u3063\u3066\u3044\u308b<\/li>\n<\/ul>\n<p>\u3068\u3044\u3046\u3053\u3068\u304c\u5206\u304b\u308a\u307e\u3059\u3002<\/p>\n<h3>\u30d5\u30a7\u30fc\u30ba3<\/h3>\n<p>\u3053\u3061\u3089\u304c\u672c\u8a18\u4e8b\u306e\u30ad\u30e2\u3067\u3059\u3002<br \/>\n\u30d5\u30a7\u30fc\u30ba3\u306f\u3001\u30d5\u30a7\u30fc\u30ba2\u306b Route53 Resolver Outbound Rule \u3092\u8ffd\u52a0\u3057\u305f\u5f62\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002<br \/>\nOutbound Rule \u306b\u3088\u308a Regional \/ Edge API \u306e\u30c9\u30e1\u30a4\u30f3\u540d\u306e\u540d\u524d\u89e3\u6c7a\u3092 8.8.8.8 (Google Public DNS) \u306b\u8ee2\u9001\u3057\u307e\u3059\u3002<br \/>\n<a href=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-21352\" src=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase3-1024x714.png\" alt=\"\" width=\"728\" height=\"508\" srcset=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase3-1024x714.png 1024w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase3-300x209.png 300w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase3-768x535.png 768w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase3-728x507.png 728w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/Phase3.png 1221w\" sizes=\"auto, (max-width: 728px) 100vw, 728px\" \/><\/a><\/p>\n<p>VPC Lambda \u3092\u30c6\u30b9\u30c8\u5b9f\u884c\u3059\u308b\u3068\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3057\u305f\u3002<br \/>\n<a href=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-21353\" src=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase3-1024x322.png\" alt=\"\" width=\"728\" height=\"229\" srcset=\"https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase3-1024x322.png 1024w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase3-300x94.png 300w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase3-768x241.png 768w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase3-728x229.png 728w, https:\/\/www.skyarch.net\/blog\/wp-content\/uploads\/2021\/12\/response-phase3.png 1293w\" sizes=\"auto, (max-width: 728px) 100vw, 728px\" \/><\/a><\/p>\n<p>\u30d5\u30a7\u30fc\u30ba3\u306e\u56f3\u306e\u901a\u308a\u3001<\/p>\n<ul>\n<li>Regional \/ Edge API \u3078 Public IP \u3067\u30a2\u30af\u30bb\u30b9\u3057\u3001<\/li>\n<li>Private API \u3078 Private IP \u3067\u30a2\u30af\u30bb\u30b9\u3057\u3066\u3044\u308b<\/li>\n<li>\u3044\u305a\u308c\u306e API \u306b\u3082\u30a2\u30af\u30bb\u30b9\u51fa\u6765\u3066\u3044\u308b<\/li>\n<\/ul>\n<p>\u3068\u3044\u3046\u7d50\u679c\u306b\u306a\u308a\u307e\u3057\u305f\u3002<\/p>\n<h2>CloudFormation\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8<\/h2>\n<p>VPC Lambda \u304c\u5229\u7528\u3057\u3066\u3044\u308b\u30ec\u30a4\u30e4\u30fc\u306e\u95a2\u4fc2\u3067\u3001\u672c\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u305d\u306e\u307e\u307e\u3060\u3068\u6771\u4eac\u30ea\u30fc\u30b8\u30e7\u30f3\u3067\u3057\u304b\u52d5\u4f5c\u3057\u307e\u305b\u3093\u3002<br \/>\n\u5225\u30ea\u30fc\u30b8\u30e7\u30f3\u3078\u5c55\u958b\u3059\u308b\u5834\u5408\u306f<a href=\"https:\/\/github.com\/keithrozario\/Klayers\/tree\/master\/deployments\/python3.8\/arns\" target=\"_blank\" rel=\"noopener\">\u3053\u3061\u3089<\/a>\u3092\u53c2\u8003\u306b\u8a72\u5f53\u90e8\u5206\u3092\u9069\u5b9c\u4fee\u6b63\u304f\u3060\u3055\u3044\u3002<\/p>\n<pre>AWSTemplateFormatVersion: 2010-09-09\nTransform: AWS::Serverless-2016-10-31\n\nParameters:\n  ResourcePrefix:\n    Type: String\n    Default: \"api-r53\"\n\n  Phase:\n    Type: String\n    Default: \"1\"\n    AllowedValues:\n      - \"1\"\n      - \"2\"\n      - \"3\"\n\nConditions:\n  Phase2: !Equals\n    - !Ref Phase\n    - \"2\"\n\n  Phase3: !Equals\n    - !Ref Phase\n    - \"3\"\n\n  AfterPhase2: !Or\n    - !Condition Phase2\n    - !Condition Phase3\n\nResources:\n# ------------------------------------------------------------#\n# Networking\n# ------------------------------------------------------------#\n  VPC:\n    Type: AWS::EC2::VPC\n    Properties:\n      CidrBlock: 10.0.0.0\/16\n      EnableDnsSupport: true\n      EnableDnsHostnames: true\n      Tags:\n        - Key: Name\n          Value: !Sub ${ResourcePrefix}-vpc-{{resolve:ssm:${RandomIdParameter}}}\n\n  PublicSubnet:\n    Type: AWS::EC2::Subnet\n    Properties:\n      CidrBlock: 10.0.0.0\/24\n      MapPublicIpOnLaunch: false\n      VpcId: !Ref VPC\n      AvailabilityZone: ap-northeast-1a\n      Tags:\n        - Key: Name\n          Value: !Sub ${ResourcePrefix}-public-subnet-{{resolve:ssm:${RandomIdParameter}}}\n\n  PrivateSubnet:\n    Type: AWS::EC2::Subnet\n    Properties:\n      CidrBlock: 10.0.1.0\/24\n      MapPublicIpOnLaunch: false\n      VpcId: !Ref VPC\n      AvailabilityZone: ap-northeast-1a\n      Tags:\n        - Key: Name\n          Value: !Sub ${ResourcePrefix}-private-subnet-{{resolve:ssm:${RandomIdParameter}}}\n\n  InternetGateway:\n    Type: AWS::EC2::InternetGateway\n    Properties:\n      Tags:\n        - Key: Name\n          Value: !Sub ${ResourcePrefix}-igw-{{resolve:ssm:${RandomIdParameter}}}\n\n  InternetGatewayAttachment:\n    Type: AWS::EC2::VPCGatewayAttachment\n    Properties:\n      InternetGatewayId : !Ref InternetGateway\n      VpcId: !Ref VPC\n\n  RouteTableForPublicSubnet:\n    Type: AWS::EC2::RouteTable\n    Properties:\n      VpcId: !Ref VPC\n      Tags:\n        - Key: Name\n          Value: !Sub ${ResourcePrefix}-public-route-table-{{resolve:ssm:${RandomIdParameter}}}\n\n  RouteForPublicSubnet:\n    Type: AWS::EC2::Route\n    Properties:\n      RouteTableId: !Ref RouteTableForPublicSubnet\n      DestinationCidrBlock: 0.0.0.0\/0\n      GatewayId: !Ref InternetGateway\n\n  AssocciateRouteTableForPublicSubnet:\n    Type: AWS::EC2::SubnetRouteTableAssociation\n    Properties:\n      RouteTableId: !Ref RouteTableForPublicSubnet\n      SubnetId: !Ref PublicSubnet\n\n  Eip:\n    Type: AWS::EC2::EIP\n    Properties:\n      Domain: vpc\n      Tags:\n        - Key: Name\n          Value: !Sub ${ResourcePrefix}-eip-{{resolve:ssm:${RandomIdParameter}}}\n\n  NatGateway:\n    Type: AWS::EC2::NatGateway\n    Properties:\n      AllocationId: !GetAtt Eip.AllocationId\n      SubnetId: !Ref PublicSubnet\n      Tags:\n        - Key: Name\n          Value: !Sub ${ResourcePrefix}-nat-gateway-{{resolve:ssm:${RandomIdParameter}}}\n\n  RouteTableForPrivateSubnet:\n    Type: AWS::EC2::RouteTable\n    Properties:\n      VpcId: !Ref VPC\n      Tags:\n        - Key: Name\n          Value: !Sub ${ResourcePrefix}-private-route-table-{{resolve:ssm:${RandomIdParameter}}}\n\n  RouteForPrivateSubnet:\n    Type: AWS::EC2::Route\n    Properties:\n      RouteTableId: !Ref RouteTableForPrivateSubnet\n      DestinationCidrBlock: 0.0.0.0\/0\n      NatGatewayId: !Ref NatGateway\n\n  AssocciateRouteTableForPrivateSubnet:\n    Type: AWS::EC2::SubnetRouteTableAssociation\n    Properties:\n      RouteTableId: !Ref RouteTableForPrivateSubnet\n      SubnetId: !Ref PrivateSubnet\n\n# ------------------------------------------------------------#\n# VPC Endpoint for API Gateway\n# ------------------------------------------------------------#\n  VpcEndpoint:\n    Type: AWS::EC2::VPCEndpoint\n    Condition: AfterPhase2\n    Properties:\n      ServiceName: !Sub \"com.amazonaws.${AWS::Region}.execute-api\"\n      VpcEndpointType: Interface\n      PrivateDnsEnabled: true\n      VpcId: !Ref VPC\n      SubnetIds:\n        - !Ref PrivateSubnet\n      SecurityGroupIds:\n        - !Ref VpcEndpointSecurityGroup\n\n  VpcEndpointSecurityGroup:\n    Type: AWS::EC2::SecurityGroup\n    Condition: AfterPhase2\n    Properties:\n        GroupName: !Sub ${ResourcePrefix}-vpc-endpoint-sg-{{resolve:ssm:${RandomIdParameter}}}\n        GroupDescription: security group for vpc endpoint of api gateway\n        VpcId: !Ref VPC\n        SecurityGroupIngress:\n          - IpProtocol: tcp\n            FromPort: 443\n            ToPort: 443\n            CidrIp: !GetAtt VPC.CidrBlock\n        SecurityGroupEgress:\n          - IpProtocol: \"-1\"\n            CidrIp: 0.0.0.0\/0\n\n# ------------------------------------------------------------#\n# Route53 Resolver\n# ------------------------------------------------------------#\n  ResolverRuleForEdgeApi:\n    Type: AWS::Route53Resolver::ResolverRule\n    Condition: Phase3\n    Properties:\n      DomainName: !Sub ${EdgeApi}.execute-api.${AWS::Region}.amazonaws.com\n      Name: !Sub ${ResourcePrefix}-edge-api-resolver-rule-{{resolve:ssm:${RandomIdParameter}}}\n      ResolverEndpointId: !Ref ResolverEndpoint\n      RuleType: FORWARD\n      TargetIps:\n        - Ip: 8.8.8.8\n          Port: 53\n\n  ResolverRuleAssociationForEdgeApi:\n    Type: AWS::Route53Resolver::ResolverRuleAssociation\n    Condition: Phase3\n    Properties:\n      Name: !Sub ${ResourcePrefix}-edge-api-resolver-rule-association-{{resolve:ssm:${RandomIdParameter}}}\n      ResolverRuleId: !GetAtt ResolverRuleForEdgeApi.ResolverRuleId\n      VPCId: !Ref VPC\n\n  ResolverRuleForRegionalApi:\n    Type: AWS::Route53Resolver::ResolverRule\n    Condition: Phase3\n    Properties:\n      DomainName: !Sub ${RegionalApi}.execute-api.${AWS::Region}.amazonaws.com\n      Name: !Sub ${ResourcePrefix}-regional-api-resolver-rule-{{resolve:ssm:${RandomIdParameter}}}\n      ResolverEndpointId: !Ref ResolverEndpoint\n      RuleType: FORWARD\n      TargetIps:\n        - Ip: 8.8.8.8\n          Port: 53\n\n  ResolverRuleAssociationForRegionalApi:\n    Type: AWS::Route53Resolver::ResolverRuleAssociation\n    Condition: Phase3\n    Properties:\n      Name: !Sub ${ResourcePrefix}-regional-api-resolver-rule-association-{{resolve:ssm:${RandomIdParameter}}}\n      ResolverRuleId: !GetAtt ResolverRuleForRegionalApi.ResolverRuleId\n      VPCId: !Ref VPC\n\n  ResolverEndpoint:\n    Type: AWS::Route53Resolver::ResolverEndpoint\n    Condition: Phase3\n    Properties:\n      Direction: OUTBOUND\n      IpAddresses:\n        # 2\u3064\u4ee5\u4e0a\u6307\u5b9a\u304c\u5fc5\u8981\n        - SubnetId: !Ref PrivateSubnet\n        - SubnetId: !Ref PrivateSubnet\n      Name: !Sub ${ResourcePrefix}-resolver-endpoint-{{resolve:ssm:${RandomIdParameter}}}\n      SecurityGroupIds:\n        - !Ref ResolverEndpointSecurityGroup\n\n  ResolverEndpointSecurityGroup:\n    Type: AWS::EC2::SecurityGroup\n    Condition: Phase3\n    Properties:\n        GroupName: !Sub ${ResourcePrefix}-resolver-endpoint-sg-{{resolve:ssm:${RandomIdParameter}}}\n        GroupDescription: security group for route53 resolver endpoint\n        VpcId: !Ref VPC\n        SecurityGroupIngress:\n          - IpProtocol: tcp\n            FromPort: 53\n            ToPort: 53\n            CidrIp: !GetAtt VPC.CidrBlock\n          - IpProtocol: udp\n            FromPort: 53\n            ToPort: 53\n            CidrIp: !GetAtt VPC.CidrBlock\n        SecurityGroupEgress:\n          - IpProtocol: \"-1\"\n            CidrIp: 0.0.0.0\/0\n\n# ------------------------------------------------------------#\n# VPC Lambda\n# ------------------------------------------------------------#\n  VpcLambda:\n    Type: AWS::Serverless::Function\n    DependsOn: VpcLambdaLog\n    Properties:\n      FunctionName: !Sub ${ResourcePrefix}-vpc-function-{{resolve:ssm:${RandomIdParameter}}}\n      InlineCode: |\n        import logging\n        import os\n        import socket\n\n        import requests\n\n        logger = logging.getLogger()\n        logger.setLevel(os.environ['LOG_LEVEL'])\n\n        def lambda_handler(event, context):\n            logger.info('\\n'.join([\n                '',\n                '# Edge API',\n                get_output(url=os.environ['EDGE_API_URL']),\n                '',\n                '# Regional API Response',\n                get_output(url=os.environ['REGIONAL_API_URL']),\n                '',\n                '# Private API Response',\n                get_output(url=os.environ['PRIVATE_API_URL']),\n            ]))\n\n        def get_output(url:str) -&gt; str:\n            domain_name = url.split('\/')[2]\n            output = '\\n'.join([\n                f'IP: {get_ip(domain_name)}',\n                f'Response: {requests_get(url)}',\n            ])\n            return output\n\n        def get_ip(domain_name:str) -&gt; str:\n            try:\n                return socket.gethostbyname(domain_name)\n            except Exception as e:\n                return str(e)\n\n        def requests_get(url:str) -&gt; str:\n            try:\n                return requests.get(url).content.decode('ascii')\n            except requests.exceptions.RequestException as e:\n                return str(e)\n      Handler: index.lambda_handler\n      Environment:\n        Variables:\n          LOG_LEVEL: INFO\n          EDGE_API_URL: !Sub https:\/\/${EdgeApi}.execute-api.${AWS::Region}.amazonaws.com\/prod\n          REGIONAL_API_URL: !Sub https:\/\/${RegionalApi}.execute-api.${AWS::Region}.amazonaws.com\/prod\n          PRIVATE_API_URL: !Sub https:\/\/${PrivateApi}.execute-api.${AWS::Region}.amazonaws.com\/prod\n      Runtime: python3.8\n      Timeout: 10\n      MemorySize: 128\n      VpcConfig:\n        SecurityGroupIds:\n          - !Ref VpcLambdaSecurityGroup\n        SubnetIds:\n          - !Ref PrivateSubnet\n      Layers:\n        # \"Python Toolkit\" on https:\/\/github.com\/mthenw\/awesome-layers\n        - arn:aws:lambda:ap-northeast-1:770693421928:layer:Klayers-python38-requests:24\n      Policies:\n        - Version: 2012-10-17\n          Statement:\n            - Effect: Allow\n              Action:\n                - logs:CreateLogGroup\n              Resource: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*\n            - Effect: Allow\n              Action:\n                - logs:CreateLogStream\n                - logs:PutLogEvents\n              Resource: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:\/aws\/lambda\/${ResourcePrefix}-vpc-function-{{resolve:ssm:${RandomIdParameter}}}:*\n\n  VpcLambdaSecurityGroup:\n    Type: AWS::EC2::SecurityGroup\n    Properties:\n        GroupName: !Sub ${ResourcePrefix}-vpc-function-sg-{{resolve:ssm:${RandomIdParameter}}}\n        GroupDescription: security group for vpc lambda function\n        VpcId: !Ref VPC\n        SecurityGroupEgress:\n          - IpProtocol: \"-1\"\n            CidrIp: 0.0.0.0\/0\n\n  VpcLambdaLog:\n    Type: AWS::Logs::LogGroup\n    Properties:\n      LogGroupName: !Sub \/aws\/lambda\/${ResourcePrefix}-vpc-function-{{resolve:ssm:${RandomIdParameter}}}\n      RetentionInDays: 7\n\n# ------------------------------------------------------------#\n# API Gateway + Lambda\n# ------------------------------------------------------------#\n  EdgeApi:\n    Type: AWS::Serverless::Api\n    Properties:\n      Name: !Sub ${ResourcePrefix}-edge-api-{{resolve:ssm:${RandomIdParameter}}}\n      StageName: prod\n      EndpointConfiguration:\n        Type: EDGE\n\n  RegionalApi:\n    Type: AWS::Serverless::Api\n    Properties:\n      Name: !Sub ${ResourcePrefix}-regional-api-{{resolve:ssm:${RandomIdParameter}}}\n      StageName: prod\n      EndpointConfiguration:\n        Type: REGIONAL\n\n  PrivateApi:\n    Type: AWS::Serverless::Api\n    Properties:\n      Name: !Sub ${ResourcePrefix}-private-api-{{resolve:ssm:${RandomIdParameter}}}\n      StageName: prod\n      EndpointConfiguration:\n        Type: PRIVATE\n      Auth:\n        ResourcePolicy:\n          IntrinsicVpcWhitelist:\n            - !Ref VPC\n\n  ApiLambda:\n    Type: AWS::Serverless::Function\n    DependsOn: ApiLambdaLog\n    Properties:\n      FunctionName: !Sub ${ResourcePrefix}-api-function-{{resolve:ssm:${RandomIdParameter}}}\n      InlineCode: |\n        def lambda_handler(event, context):\n            return {\n                'isBase64Encoded': False,\n                'statusCode': 200,\n                'headers': {},\n                'body': '{\"message\": \"Hello from AWS Lambda\"}'\n            }\n      Handler: index.lambda_handler\n      Runtime: python3.8\n      Timeout: 10\n      MemorySize: 128\n      Events:\n        EdgeApiEvent:\n          Type: Api\n          Properties:\n            Path: \/\n            Method: get\n            RestApiId: !Ref EdgeApi\n        RegionalApiEvent:\n          Type: Api\n          Properties:\n            Path: \/\n            Method: get\n            RestApiId: !Ref RegionalApi\n        PrivateApiEvent:\n          Type: Api\n          Properties:\n            Path: \/\n            Method: get\n            RestApiId: !Ref PrivateApi\n      Policies:\n        - Version: 2012-10-17\n          Statement:\n            - Effect: Allow\n              Action:\n                - logs:CreateLogGroup\n              Resource: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*\n            - Effect: Allow\n              Action:\n                - logs:CreateLogStream\n                - logs:PutLogEvents\n              Resource: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:\/aws\/lambda\/${ResourcePrefix}-api-function-{{resolve:ssm:${RandomIdParameter}}}:*\n\n  ApiLambdaLog:\n    Type: AWS::Logs::LogGroup\n    Properties:\n      LogGroupName: !Sub \/aws\/lambda\/${ResourcePrefix}-api-function-{{resolve:ssm:${RandomIdParameter}}}\n      RetentionInDays: 7\n\n# ------------------------------------------------------------#\n# Supplemental Resources\n# ------------------------------------------------------------#\n  RandomIdParameter:\n    Type: AWS::SSM::Parameter\n    Properties:\n      Name: !Join\n        - '\/'\n        - - !Sub \/${ResourcePrefix}\n          - !Select [ '0', !Split [ '-', !Select [ '2', !Split [ '\/', !Ref AWS::StackId ] ] ] ]\n          - random-id\n      Type: String\n      Value: !Select [ '0', !Split [ '-', !Select [ '2', !Split [ '\/', !Ref AWS::StackId ] ] ] ]\n\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u672c\u8a18\u4e8b\u3067\u691c\u8a3c\u3057\u305f\u5185\u5bb9\u306f\u5b9f\u9a13\u7684\u306a\u3082\u306e\u3067\u3059\u306e\u3067\u3001\u5b9f\u74b0\u5883\u3078\u5c0e\u5165\u3059\u308b\u969b\u306f\u81ea\u5df1\u8cac\u4efb\u3067\u304a\u9858\u3044\u3057\u307e\u3059\u3002 \u306f\u3058\u3081\u306b VPC Endpoint \u3092\u8a2d\u5b9a\u3057\u3066\u3044\u308b\u74b0\u5883\u3067\u3001API Gateway \u306e Regional API \u307e\u305f\u306f Edge &#8230;<\/p>\n","protected":false},"author":60,"featured_media":21355,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_locale":"ja","_original_post":"https:\/\/www.skyarch.net\/blog\/?p=21337","footnotes":""},"categories":[20,343],"tags":[392,354,32],"class_list":{"0":"post-21337","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-aws","8":"category-343","9":"tag-amazon-api-gateway","10":"tag-aws-privatelink","11":"tag-route53","12":"ja"},"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/posts\/21337","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/users\/60"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/comments?post=21337"}],"version-history":[{"count":13,"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/posts\/21337\/revisions"}],"predecessor-version":[{"id":21360,"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/posts\/21337\/revisions\/21360"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/media\/21355"}],"wp:attachment":[{"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/media?parent=21337"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/categories?post=21337"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/tags?post=21337"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}