三歩あるけば物も忘れる

私メタボックル!お腹のお肉の妖精さ!

ユーザ用ツール

サイト用ツール


サイドバー

  
人気ページTOP10

121

Aws:APIGateway:プライベートAPIGatewayを異なるアカウントから呼び出す

Aws/APIGateway/プライベートAPIGatewayを異なるアカウントから呼び出す

サーバーレスを勉強中に、classmethodさんの記事を見て、え?そうなの?と思って試してみた。

イメージは以下の感じで、プライベートAPIGatewayを作成したアカウントAからは勿論、異なるアカウントBからもアクセスさせたい。
ついでにLambdaからのプライベートAPIGateway呼び出しも試してみた

アカウントBのRoute53にアカウントAで作成したAPIGatewayのエンドポイントを、ホストゾーンとレコード追加して
アカウントBで作成したVPCエンドポイントのDNS名と紐づけることで、アカウントBからアカウントAで作成したプライベートAPIGatewayの呼び出しが可能となりました。

VPCエンドポイントで「*.execute-api.ap-northeast-1.amazonaws.com」がワイルドカードで登録されるので
Route53を登録しなくてもプライベートAPIGatewayのURL形式であればエンドポイントに接続されました。

アカウントAでの環境準備

各リソースの作成手順は割愛します、重要な設定値のみです。

APIGatewayの作成

以下の設定値でAPIGatewayを作成。
・エンドポイントタイプ:プライベート
・ID:xxxx
・メソッド:GET
・タイプ:Lambda関数
・ドメイン:https://xxxx.execute-api.ap-northeast-1.amazonaws.com
・ステージ:test
・リソースポリシー:下記の通りvpcidを指定してアクセス許可を設定(参考:https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-vpc-endpoint-policies.html)
 事前にアカウントBのVPCIDも登録しています。
 ※プライベートAPI Gatewayの送信先IPアドレス制限は意味がない(0.0.0.0/0をDenyしてもリクエストできます。)→VPCで送信元偽れますもんね、よく考えたらそらそうか・・・。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:ap-northeast-1:1234567890:xxxx/*"
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:ap-northeast-1:1234567890:xxxx/*",
            "Condition": {
                "StringNotEquals": {
                    "aws:SourceVpc": [
                        "vpc-xxxxa",
                        "vpc-xxxxb"
                    ]
                }
            }
        }
    ]
}

APIGatewayから呼び出されるLambda関数

def lambda_handler(event, context):
    return {
        'isBase64Encoded': False,
        'statusCode': 200,
        'headers': {},
        'body': {"message": "Hello from AWS Lambda"}
    }

APIGatewayを呼び出すLambda関数

エンドポイント経由でアクセスするため、VPC、サブネット、セキュリティグループを指定して作成します。
指定したリソースは下記として説明します。
・VPC:vpc-xxxxa
・サブネット:Lambda-subnet
・セキュリティグループ:Lambda-sg

import urllib.request
import json
 
def lambda_handler(event, context):
    url = "https://xxxx.execute-api.ap-northeast-1.amazonaws.com/test/"
    
    response = urllib.request.urlopen(url)
    
    content = json.loads(response.read().decode('utf8'))
     
    return content

VPCエンドポイントの作成

VPCに設置したLambdaがプライベートAPIGatewayに到達できるようにVPCエンドポイントを作成します。
VPCエンドポイントは、Lambdaからhttpsのインバウンドを許可する必要があります。

指定したリソースは下記になります。
・サービス名:com.amazonaws.ap-northeast-1.execute-api
・VPC:vpc-xxxxa
・サブネット:Lambda-subnet
・セキュリティグループ:Vpcendpoint-sg(Lambda-sgをソースとしたhttpsのインバウンドを許可する)

アカウントAでの実行結果

以上でアカウントAの環境は整ったので、「APIGatewayを呼び出すLambda関数」を実行します。
実行結果は以下の通りで、LambdaからAPIGatewayが呼び出せました。

アカウントBでの環境準備

各リソースの作成手順は割愛します、重要な設定値のみです。

APIGatewayを呼び出すLambda関数

これかアカウントAとソースコードは変わりません。
指定したリソースは下記として説明します。
・VPC:vpc-xxxxb
・サブネット:Lambda-subnet
・セキュリティグループ:Lambda-sg

import urllib.request
import json
 
def lambda_handler(event, context):
    url = "https://xxxx.execute-api.ap-northeast-1.amazonaws.com/test/"
    
    response = urllib.request.urlopen(url)
    
    content = json.loads(response.read().decode('utf8'))
     
    return content

VPCエンドポイントの作成

VPCに設置したLambdaがプライベートAPIGatewayに到達できるようにVPCエンドポイントを作成します。
VPCエンドポイントは、Lambdaからhttpsのインバウンドを許可する必要があります。

指定したリソースは下記になります。
・サービス名:com.amazonaws.ap-northeast-1.execute-api
・VPC:vpc-xxxxb
・サブネット:Lambda-subnet
・セキュリティグループ:Vpcendpoint-sg(Lambda-sgをソースとしたhttpsのインバウンドを許可する)

アカウントBでの実行結果

以上でアカウントBの環境は整ったので、「APIGatewayを呼び出すLambda関数」を実行します。
実行結果は以下の通りで、アカウントAと同様にLambdaからAPIGatewayが呼び出せました。

まとめ

classmethodさんの記事は正しかった。
AWS のプライベートネットワーク内においては特に制限をしない限り、誰でもアクセスできる API Gateway です。←まさにこれでした。

その他

LambdaからAPIGatewayの呼出し方は下記のスクリプトでも良いかもメモ

import urllib3
import json

def lambda_handler(event, context):
    url = "https://xxxx.execute-api.ap-northeast-1.amazonaws.com/test"
    
    http = urllib3.PoolManager()
    
    response = http.request("GET",url)
    
    content = json.loads(response.data.decode("utf-8"))
    
    return content

Aws/APIGateway/プライベートAPIGatewayを異なるアカウントから呼び出す.txt · 最終更新: 2021/06/02 by admin