📝

VPC Lambda から プライベート API Gateway 経由で非 VPC Lambda を呼び出してみた

2022/10/10に公開

今回は VPC Lambda から プライベート API Gateway 経由で非 VPC Lambda を呼び出してみました。

構成図

非 VPC Lambda

以下の設定で作成しました。

  • ランタイム: Node.js 16.x
  • コード
index.js
exports.handler = async (event) => {
    // TODO implement
    console.log(JSON.stringify(event, null, 2))
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};

VPC Lambda

以下の設定で作成しました。

  • ランタイム: Node.js 16.x
  • レイヤー: axios をインストールしたレイヤー
    レイヤーについては AWS 公式ドキュメントおよび Zenn ブログをご覧ください。
  • VPC
    • サブネット: プライベートサブネット × 1
    • セキュリティグループ
      • インバウンドルール: なし
      • アウトバウンドルール: デフォルト (全許可)
  • コード
index.js
const axios = require('axios');

exports.handler = async (event) => {
    const res = await axios.get("https://{my-api-id}.execute-api.ap-northeast-1.amazonaws.com/{api-stage-name}");
    console.log(res.data)
    return res.data;
};

VPC エンドポイント

AWS 公式ドキュメントを参考に以下の設定で作成ました。

  • サービス名: com.amazonaws.ap-northeast-1.execute-api
  • VPC: VPC Lambda と同じ VPC
  • サブネット: VPC Lambda と同じプライベートサブネット
  • セキュリティグループ
    • インバウンドルール: すべてのトラフィックを VPC の CIDR (10.0.0.0/16) から許可
    • アウトバウンドルール: デフォルト (全許可)
  • ポリシー
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Deny",
			"Principal": "*",
			"Action": "execute-api:Invoke",
			"Resource": "arn:aws:execute-api:ap-northeast-1:{account-id}:<my-api-id>/*",
			"Condition": {
				"StringNotEquals": {
					"aws:sourceVpc": "{my-vpc-id}"
				}
			}
		},
		{
			"Effect": "Allow",
			"Principal": "*",
			"Action": "execute-api:Invoke",
			"Resource": "arn:aws:execute-api:ap-northeast-1:{account-id}:{my-api-id}/*"
		}
	]
}

上記のポリシーで VPC 内からの API 呼び出しのみ許可するように設定しています。

プライベート API Gateway

上記 2 つの AWS 公式ドキュメントを参考に以下の設定で作成ました。

  • API タイプ: REST API
  • エンドポイントタイプ: プライベート
  • メソッド: GET
  • Lambda プロキシ統合の使用: 有効
  • Lambda 関数: 作成済みの非 VPC Lambda
  • リソースポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:ap-northeast-1:{account-id}:{my-api-id}/*",
            "Condition": {
                "StringNotEquals": {
                    "aws:sourceVpce": "{my-vpc-endpoint-id}"
                }
            }
        },
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:ap-northeast-1:{account-id}:{my-api-id}/*"
        }
    ]
}

上記のポリシーで VPC エンドポイントからの API 呼び出しのみ許可するように設定しています。

動作確認

VPC Lambda からテスト実行してみます。

レスポンスを取得できました。

トラブルシューティング

エラーが発生する場合には以下の点を確認してください。

  • VPC Lambda
    • レイヤーを登録して関数に追加したか
    • セキュリティグループのアウトバウンドルールで通信を許可しているか
  • VPC エンドポイント
    • サブネットが VPC Lambda と同じか
    • セキュリティグループで VPC Lambda からの通信を許可しているか
    • ポリシーで VPC からのアクセスを許可しているか
  • API Gateway
    • リソースポリシーで VPC エンドポイントからのアクセスを許可しているか
    • デプロイしたか
  • その他
    • ネットワーク ACL などのその他のファイアウォール機能で通信を許可しているか
    • Lambda のコードをデプロイしたか
    • API Gateway のテスト実行はうまくいくか
      • 成功する場合: VPC Lambda から API Gateway までの設定を見直す
      • 失敗する場合: API Gateway と 非 VPC Lambda の設定を見直す
    • ログを確認する

まとめ

今回は、VPC Lambda から プライベート API Gateway 経由で非 VPC Lambda を呼び出してみました。
VPC Lambda やプライベート API Gateway はあまり使ったことがなかったのですが、簡単に設定できました。

参考になれば幸いです。

参考資料

Discussion