きっかけ
とあるプロジェクトで使った別で作成された既存のAPIを実行するのにIAM認証が有効になっていたためIAMが必要だったのですが、これまでAPIキーでしか認証を通したことがなかったため実装するのに悪戦苦闘しました。
色々調べてうまく行ったのでここにまとめてみました。
やりたいこと
- CDKから作成しているラムダ関数から別で作成されたIAM認証を通してAPIを実行する
- postmanからAPIの動作確認をしたいためpostmanでのIAM認証設定
ラムダ関数の設定
CDKでの権限設定
ラムダはこのように定義しました⇩
cdk/lib/lambda.ts
const lambda = new lambda.Function(
this,
`lambda-${props.envName}`,
{
runtime: Runtime.NODEJS_18_X,
handler: 'index.handler',
code: lambda.Code.fromAsset('lambda/'), // ラムダコードのパス
environment: { // ラムダの環境変数
REGION: this.region,
apiGatewayEndpoint: props.apiGatewayEndpoint,
},
timeout: Duration.seconds(900),
layers: [lambdaLayer], // ラムダレイヤーの設定
}
);
ラムダのIAMにAPIを実行可能にするポリシーをロールに追加する必要があるので、CDKでこのように取り付けました。
cdk/lib/lambda.ts
lambda.role?.addManagedPolicy(
iam.ManagedPolicy.fromAwsManagedPolicyName(
'AmazonAPIGatewayInvokeFullAccess'
)
);
これでCDKの方で必要な権限まわりの設定は完了です!
ラムダのコードでIAM認証する方法
lambda/credential.ts
import { SignatureV4 } from '@aws-sdk/signature-v4';
import { defaultProvider } from '@aws-sdk/credential-provider-node';
import { Sha256 } from '@aws-crypto/sha256-js';
import { HttpRequest } from '@aws-sdk/protocol-http';
export const getSignedHttpRequest = async (url: string, body: object) => {
const serviceName = 'execute-api'; // APIを実行するため
const parts = url.split('?');
const host = parts[0].substring(8, parts[0].indexOf('/', 8));
const path = parts[0].substring(parts[0].indexOf('/', 8));
const req = new HttpRequest({
headers: {
host,
},
protocol: 'https:',
hostname: host,
method: 'POST', //実行したいAPIのメソッドに変える
path: path,
body: JSON.stringify(body),
});
const signer = new SignatureV4({
credentials: defaultProvider(), //自動的にラムダのアクセスキーとシークレットキーを使って認証コードを発行してくれます
region: process.env.envName
service: serviceName,
sha256: Sha256,
});
const signedHttpRequest = await signer.sign(req);
return signedHttpRequest;
};
これで設定完了です!ラムダからAPI実行できるようになると思います。
注意点
cdkもしくはマネコンからラムダのロールにAPIを実行するポリシーを付与できていないと
"User: arn:aws:iam::*:user/api-unvalid is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api...."
というエラーが出てしまうので注意です。
Postmanの設定
- ポストマンの
Authorization
タグをクリックします - Typeで
AWS Signature
を選択します。 - コンソールから作成した
AccessKey
とSecreteKey
を貼り付けます。(APIInvocationの権限を付与したもの) - AWS Regionを設定する。東京の場合は
ap-northeast-1
になります。
これで設定完了です!PostmanからもAPI実行できるようになりました!