node.js 的 AWS SDK 在 ECS 中 运行 时未获取凭证
AWS SDK for node.js not picking up credentials when running in ECS
我有这个代码:
const uploadAllToS3 = () => {
console.log("upload useless file to s3, just to test access rights");
new AWS.S3().putObject({
Bucket: scheduledJobsConstants.s3BucketName(),
Key: `test/${new Date()}.txt`, Body: "Hello!",
}, (err) => {
console.log(`env:${inspect(process.env)}
provider:${AWS.CredentialProviderChain.defaultProviders}
cred:${inspect(AWS.config.credentials)}
err:${inspect(err)}`.replace(/(\r\n|\n|\r)/gm, ""));
});
};
当此代码 运行s 在 ecs 中(它承担了一个可以访问 S3 存储桶的角色)时,我将在日志中得到这个:
日志的env部分:
env: {
PATH: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
HOSTNAME: '485bbd95f87d',
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI: '/v2/credentials/be3d4d7c-28b6-47e6-8081-cd746d95cb28',
ECS_CONTAINER_METADATA_FILE: '/opt/ecs/metadata/8c0b731d-49ce-4e19-bf79-64087b433876/ecs-container-metadata.json',
NODE_VERSION: '8.9.4',
YARN_VERSION: '1.3.2',
NPM_CONFIG_PROGRESS: 'false',
HOME: '/root'
}
"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" 存在于 env var 中,因此我认为 sdk 应该能够获取它。
日志的提供者部分只是在 sdk 代码中定义的 4 个函数,如果它在环境变量中看到 "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI",则第 4 个将 return "ECSCredentials"。
St运行gely log的cred部分在ECS中是"null"。
当我 运行 在本地(我手动承担一个角色)时,日志的 cred 部分是 "EnvironmentCredentials",文件被上传到 S3。
日志错误部分为:
{ Forbidden: null
at Request.extractError (/app/node_modules/aws-sdk/lib/services/s3.js:557:35)
at Request.callListeners (/app/node_modules/aws-sdk/lib/sequential_executor.js:105:20) at Request.emit (/app/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
at Request.emit (/app/node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (/app/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/app/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /app/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/app/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (/app/node_modules/aws-sdk/lib/request.js:685:12)
at Request.callListeners (/app/node_modules/aws-sdk/lib/sequential_executor.js:115:18)
message: null,
code: 'Forbidden',
region: null,
time: 2018-01-14T06:30:00.490Z,
requestId: '4E7121D88BA0FEF1',
extendedRequestId: 'D5uiXf5EI/OLHeaPhYX67C384ba3SF1I950N78hJWw8Vv4XGQ0opSLOQlXaxVFW31g252dx8YUc=',
cfId: undefined,
statusCode: 403,
retryable: false,
retryDelay: 118.50320949834776 }
我的代码或我的环境变量有什么问题吗?
我是否应该打印更多日志以帮助诊断此问题?
请指教,谢谢
==========更新==========
我在 ECS 中有 运行 这段代码
const curlCommand = `curl http://169.254.170.2${process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI}`;
exec(curlCommand, (error, stdout, stderr) => {
console.log(`${curlCommand} err:${error} out:${stdout} stderr:${stderr}`);
});
我得到的结果是:
{
"SecretAccessKey": "long string",
"Token": "very long string",
"Expiration": "2018-01-14T08:55:04+0000",
"AccessKeyId": "shorted string"
}
所以如果 sdk 调用了 http://169.254.170.2${process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI},它应该得到正确的响应。
简单的答案就是
AWS.config.credentials = new AWS.ECSCredentials(options);
可能是因为 aws-sdk 凭据的凭据未配置/配置不正确。
尝试使用 AWS.ECSCredentials.get
或 getPromise
以确保在使用之前加载凭据:
const ecsCredentials = new AWS.ECSCredentials({ ... });
await ecsCredentials.getPromise();
AWS.config.credentials = ecsCredentials;
查看此线程以获取更多信息:https://github.com/aws/aws-sdk-js/issues/3281#issuecomment-637171993。
我有这个代码:
const uploadAllToS3 = () => {
console.log("upload useless file to s3, just to test access rights");
new AWS.S3().putObject({
Bucket: scheduledJobsConstants.s3BucketName(),
Key: `test/${new Date()}.txt`, Body: "Hello!",
}, (err) => {
console.log(`env:${inspect(process.env)}
provider:${AWS.CredentialProviderChain.defaultProviders}
cred:${inspect(AWS.config.credentials)}
err:${inspect(err)}`.replace(/(\r\n|\n|\r)/gm, ""));
});
};
当此代码 运行s 在 ecs 中(它承担了一个可以访问 S3 存储桶的角色)时,我将在日志中得到这个:
日志的env部分:
env: {
PATH: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
HOSTNAME: '485bbd95f87d',
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI: '/v2/credentials/be3d4d7c-28b6-47e6-8081-cd746d95cb28',
ECS_CONTAINER_METADATA_FILE: '/opt/ecs/metadata/8c0b731d-49ce-4e19-bf79-64087b433876/ecs-container-metadata.json',
NODE_VERSION: '8.9.4',
YARN_VERSION: '1.3.2',
NPM_CONFIG_PROGRESS: 'false',
HOME: '/root'
}
"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" 存在于 env var 中,因此我认为 sdk 应该能够获取它。
日志的提供者部分只是在 sdk 代码中定义的 4 个函数,如果它在环境变量中看到 "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI",则第 4 个将 return "ECSCredentials"。
St运行gely log的cred部分在ECS中是"null"。 当我 运行 在本地(我手动承担一个角色)时,日志的 cred 部分是 "EnvironmentCredentials",文件被上传到 S3。
日志错误部分为:
{ Forbidden: null
at Request.extractError (/app/node_modules/aws-sdk/lib/services/s3.js:557:35)
at Request.callListeners (/app/node_modules/aws-sdk/lib/sequential_executor.js:105:20) at Request.emit (/app/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
at Request.emit (/app/node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (/app/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/app/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /app/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/app/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (/app/node_modules/aws-sdk/lib/request.js:685:12)
at Request.callListeners (/app/node_modules/aws-sdk/lib/sequential_executor.js:115:18)
message: null,
code: 'Forbidden',
region: null,
time: 2018-01-14T06:30:00.490Z,
requestId: '4E7121D88BA0FEF1',
extendedRequestId: 'D5uiXf5EI/OLHeaPhYX67C384ba3SF1I950N78hJWw8Vv4XGQ0opSLOQlXaxVFW31g252dx8YUc=',
cfId: undefined,
statusCode: 403,
retryable: false,
retryDelay: 118.50320949834776 }
我的代码或我的环境变量有什么问题吗?
我是否应该打印更多日志以帮助诊断此问题?
请指教,谢谢
==========更新==========
我在 ECS 中有 运行 这段代码
const curlCommand = `curl http://169.254.170.2${process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI}`;
exec(curlCommand, (error, stdout, stderr) => {
console.log(`${curlCommand} err:${error} out:${stdout} stderr:${stderr}`);
});
我得到的结果是:
{
"SecretAccessKey": "long string",
"Token": "very long string",
"Expiration": "2018-01-14T08:55:04+0000",
"AccessKeyId": "shorted string"
}
所以如果 sdk 调用了 http://169.254.170.2${process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI},它应该得到正确的响应。
简单的答案就是
AWS.config.credentials = new AWS.ECSCredentials(options);
可能是因为 aws-sdk 凭据的凭据未配置/配置不正确。
尝试使用 AWS.ECSCredentials.get
或 getPromise
以确保在使用之前加载凭据:
const ecsCredentials = new AWS.ECSCredentials({ ... });
await ecsCredentials.getPromise();
AWS.config.credentials = ecsCredentials;
查看此线程以获取更多信息:https://github.com/aws/aws-sdk-js/issues/3281#issuecomment-637171993。