Я спросил здесь этот другой вопрос, что наводит меня на мысль, что по умолчанию JavaScript AWS SDK ищет учетные данные в нескольких местах в вашей среде, и вам не нужно ничего делать. Порядок мест, которые он проверяет, указан здесь: https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-node.html.
У меня есть рабочий код, который подключается к AWS Athena. Я могу заставить его работать только в том случае, если я жестко запрограммирую учетные данные вручную, что, похоже, противоречит приведенной выше документации. Вот мой код:
export const getAthena = (): AWS.Athena => {
if (process.env["LOCAL_MODE"] === "true") {
const awsCredentials = {
region: "us-east-1",
accessKeyId: awsCredentialsParser("aws_access_key_id"),
secretAccessKey: awsCredentialsParser("aws_secret_access_key"),
sessionKey: awsCredentialsParser("aws_session_token")
};
AWS.config.update(awsCredentials);
let credential = new AWS.Credentials({
accessKeyId: awsCredentials.accessKeyId,
secretAccessKey: awsCredentials.secretAccessKey,
sessionToken: awsCredentials.sessionKey
});
return new AWS.Athena({credentials: credential, signatureCache: false});
} else {
const awsCredentials1 = {
region: "us-east-1",
accessKeyId: undefined,
secretAccessKey: undefined,
sessionKey: undefined
};
AWS.config.update(awsCredentials1);
return new AWS.Athena({credentials: undefined, signatureCache: false});
}
};
export const awsCredentialsParser = (key: string): string => {
const homeDirectory = os.homedir();
const awsCredentials = fs.readFileSync(homeDirectory + "/.aws/credentials", {encoding: "UTF8"});
const awsCredentialLines = awsCredentials.split("\n");
const lineThatStartsWithKey = awsCredentialLines.filter((line) => line.startsWith(key))[0];
return lineThatStartsWithKey.split(" = ")[1];
};
Как видите, я использую переменную среды под названием «LOCAL_MODE». Если установлено значение true, он получает учетные данные из моего общего файла учетных данных. Принимая во внимание, что если вы не находитесь в локальном режиме, он устанавливает для всех учетных данных значение undefined и вместо этого полагается на роль IAM. Разве в документации не сказано, что мне не нужно этого делать?
Но если я изменю свой код на это, любой вызов афины зависнет, пока не истечет время ожидания:
export const getAthena = (): AWS.Athena => {
return new AWS.Athena();
};
Если я установлю тайм-аут на действительно большое число, это в конечном итоге сообщит мне, что у меня недействительные учетные данные.
Согласно документации, разве второй пример не должен находить учетные данные так же, как и первый? Почему второй пример зависает? Я не хочу писать код выше. Как заставить мой код работать, как в примерах?
AWS.Athena()
неправильно во 2-м примере?@freakish, насколько я могу судить, нет. Локально, я думаю, у меня есть только файл учетных данных. Опять же, я мало знаю об IAM в целом. Может ли мой локальный компьютер иметь роль IAM, если он подключен к VPN? Я думал, что роли IAM применяются только к серверам/сервисам AWS.
Да, я не думаю, что IAM имеет значение, если вы не настроили его явно. Хотя я тоже не эксперт IAM. В любом случае, я думаю, что проблема связана с настройкой региона. Потому что вы не можете подключиться. С неверными учетными данными вы получите сообщение об ошибке относительно быстро. Пробовали ли вы вызывать new AWS.Athena({region: "us-east-1"})
или обновлять только регион перед созданием нового экземпляра AWS.Athena
?
@freakish Да, и время истекает так же.
Странный. У вас есть более одного профиля в вашей конфигурации учетных данных? Если да, то по умолчанию первый?
@причудливый хороший вопрос. У меня только один называется [aws14]
. Я переименовал его в [default]
, и он работал, как и ожидалось. Большое спасибо за помощь!
Если вы используете роль IAM, вам не нужно явно указывать какие-либо учетные данные, нулевые или иные:
const AWS = require('aws-sdk');
const athena = new AWS.Athena();
const params = { ... };
const rc = await athena.startQueryExecution(params).promise();
Фактически, это работает с учетными данными, предоставленными через локальные переменные среды или в файле учетных данных/конфигурации. Есть цепочка поставщиков учетных данных, которые SDK будет пробовать один за другим.
Я не использую роль IAM локально (по крайней мере, не намеренно). Я использую роль IAM только при развертывании кода. Мой пример в значительной степени уже показывает то, что вы сказали здесь (у вас есть 2 дополнительные строки).
Вам не нужно больше кода, чем я показал. Что произойдет, если вы локально запустите awscli: aws s3 ls
и aws athena list-named-queries
? Истечет ли время ожидания?
Проверьте комментарии к ОП. Проблема в том, что в моем файле учетных данных есть только один профиль, но он не назван [default]
. Знаете, как я могу сказать, что хочу использовать профиль с именем [aws14]
вместо [default]
?
На Mac или Linux: AWS_PROFILE=aws14 node app.js
Итак, после расследования кажется, что это (т.е. сбой во втором фрагменте) связано с тем, что у вас нет профиля [default]
в вашем файле .aws/credentials
. Это специальный профиль. Я предполагаю, что клиент использует пустые строки (или нули или что-то еще), когда он не может их найти. Что я нахожу забавным, если честно (должно быть исключение).
В любом случае, чтобы исправить это, либо переименуйте профиль, который вам нужно [default]
, либо настройте другой профиль в своем коде. Вот соответствующие документы:
Я рекомендую использовать переменную окружения AWS_PROFILE
. Сделает ваш код более переносимым.
Эти два фрагмента работают по-разному, если у вас есть конкурирующие источники учетных данных. Согласно документам, учетные данные извлекаются из различных источников: IAM, файл
credentials
, переменные env и т. д. В документах ничего не говорится о приоритете, но он должен каким-то образом (детерминистически) решить, что использовать. Итак, ваше соединение зависает, потому что оно использует учетные данные с более высоким приоритетом, которые оказались недействительными, верно? Я предполагаю, что это из-за смены региона.