如何在Javascript aws-sdk中使用MFA



我有一个基础设施,在该基础设施中,AWS登录以角色为基础,需要来自MS验证器的MFA,该验证器弹出在移动设备上用于接受或拒绝。通常在CLI上,我们使用saml2aws,它会生成具有假定角色的临时访问密钥密钥。

我试图在我的nodejs中使用aws-sdk,并试图验证凭据,但没有得到任何弹出窗口,并得到以下错误。

请提出实现这一目标的方法或途径。

const AWS = require('aws-sdk');
var eks = new AWS.EKS({ accessKeyId: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", secretAccessKey : "gsdhjfkjbkbfvfkqbvfhvqhfvqhfv", region: "us-west-2"});
var params = { name: "testing" };

eks.describeCluster(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else     console.log(data);           // successful response
});

执行上述代码后:我收到以下错误:

UnrecognizedClientException: The security token included in the request is invalid.
at Object.extractError (D:Prashantkubernetes-appnode_modulesaws-sdklibprotocoljson.js:52:27)
at Request.extractError (D:Prashantkubernetes-appnode_modulesaws-sdklibprotocolrest_json.js:55:8)
at Request.callListeners (D:Prashantkubernetes-appnode_modulesaws-sdklibsequential_executor.js:106:20)
at Request.emit (D:Prashantkubernetes-appnode_modulesaws-sdklibsequential_executor.js:78:10)
at Request.emit (D:Prashantkubernetes-appnode_modulesaws-sdklibrequest.js:688:14)
at Request.transition (D:Prashantkubernetes-appnode_modulesaws-sdklibrequest.js:22:10)
at AcceptorStateMachine.runTo (D:Prashantkubernetes-appnode_modulesaws-sdklibstate_machine.js:14:12)
at D:Prashantkubernetes-appnode_modulesaws-sdklibstate_machine.js:26:10
at Request.<anonymous> (D:Prashantkubernetes-appnode_modulesaws-sdklibrequest.js:38:9)
at Request.<anonymous> (D:Prashantkubernetes-appnode_modulesaws-sdklibrequest.js:690:12) {
code: 'UnrecognizedClientException',
time: 2020-11-03T22:36:19.516Z,
requestId: '2e3486d0-3219-410c-8963-970958c5c14d',
statusCode: 403,
retryable: false,
retryDelay: 91.55836550904752
}

有多种方法可以获得证书,AWS文档建议使用官方的npm包"aws-sdk/凭证提供者";

其中,我发现最有用的是:

  • fromEnv:从环境变量中获取相关凭据。

    也是CI脚本的理想选择。

  • fromIni:它使用您的~/.aws/config和凭据文件。

示例:

import { ListBucketsCommand, S3Client } from "@aws-sdk/client-s3";
import { fromIni, fromEnv } from "@aws-sdk/credential-providers";
import * as readline from "readline";
function getCredentials(ci = process.env.CI) {
if (ci) {
return fromEnv();
}
// This assumes that you've set-up your ~/.aws/config and credentials!
return fromIni({
profile: "MY-PROFILE",
mfaCodeProvider: async (serial) => await prompt(
`Type the mfa token for the following account: ${serial}n`
),
});
}

const s3Client = new S3Client({
credentials: getCredentials(),
});
const test = await s3Client.send(new ListBucketsCommand({}));
console.log("Response:", test);

// Helper function for node-js
function prompt(query) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
return new Promise((resolve) =>
rl.question(query, (ans) => {
rl.close();
resolve(ans);
})
);
}

通过将前面的代码段保存为"test.mjs",我们现在可以测试与AWS各种服务的连接(S3是最简单的,这里是一个例子(。

所以我们现在可以使用awsume这样的程序来扮演一个角色;为我们获取所有相关的环境变量,看看给定的角色是否成功地获取了我们的数据,或者我们可以直接键入MFA 提供给我们的令牌

示例:

$ node test.mjs
Type the mfa token for the following account: <some account>
<Token from your Authenticator App>
Response: <etc>

$ source awsume MY-PROFILE
Enter MFA token: <MFA token>
[MY-PROFILE] Role credentials will expire # <Some date>
$ CI=true node test.mjs
Response: # <etc>

编辑:一段时间后,我们在EC2实例内部运行此代码时遇到问题。事实证明,在这种情况下,凭证都是";"烘烤";并且没有必要使用凭证提供商

原始getCredentials可适用于:

function getCredentials(ci = process.env.CI, in_ec2 = process.env.CI) {
if (in_ec2) {
return undefined;
}
if (ci) {
return fromEnv();
}
// This assumes that you've set-up your ~/.aws/config and credentials!
return fromIni({
profile: "MY-PROFILE",
mfaCodeProvider: async (serial) => await prompt(
`Type the mfa token for the following account: ${serial}n`
),
});
}

此请求已完成。有点棘手,但已经完成了。评论是否有其他人会让你知道解决方案。

最新更新