AWS SDK for JavaScript v3はMFA認証を自動でやってくれなくなったぞ
AWS SDK for JavaScript を v2 から v3 にアップデートしたら、MFA認証が失敗するという思わぬ落とし穴に遭遇した。
ローカル開発環境で、~/.aws/credentials
の設定と MFA (Multi-Factor Authentication) を使って一時クレデンシャルを取得していたのだが、v3ではMFAの対話的認証を自動でやってくれないらしい。
v2ではどうだったの?
v2では AWS.SharedIniFileCredentials
を使うことで、.aws/config
に mfa_serial
が設定されていれば、自動的にMFAプロンプトが表示されて認証してくれていた。
ところが、v3はモジュールベースになったことで @aws-sdk/credential-providers の fromIni()
を使っても、デフォルトではMFAを要求するプロファイルに対して何の対話も行われずに失敗してしまう。……これが原因だったか。
mfaProvider
を使って自前で入力プロンプトを出す
解決策:v3では fromIni()
に mfaProvider
を渡して、自前でコード入力を処理する必要がある。
実装例:
import readline from 'readline';
import { fromIni } from "@aws-sdk/credential-providers";
export const mfaProvider = async () => {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
return new Promise((resolve) => {
rl.question(`Enter MFA code for the following account: `, (answer) => {
rl.close();
resolve(answer);
});
});
};
export const getCredentials = () => {
return fromIni({
profile: process.env.AWS_PROFILE, // AWS_PROFILE 環境変数を使用
mfaProvider
});
};
このコードはMFA認証部分をライブラリ化していて、ツール側でこれを利用して実際にMFA認証していく。
DynamoDBにアクセスするような場合は以下のようにする。
実装例:
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { getCredentials } from "./credential.js";
const REGION = "ap-northeast-1";
const getAllData = async (credentials) => {
const client = new DynamoDBClient({
region: REGION,
credentials
});
// ここでデータ取得処理を行う
};
(async () => {
try {
const credentials = await getCredentials();
await getAllData(credentials);
} catch (e) {
console.error("Error:", e);
}
})();
スクリプトを実行すると、CLIで
Enter MFA code for the following account:
という表示がされて一時クレデンシャルを入力できるようになる。
まとめ
-
v2ではMFAを自動で処理してくれたが、v3ではそうはいかない。
-
fromIni() に mfaProvider を指定すれば、対話的にMFAコードを入力させることが可能。。
-
ローカルでMFAが必須なプロファイルを使っている人は、v3移行時に要注意!
もう少しスムーズにMFA認証できるようにならないかな~
Discussion