为什么需要使用JavaScript SDK对凭证进行硬编码才能连接到AWS?

时间:2019-07-30 18:42:30

标签: javascript amazon-web-services aws-sdk amazon-athena

我在这里问过this other question,这使我相信,默认情况下,JavaScript AWS开发工具包无需执行任何操作即可在您环境中的许多位置查找凭证。它检查的位置顺序在此处列出: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();
};

如果我将超时设置为一个非常大的数字,它最终会让我知道我的凭证无效。

根据文档,第二个示例不应该像第一个示例那样找到凭证吗?为什么第二个示例挂起?我不想写上面的代码。如何使我的代码像示例一样工作?

  1. 在第二个示例中,我是否以某种错误的方式创建了AWS.Athena()
  2. 如何解决此问题以弄清楚其为何挂起?
  3. 根据文档,底部示例是否应该与顶部示例做相同的事情?

2 个答案:

答案 0 :(得分:2)

因此,经过调查后,这似乎是(第二个代码段中的失败)是因为您的[default]文件中没有.aws/credentials个人资料。这是一个特殊的配置文件。我假设客户端找不到时使用空字符串(或null或其他内容)。老实说我觉得很有趣(应该抛出一个例外)。

无论如何,要解决此问题,可以将配置文件重命名为[default]或在代码中设置其他配置文件。以下是相关文档:

https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-shared.html

我建议使用AWS_PROFILE环境变量。将使您的代码更具可移植性。

答案 1 :(得分:0)

如果您使用的是IAM角色,则无需显式提供任何凭据(为null或其他方式):

const AWS = require('aws-sdk');
const athena = new AWS.Athena();
const params = { ... };
const rc = await athena.startQueryExecution(params).promise();

实际上,这可以与通过本地环境变量提供的凭据一起使用,也可以在凭据/配置文件中使用。 SDK会一一尝试chain of credentials providers