【问题标题】:Why do I need to hardcode credentials to connect to AWS using the javascript SDK?为什么我需要硬编码凭证才能使用 javascript SDK 连接到 AWS?
【发布时间】:2019-07-30 18:42:30
【问题描述】:

我在这里问过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,它会从我的共享凭证文件中获取凭证。然而,如果您不在本地模式下,它会将所有凭证设置为未定义并依赖 IAM 角色。 文档不是说我不必这样做吗?

但是,如果我将代码更改为此,任何对 athena 的调用都会挂起,直到超时:

export const getAthena = (): AWS.Athena => {
    return new AWS.Athena();
};

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

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

  1. 我是否在第二个示例中以错误的方式创建了 AWS.Athena()
  2. 如何解决此问题以找出它挂起的原因?
  3. 根据文档,底部示例不应该与顶部执行相同的操作吗?

【问题讨论】:

  • 这两个 sn-ps 的作用不同,以防您有相互竞争的凭据来源。根据文档,正在从各种来源检索凭证:IAM、credentials 文件、环境变量等。文档没有说明优先级,但它必须以某种方式(确定性地)决定使用哪个。因此,您的连接挂起是因为它使用了具有更高优先级的凭据,而这些凭据恰好是无效的,对吗?我的猜测是这是因为地区变化。
  • @freakish 据我所知,我没有。在本地,我想我只有一个凭据文件。再说一次,我一般对 IAM 了解不多。如果我的本地计算机在 VPN 上,它可以有一个 IAM 角色吗?我认为 IAM 角色仅适用于 AWS 服务器/服务。
  • 是的,如果您没有明确设置 IAM,我认为它并不重要。虽然我也不是 IAM 专家。无论哪种方式,我认为这个问题与区域设置有关。因为无法连接。如果凭据无效,您会相对较快地收到错误。您是否尝试过在创建新的AWS.Athena 实例之前调用new AWS.Athena({region: "us-east-1"}) 或仅更新区域?
  • @freakish 是的,它会以同样的方式超时。
  • 很奇怪。您的凭据配置中是否有多个配置文件?如果是,那么默认是第一个吗?

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


【解决方案1】:

所以经过调查,这似乎是因为您的.aws/credentials 文件中没有[default] 配置文件。这是一个特殊的配置文件。我假设客户在找不到时使用空字符串(或空值或其他东西)。老实说,我觉得这很有趣(应该抛出异常)。

无论如何,要解决此问题,要么将您必须的配置文件重命名为 [default],要么在您的代码中设置不同的配置文件。以下是相关文档:

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

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

【讨论】:

    【解决方案2】:

    如果您使用的是 IAM 角色,则无需显式提供任何凭证,无论是否为空:

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

    事实上,这也适用于通过本地环境变量或凭据/配置文件提供的凭据。 SDK 会一一尝试chain of credentials providers

    【讨论】:

    • 我没有在本地使用 IAM 角色(至少不是故意的)。我仅在部署代码时使用 IAM 角色。我的示例几乎已经显示了您在此处所说的内容(您还有 2 行)。
    • 您不需要比我展示的更多的代码。如果您在本地运行 awscli:aws s3 lsaws athena list-named-queries,会发生什么情况?超时了吗?
    • 检查 OP 上的 cmets。问题是我的凭据文件只有一个配置文件,但它没有命名为[default]。你知道我怎么能说我想使用名为 [aws14] 而不是 [default] 的配置文件吗?
    • 在 Mac 或 Linux 上:AWS_PROFILE=aws14 node app.js
    猜你喜欢
    • 2020-01-16
    • 2018-05-14
    • 1970-01-01
    • 2012-11-13
    • 2017-07-31
    • 2013-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多