LambdaからAPI Gateway(IAM認可)へのアクセス方法 [Node.js版]


AWS上でServerlessかつMicroservicesな構成の場合、Lambda内から別サービスのAPI Gatewayにアクセスすることがある。
API GatewayがIAMでアクセス制限がかかっている場合のアクセス方法が分からなかったので調査した。

※ Python版はこちら

前提

  • Lambda (Node.js 10.x)
  • LambdaにIAM Role付与済み
  • API Gateway(IAM認可)作成済み

※ API Gatewayの設定方法やIAM Roleの内容などはここでは取り扱わない

結論

aws-sdkのSigners.V4で署名する。

index.js
const https = require("https")
const AWS = require("aws-sdk")

exports.handler = async (event) => {
  const HOST = "XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com"
  const STAGE = "dev"
  const PATH = "/your/resource"

  const url = `https://${HOST}/${STAGE}${PATH}`
  const req = new AWS.HttpRequest(url, process.env.AWS_REGION)
  req.method = "GET"  // Default => "POST"
  req.headers.host = HOST

  // Sign
  const signer = new AWS.Signers.V4(req, "execute-api", true)
  signer.addAuthorization(AWS.config.credentials, AWS.util.date.getDate())

  // Request
  const res = await new Promise(resolve => https.get(req.endpoint.href, req, resolve))
  const body = await new Promise(resolve => res.on("data", resolve))

  // Do something 
}

AWS.Signers.V4 で AWS.HttpRequest を署名する。
⇒ 下記のようなHeadersが設定される

req.headers
{
  'X-Amz-Date': '20190628T180333Z',
  'x-amz-security-token': 'AgoJb3JpZ3luX2VjEBgaDmFwLW6vcnRoZWFzdC0xIkcwRQIgXKqUW7xJYR7xjI8r3A8867/J/258UZa3dVZTZXJhZdoCIQCtfBGGCJQR2RIGAaFMUzXdr4MXYzVapq0dUV8tN6QWGSqAAghhEAIaDDM1OTAzMDQzODQ5MSIMuUdqb7U/zKQD0S6GKt0BOkhXekZuxE8LCL9u8ktGjEeQJGHXiRvyfQ8ohzGRlWzmql66Ao1ArjTjYB1Bw7hbnFs4EUylvwc1XBvbEG/OEyWm1rpbZqe5U5Jg0Z9HY8UvJ2wrjKTH4OBMIYMXk4ZdHu9djIx+6d1Ap0E2F2SAtyMsaG75gFuNOx6frG7T0ZFj9t/pT+5HfxE5349VbxaBX6PvRvOIDfLXqv2UacY9eq3gRkkCNOlBm/4Z+iHyQLkWxkOeG05YIx2r7oeeBqN/459KeKU/pDJMcc/QbnTilCQx+oedEmlV+HRfVIswmPbY6AU6tAHD/gc0T1Rszlg1QgZ7aytsID5JvZCaO6/0SYx0C6mx2G/vrQQivQlxCkK396anWK+sVu69goOxay8cs+wov5+TVtL+1ybPYsMJIv6Pb0/zNS82jyh2Va1YOZ8Ep/i/VHrvPVgVLL1419Ly92MhkPZqMecDiniomEzfBchLYpB+eZ/+B+8+SnqOBuooz+QiF+y8doSBMj24ahhEaa7ErGC/rTI1VuT0GSN8a43N1hpkZ7O9Vlg=',
  Authorization: 'AWS4-HMAC-SHA256 Credential=ASIAVHFXXXXXXXXXXXXX/20190628/ap-northeast-1/execute-api/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature=ac00aaab0b00fe0a000000e0fd0a00c00aab00000b0000a0a000bddb0b000d'
}

AWS.HttpRequest 自体はリクエストを発行してくれないので、別途httpsやrequestsなどでリクエストを送る必要がある。

参考

https://docs.aws.amazon.com/ja_jp/general/latest/gr/sigv4_signing.html
https://www.cloudspecialist.uk/2017/04/08/How-to-make-custom-IAM-authenticated-requests-to-AWS-API-Gateway/
https://qiita.com/paper2/items/cea6021512132f070403
https://qiita.com/toshihirock/items/a92cbda51d5f469bb0ac
https://qiita.com/crifff/items/6dff429555c898a19758