在 ECS 中运行时,适用于 node.js 的 AWS 开发工具包未获取凭证

Posted

技术标签:

【中文标题】在 ECS 中运行时,适用于 node.js 的 AWS 开发工具包未获取凭证【英文标题】:AWS SDK for node.js not picking up credentials when running in ECS 【发布时间】:2018-06-23 03:51:48 【问题描述】:

我有这个代码:

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, ""));
    );
;

当这段代码在 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 个函数,如果在 env var 中看到“AWS_CONTAINER_CREDENTIALS_RELATIVE_URI”,第 4 个函数将返回“ECSCredentials”。

奇怪的是,日志的 cred 部分在 ECS 中是“null”。 当我在本地运行它时(我手动承担角色),日志的凭据部分是“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,它应该会得到正确的响应。

【问题讨论】:

您确定在您的本地和 ec2 实例上使用的提供程序是相同的吗?例如,ec2 实例可能从元数据服务中获得了无效的凭据 @Malice AWS.config.credentials 在 ECS 中运行时为空。我的假设是这不应该为空,因为“AWS_CONTAINER_CREDENTIALS_RELATIVE_URI”存在于环境变量中。这是一个正确的假设吗? 您可能需要初始化 AWS.EC2MetadataCredentials 并将其分配给 aws.config.credentials。据我所知,除非明确完成,否则它不会这样做 docs.aws.amazon.com/AWSjavascriptSDK/latest/AWS/… @Malice 感谢您提供文档链接。我的代码没有在 EC2 中运行,而是在 ECS 容器中运行。根据这个:docs.aws.amazon.com/AWSJavaScriptSDK/latest/… 如果 AWS_CONTAINER_CREDENTIALS_RELATIVE_URI 存在,它应该加载 ecs 凭证,从我的日志来看就是这种情况 【参考方案1】:

简单的答案是做

AWS.config.credentials = new AWS.ECSCredentials(options);

可能是因为 aws-sdk 凭证的凭证没有配置/配置不正确。

【讨论】:

问题已解决。它在某种程度上与节点版本有关。我的代码在 ECS 中运行,带有一个基本的 docker 镜像:node:8.9.4。我切换到 node:9.4,这是解决问题的最新版本。不知道为什么,但它现在可以工作了。【参考方案2】:

尝试使用AWS.ECSCredentials.getgetPromise 以确保在使用之前加载凭据:

const ecsCredentials = new AWS.ECSCredentials( ... );
await ecsCredentials.getPromise();
AWS.config.credentials = ecsCredentials;

查看此线程以获取更多信息:https://github.com/aws/aws-sdk-js/issues/3281#issuecomment-637171993。

【讨论】:

以上是关于在 ECS 中运行时,适用于 node.js 的 AWS 开发工具包未获取凭证的主要内容,如果未能解决你的问题,请参考以下文章

在适用于 Linux 的 Oracle Agile 9.3.0.2 中运行时 Apache POI 中的 java.lang.IncompatibleClassChangeError

当应用程序在本地运行时,Node.js 能够连接到 MySQL 容器,但当应用程序在容器中运行时无法连接

防止 Java 7/8 采样声音在播放时点击(适用于 6)

应用程序正在模拟器中定位,但在实际的 android 设备中运行时没有

Node.js 在 Windows 7 中不运行 HelloWorld 程序

Node JS - 数据库调用异步? [复制]