API GatewayでIAM認証を設定して、SigV4署名を実装する機会があったので、備忘録としてまとめる。
IAM認証とは
AWS APIGatewayのAPIを叩くときに使用する認証方法のうちの一つ。事前に権限を絞ったIAMユーザを用意しておき、APIの実行の際にIAMユーザの認証を要求する。認証されたIAMユーザが当該のAPIの実行を認可されている場合に、正常にAPIが応答を返す。
SignV4署名とは
上記IAM認証を実現するための手法。IAMユーザの認証にはアクセスキーとシークレットキーが必要だが、シークレットキーを外部にハードコーディングする訳にもいかないのでSignV4署名を発行して、署名をヘッダに入れることで認証を行う。
注意点
const core = require('aws-sdk/lib/core');
const aws = require('aws-sdk');
// アクセスキーとシークレットアクセスキーを設定
const accessKey = 'XXXXXXXXX';
const secretKey = 'XXXXXXXXX';
const credential = new aws.Credentials(accessKey, secretKey);
exports.handler = async (event) =>{
let method = event.method;
let url = event.url;
const res = main(url,method,event.requestBody);
return res;
};
function main(apiurl,method,requestBody) {
// サービス名は、API GatewayのAPIの場合は、execiute-api固定です。
const serviceName = "execute-api";
// Signers.V4クラスのコンストラクタに渡すオプションを作成します。
const options = {
// api gatewayのURL
url: apiurl,
headers: {}
};
// api gatewayのURLからホスト、パス、クエリストリングを抽出
const parts = options.url.split('?');
const host = parts[0].substr(8, parts[0].indexOf("/", 8) - 8);
const path = parts[0].substr(parts[0].indexOf("/", 8));
const querystring = parts[1];
// V4クラスのコンストラクタの引数に沿う形でoptionsを作成
const now = new Date();
options.headers.host = host;
options.pathname = () => path;
options.methodIndex = method;
options.search = () => querystring ? querystring : "";
options.region = 'ap-northeast-1';
options.method = method;
if(method == "POST"){
options.body = requestBody;
options.headers['Content-Type'] = "application/json";
}
// V4クラスのインスタンスを作成
const signer = new core.Signers.V4(options, serviceName);
// SigV4署名
signer.addAuthorization(credential, now);
//署名されたヘッダーを出力
console.log(options.headers);
const response = {
statusCode: 200,
// body: JSON.stringify(array2responseData(responseArray))
body: options.headers
};
return response;
}
このlamdaにPOSTする内容は以下の通り
{
"method": "XXXX",
"url": "XXXXXXXXX"
"requestBody":XXXX
}