AWS CLIおよびAWS SDK for JS v2は正常に実行できるのにAWS SDK for JS v3のみ認証が上手くいかない時の対処

2022.05.14

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部 IoT事業部の若槻です。

今回は、AWS CLIおよびAWS SDK for JS v2は正常に実行できるのにAWS SDK for JS v3のみ認証が上手くいかないという事象に遭遇したので、対処方法を書き残しておきます。

先に結論

  • AWS SDK for JavaScript v3の認証では、環境変数AWS_PROFILEが優先して使用される。
  • AWS CLIおよびAWS SDK for JavaScript v2の認証では、環境変数AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYおよびAWS_SESSION_TOKENが優先して使用される。
  • よってそれぞれ優先使用される環境変数に格納された情報が正しくなければ、認証が正常に行えない事象が起こりうる。

環境

  • aws-sdk@2.1135.0
  • @aws-sdk/client-s3@3.88.0
  • aws-cli/2.4.16 Python/3.8.8 Darwin/20.6.0 exe/x86_64 prompt/off

事象

次のようにSTS:AssumeRoleによる認証により一時クレデンシャルを取得し、環境変数AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYおよびAWS_SESSION_TOKENに格納しました。ちなみに、この時使用しているhoge-profileプロファイルは、AssumeRoleを行う権限しか付与されていない認証情報となります。

$ AWS_PROFILE=hoge-profile
$ TOKEN_CODE=123456
$ AWS_STS_CREDENTIALS=`aws sts assume-role \
  --profile default \
  --role-arn $(aws configure get ${AWS_PROFILE}.role_arn) \
  --role-session-name ${AWS_PROFILE}-session \
  --serial-number $(aws configure get ${AWS_PROFILE}.mfa_serial) \
  --duration-seconds $((60*60*12)) \
  --token-code ${TOKEN_CODE}`
export AWS_ACCESS_KEY_ID=`echo "${AWS_STS_CREDENTIALS}" | jq -r '.Credentials.AccessKeyId'`
export AWS_SECRET_ACCESS_KEY=`echo "${AWS_STS_CREDENTIALS}" | jq -r '.Credentials.SecretAccessKey'`
export AWS_SESSION_TOKEN=`echo "${AWS_STS_CREDENTIALS}" | jq -r '.Credentials.SessionToken'`

これによりAWS CLIは、認証は問題なくできており、コマンド実行も正常に行えています。

$ aws s3 ls
2022-04-24 02:31:48 awscdkv2projectstack-hogebucketb99ea3ad-pu96882yudl4
2022-04-27 20:12:42 awscdkv2projectstack-websitebucket75c24d94-1df6db2s7rqkz
...

しかし次のAWS SDK for JavaScript v3を使用したスクリプトの場合。

index.js

//AWS SDK for JavaScript v3
import { S3Client, ListBucketsCommand } from '@aws-sdk/client-s3';

const client = new S3Client({});
const command = new ListBucketsCommand({});
const response = await client.send(command);

console.log(response.Buckets);

実行するとエラーとなってしまいます。

$ node index                                                                          
/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/20220513-awssdk/node_modules/@aws-sdk/credential-provider-ini/dist-cjs/resolveAssumeRoleCredentials.js:43
            throw new property_provider_1.CredentialsProviderError(`Profile ${profileName} requires multi-factor authentication, but no MFA code callback was provided.`, false);
                  ^

CredentialsProviderError: Profile hoge-profile requires multi-factor authentication, but no MFA code callback was provided.

原因、対処

AWS SDK for JavaScript v3の場合のみAssumeRole元のプロファイルが認証に使われてしまっていることが原因でした。

環境変数AWS_PROFILEを削除することにより、AWS SDK for JavaScript v3の場合も正常に実行できるようになりました。

$ unset AWS_PROFILE

$ node index
[
  {
    Name: 'awscdkv2projectstack-hogebucketb99ea3ad-pu96882yudl4',
    CreationDate: 2022-04-23T17:31:48.000Z
  },
  {
    Name: 'awscdkv2projectstack-websitebucket75c24d94-1df6db2s7rqkz',
    CreationDate: 2022-04-27T11:12:42.000Z
  },
  ...
]

ちなみにAWS SDK for JavaScript v2なら発生しない

ちなみにAWS SDK for JavaScript v2であれば事象は発生しませんでした。

index2.js

import AWS from 'aws-sdk';

var s3 = new AWS.S3({ apiVersion: '2006-03-01' });

s3.listBuckets(function (err, data) {
  if (err) {
    console.log('Error', err);
  } else {
    console.log('Success', data.Buckets);
  }
});

環境変数AWS_PROFILEを指定した状態で上記スクリプトを実行しても、正常に実行できています。

$ export AWS_PROFILE=hoge-profile
$ node index2
Success [
  {
    Name: 'awscdkv2projectstack-hogebucketb99ea3ad-pu96882yudl4',
    CreationDate: 2022-04-23T17:31:47.000Z
  },
  {
    Name: 'awscdkv2projectstack-websitebucket75c24d94-1df6db2s7rqkz',
    CreationDate: 2022-04-27T10:57:22.000Z
  },
  ...
]

おわりに

AWS CLIおよびAWS SDK for JS v2は正常に実行できるのにAWS SDK for JS v3のみ認証が上手くいかない時の対処についてでした。

どうやら両者で使用する認証情報の優先順位が異なるようです。気を付けたいですね。

参考

以上