如何使用AWS cli在MFA上下文中获取访问密钥?

时间:2020-06-25 16:35:03

标签: amazon-web-services aws-cli aws-sts aws-credentials

我正在开发一个将在现有EC2实例上运行的简单应用程序。 AWS帐户已通过MFA保护。我们使用主要帐户,并在目标帐户中扮演角色以供个人访问。

仅当我在本地开发时,该应用程序才能处理MFA。我想避免在目标帐户中仅为开发而创建用户,而将本地开发内容包装在--profile之类的功能中。

我的想法是使用aws sts来生成访问密钥和秘密密钥,但是使用与我的凭据文件中相同的设置执行假设角色会给我一个拒绝访问错误。

我的凭据文件遵循以下模式:

[main-profile]
aws_access_key_id={access-key}
aws_secret_access_key={secret-key}

[target-profile]
mfa_serial=arn:blah
role_arn=arn:blah2
source_profile=main-profile

我尝试使用aws sts --role-name arn:blah2 --role-session-name test --profile main-profile。似乎我也需要引用MFA设备,但我不认为这是一个选择。

有什么办法可以做我想做的事吗?


好,所以我能够成功检索和缓存凭据,但是返回的访问密钥对于设置到环境变量中似乎无效。有想法吗?

#!/bin/bash
#set -x

###
# Note: This uses jq (sudo apt-get install jq -y)

targetProfile="target-profile"

sessionFile="/tmp/session-$targetProfile.txt"
sessionFile=$(echo $sessionFile)
echo "Looking for $sessionFile"
if [[ -f "$sessionFile" ]]; then
    echo "Found $sessionFile"
    sessionInfo="$(cat $sessionFile)"    

else
    echo "Building $sessionFile"

    roleArn="$(aws configure get role_arn --profile $targetProfile)"
    mfaArn="$(aws configure get mfa_serial --profile $targetProfile)"
    mainProfile="$(aws configure get source_profile --profile $targetProfile)"

    echo MFA Token:
    read mfaToken

    echo "aws sts get-session-token --serial-number $mfaArn --token-code $mfaToken --profile $mainProfile"
    sessionInfo="$(aws sts get-session-token --serial-number $mfaArn --token-code $mfaToken --profile $mainProfile)"

fi
echo "Current session info: $sessionInfo"

expirationDateValue="$(echo $sessionInfo | jq '.Credentials.Expiration' | tr -d '"')"
echo "Expiration value: $expirationDateValue"
expirationDate=$(date -d $expirationDateValue +%s)
echo "Expiration date: $expirationDate"
currentDate=$(date +%s)
echo "Current date: $currentDate"

if [[ $currentDate -ge $expirationDate ]]; then
    rm $sessionFile
    /bin/bash $0
    exit
fi  

echo "$sessionInfo" > $sessionFile

export AWS_ACCESS_KEY_ID=$(echo $sessionInfo | jq '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $sessionInfo | jq '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $sessionInfo | jq '.Credentials.SessionToken')

#dotnet run
aws s3 ls

运行此命令时,出现以下错误消息:

An error occurred (InvalidAccessKeyId) when calling the ListBuckets operation: The AWS Access Key Id you provided does not exist in our records.

事实证明,我无法重用从会话JSON返回的值中的引号。我必须删除引号并添加新的引号,这实际上是有道理的。有关解决方案,请参见下面的答案。

2 个答案:

答案 0 :(得分:0)

AWS CLI可以使用两个不同的文件来处理configcredentials

  • AWS CLI配置文件(~/.aws/config
  • AWS Shared Credential文件(~/.aws/credentials

关于共享凭据文件,让我引用文档:

对于每个部分,可以指定上面显示的三个配置变量:aws_access_key_idaws_secret_access_keyaws_session_token这些是共享凭据文件中唯一受支持的值。

参考:https://docs.aws.amazon.com/cli/latest/topic/config-vars.html

因此,基本上,您可以将主配置文件放在credentials文件中,但需要将目标配置文件放在config文件中。

请参见以下示例:

# In ~/.aws/credentials:
[development]
aws_access_key_id=foo
aws_secret_access_key=bar

# In ~/.aws/config
[profile crossaccount]
role_arn=arn:aws:iam:...
source_profile=development

还要注意,这些部分的名称与AWS CLI配置文件(~/.aws/config)不同。在AWS CLI配置文件中,您可以通过创建[profile profile-name]部分来创建新的配置文件。在共享凭据文件中,配置文件没有前缀profile

答案 1 :(得分:0)

知道了!我终于找到了正确的Bash拼写:o)

#!/bin/bash
#set -x

###
# Note: This uses jq (sudo apt-get install jq -y)

targetProfile="target-profile"

sessionFile="/tmp/session-$targetProfile.txt"
sessionFile=$(echo $sessionFile)
echo "Looking for $sessionFile"
if [[ -f "$sessionFile" ]]; then
    echo "Found $sessionFile"
    sessionInfo="$(cat $sessionFile)"    

else
    echo "Building $sessionFile"

    roleArn="$(aws configure get role_arn --profile $targetProfile)"
    mfaArn="$(aws configure get mfa_serial --profile $targetProfile)"
    mainProfile="$(aws configure get source_profile --profile $targetProfile)"

    echo MFA Token:
    read mfaToken

    sessionInfo="$(aws sts get-session-token --serial-number $mfaArn --token-code $mfaToken --profile $mainProfile)"

fi

expirationDateValue="$(echo $sessionInfo | jq '.Credentials.Expiration' | tr -d '"')"
expirationDate=$(date -d $expirationDateValue +%s)
currentDate=$(date +%s)

if [[ $currentDate -ge $expirationDate ]]; then
    echo "Session expired"
    rm $sessionFile
    /bin/bash $0
    exit
fi  

echo "$sessionInfo" > $sessionFile

export AWS_ACCESS_KEY_ID="$(echo $sessionInfo | jq '.Credentials.AccessKeyId' | tr -d '"')"
export AWS_SECRET_ACCESS_KEY="$(echo $sessionInfo | jq '.Credentials.SecretAccessKey' | tr -d '"')"
export AWS_SESSION_TOKEN="$(echo $sessionInfo | jq '.Credentials.SessionToken' | tr -d '"')"

#dotnet run
aws s3 ls