AWS SDK для node.js не получает учетные данные при работе в 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, ""));
    });
};

Когда этот код запускается в 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 сможет его подобрать.

Часть журнала поставщика — это всего лишь 4 функции, определенные в коде SDK, 4-я из которых вернет «ECSCredentials», если увидит «AWS_CONTAINER_CREDENTIALS_RELATIVE_URI» в env var.

Как ни странно, кредитная часть журнала является «нулевой» в ECS. Когда я запускаю это локально (где я вручную беру на себя роль), часть журнала 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 }

Что-то не так с моим кодом или моей env var?

Должен ли я распечатать дополнительные журналы, чтобы помочь диагностировать эту проблему?

Пожалуйста, посоветуйте, спасибо.

==========Обновление==========

Я запустил этот код в 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}, он должен был получить правильный ответ.


person Cui Pengfei 崔鹏飞    schedule 14.01.2018    source источник
comment
Вы уверены, что используемый провайдер один и тот же на вашем локальном экземпляре и на экземпляре ec2? Например, экземпляр ec2 мог получить недопустимый кредит от службы метаданных.   -  person Malice    schedule 14.01.2018
comment
@Malice AWS.config.credentials имеет значение null при работе в ECS. мое предположение состоит в том, что это не должно быть нулевым, поскольку AWS_CONTAINER_CREDENTIALS_RELATIVE_URI присутствует в env var. это верное предположение?   -  person Cui Pengfei 崔鹏飞    schedule 14.01.2018
comment
Возможно, вам потребуется инициализировать AWS.EC2MetadataCredentials и назначить его aws.config.credentials. Насколько я знаю, он не делает этого, если это не делается явно   -  person Malice    schedule 14.01.2018
comment
@Malice спасибо за ссылку на документ. мой код не работает в EC2, он работает в контейнерах ECS. в соответствии с этим: docs.aws.amazon.com/AWSJavaScriptSDK/ last/ он должен загрузить учетные данные ecs, если существует AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, что, судя по моему журналу, так и есть   -  person Cui Pengfei 崔鹏飞    schedule 14.01.2018
comment
@Malice я попытаюсь явно установить ECSCredentials и посмотреть, как это пойдет, спасибо   -  person Cui Pengfei 崔鹏飞    schedule 14.01.2018
comment
Ах, я устарел, но я все еще не понимаю, почему вы считаете, что учетные данные были получены приложением?   -  person Malice    schedule 14.01.2018
comment
@Malice github.com/aws/ aws-sdk-js/blob/ в исходном коде sdk, цепочка провайдеров по умолчанию включает учетные данные ecs, поэтому я предполагал, что он подберет это автоматически.   -  person Cui Pengfei 崔鹏飞    schedule 14.01.2018
comment
Давайте продолжим обсуждение в чате.   -  person Malice    schedule 14.01.2018


Ответы (2)


Простой ответ - сделать

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

предположительно, потому что учетные данные для учетных данных aws-sdk не были настроены/настроены неправильно.

person Malice    schedule 14.01.2018
comment
Задача решена. Это было как-то связано с версией узла. Мой код работал в ECS с базовым образом докера: node:8.9.4. Я переключился на node:9.4, последнюю версию, которая решила проблему. Не знаю почему, но сейчас работает. - person Cui Pengfei 崔鹏飞; 26.01.2018

Попробуйте использовать 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.

person Aleksi    schedule 11.08.2020