【问题标题】:Download AWS S3 file from EC2 instance从 EC2 实例下载 AWS S3 文件
【发布时间】:2016-11-10 21:01:41
【问题描述】:

我有一个从 AWS S3 下载文件的脚本,它可以在 AWS 之外的单独服务器上运行。但是,当我将此脚本放在 EC2 实例上并尝试时,它会返回错误“SignatureDoesNotMatch - 我们计算的请求签名与您提供的签名不匹配。请检查您的密钥和签名方法。”

但它可以在其他服务器上运行。 ec2 与 s3 主机位于同一区域。估计跟楼主有关系。我尝试了这些主机/网址,但它返回相同的错误。

谁能用 curl 从 ec2 下载 s3 文件?我只需要使用 curl。如果您知道如何通过 curl 进行操作,请回答。谢谢。

https://s3-ap-southeast-1.amazonaws.com/$bucket/$file

https://s3.amazonaws.com/$bucket/$file

https://$bucket.s3-ap-southeast-1.amazonaws.com/$file

https://$bucket.s3.amazonaws.com/$file

#!/bin/sh
file="file-name"
bucket="bucket-name"
resource="/${bucket}/${file}"
contentType="application/x-compressed-tar"
dateValue="`date +'%a, %d %b %Y %H:%M:%S %z'`"
stringToSign="GET\n\n${contentType}\n${dateValue}\n${resource}"
s3Key="xxxxxxxxxxxxxxxxxx"
s3Secret="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
signature=$(echo -en "${stringToSign}" | openssl sha1 -hmac "${s3Secret}" -binary | base64)
curl -H "Host: s3-ap-southeast-1.amazonaws.com" \
 -H "Date: $dateValue" \
 -H "Content-Type: $contentType" \
 -H "Authorization: AWS ${s3Key}:${signature}" \
 https://s3-ap-southeast-1.amazonaws.com/$bucket/$file -o $file

【问题讨论】:

  • We've seen a question here like this before,可能与 OpenSSL 中的一个错误有关,因为它已通过 OpenSSL 的升级解决。不幸的是,旧版本无法识别,因此从未确定根本原因。也许比较两台机器上的 OpenSSL 版本对您来说是一个起点。
  • 嗨迈克尔,我刚刚尝试了更高版本的 openssl 版本。在 aws 之外工作的服务器中有 OpenSSL 1.0.1e-fips 2013 年 2 月 11 日,然后现在 aws 服务器有 OpenSSL 1.0.2j 2016 年 9 月 26 日,但它仍然返回 SignatureDoesNotMatch。我想知道是否可能是我没有使用正确的主机或网址?
  • 看来我上面的代码可能适用于centos。我尝试了另一个 ubuntu 服务器,但它不起作用。也许不知何故,生成签名的行没有为 ubuntu 正确处理。我尝试了最新的 openssl 版本,但似乎仍然无法正常工作。
  • 好奇心:把#!/bin/sh改成#!/bin/bash
  • ubuntu 使用与 centos 不同的回显 echo -en ${stringToSign } 从字面上打印出 dash space en space G E T slash n ...

标签: curl amazon-s3 amazon-ec2


【解决方案1】:

与其编写 CURL 命令,不如考虑使用AWS Command-Line Interface (CLI)

它有一个aws s3 cp 命令,可以将内容复制到/从 Amazon S3 存储桶(甚至在存储桶之间)。

【讨论】:

  • 嗨。我知道还有其他选择,但正如我提到的,我需要使用 curl,所以我希望能回答我的问题。我正在使用自动缩放,所以我已经创建了图像,并且所有区域都需要做很多事情来设置 CLI。我已经运行了厨师,因此通过说明书加载一些 bash 代码来运行下载而不更新图像会更容易。
  • 如果您知道如何通过 curl 进行操作,请回答,而不是建议其他选项。谢谢。
【解决方案2】:

试试这个...

#!/bin/sh
S3_KEY='/file.txt'
S3_SECRET_KEY='xxx'
S3_ACCESS_KEY='AKIAxxx'
S3_HOST=yourbucket.s3.amazonaws.com

AMZ_DATE=$(date -u "+%Y%m%dT%H%M%SZ")
DATE=$(/bin/echo ${AMZ_DATE} | cut -b 1-8)
REGION=ap-southeast-1
CANONICAL_REQUEST="GET\n${S3_KEY}\n\nhost:${S3_HOST}\nx-amz-content-sha256:UNSIGNED-PAYLOAD\nx-amz-date:${AMZ_DATE}\n\nhost;x-amz-content-sha256;x-amz-date\nUNSIGNED-PAYLOAD"
STRING_TO_SIGN="AWS4-HMAC-SHA256\n${AMZ_DATE}\n${DATE}/${REGION}/s3/aws4_request\n$(/bin/echo -en ${CANONICAL_REQUEST} | sha256sum | cut -f 1 -d' ')"

AWS_SIG_V4_AND_S3_SECRET_KEY=AWS4${S3_SECRET_KEY}

DATE_HMAC_HEX=$(/bin/echo -n "${DATE}" | openssl sha256 -hmac "${AWS_SIG_V4_AND_S3_SECRET_KEY}" | cut -f 2 -d' ')
DATE_HMAC_BIN=$(/bin/echo -n "${DATE_HMAC_HEX}" | xxd -r -p)

REGION_HMAC_HEX=$(/bin/echo -n "${REGION}"  | openssl sha256 -hmac "${DATE_HMAC_BIN}" | cut -f 2 -d' ')
REGION_HMAC_BIN=$(/bin/echo -n "${REGION_HMAC_HEX}" | xxd -r -p)

SERVICE_HMAC_HEX=$(/bin/echo -n "s3"  | openssl sha256 -hmac "${REGION_HMAC_BIN}" | cut -f 2 -d' ')
SERVICE_HMAC_BIN=$(/bin/echo -n "${SERVICE_HMAC_HEX}" | xxd -r -p)

SIGNING_KEY_HEX=$(/bin/echo -n "aws4_request"  | openssl sha256 -hmac "${SERVICE_HMAC_BIN}" | cut -f 2 -d' ')
SIGNING_KEY_BIN=$(/bin/echo -n "${SIGNING_KEY_HEX}" | xxd -r -p)


SIGNATURE_HEX=$(/bin/echo -ne "${STRING_TO_SIGN}" | openssl sha256 -hmac "${SIGNING_KEY_BIN}" | cut -f 2 -d' ')

curl -vv https://${S3_HOST}/file.txt \
    -H "Host: ${S3_HOST}" \
    -H "x-amz-content-sha256: UNSIGNED-PAYLOAD" \
    -H "x-amz-date: ${AMZ_DATE}" \
    -H "Authorization: AWS4-HMAC-SHA256 Credential=${S3_ACCESS_KEY}/${DATE}/${REGION}/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=${SIGNATURE_HEX}"

这是使用 AWS Signature V4。 我已经对此进行了测试,它适用于我在 ap-southeast-1 区域的存储桶的 CentOS 7.3 和 Ubuntu LTS 16.04。 我强烈建议使用 John Rotenstein 的建议。

【讨论】:

  • 我已经尝试了好几个小时来完成这项工作。这次真是万分感谢。我关注了 aws 文档,但不知道什么不起作用。显然我错过了两件事:我使用空字符串的哈希而不是UNSIGNED-PAYLOAD,并且在生成签名密钥时 - 我没有转换为二进制。这些步骤显然是必要的,文档中没有提到
  • 知道为什么有时它会返回 403 和 The request signature we calculated does not match the signature you provided. Check your key and signing method 吗?
【解决方案3】:

Titi Wangsa bin Damhore 的回答非常有帮助。这是一个稍作修改的版本,以使用分配给 EC2 实例的 IAM 配置文件中的凭证。我的机器上也没有可用的 xxd,因此对其进行了调整以使用 sed。

#!/bin/bash

#### Variables

REGION=eu-west-2
S3_KEY='/some/file.txt'   # The file you want to download
FILENAME=$(basename $S3_KEY)
S3_HOST=yourbucket.s3.amazonaws.com # Endpoint for the S3 bucket


#### Get Temporary AWS Credentials from instance metadata ###### 

ROLE_NAME=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/)
CREDENTIALS_TEXT=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE_NAME)

S3_SECRET_KEY=$(echo $CREDENTIALS_TEXT | sed -e 's/.*SecretAccessKey" : "\(.*\)", "Token.*/\1/')
S3_ACCESS_KEY=$(echo $CREDENTIALS_TEXT | sed -e 's/.*AccessKeyId" : "\(.*\)", "SecretAccessKey.*/\1/')
TOKEN=$(echo $CREDENTIALS_TEXT | sed -e 's/.*Token" : "\(.*\)", "Expiration.*/\1/')

####################################

##### Create the string that needs signing ########

AMZ_DATE=$(date -u "+%Y%m%dT%H%M%SZ")
DATE=$(/bin/echo ${AMZ_DATE} | cut -b 1-8)

CANONICAL_REQUEST="GET\n${S3_KEY}\n\nhost:${S3_HOST}\nx-amz-content-sha256:UNSIGNED-PAYLOAD\nx-amz-date:${AMZ_DATE}\nx-amz-security-token:${TOKEN}\n\nhost;x-amz-content-sha256;x-amz-date;x-amz-security-token\nUNSIGNED-PAYLOAD"
STRING_TO_SIGN="AWS4-HMAC-SHA256\n${AMZ_DATE}\n${DATE}/${REGION}/s3/aws4_request\n$(/bin/echo -en ${CANONICAL_REQUEST} | sha256sum | cut -f 1 -d' ')"

####################################

#### Use Temporary AWS Credentials to create signing key ###### 

AWS_SIG_V4_AND_S3_SECRET_KEY=AWS4${S3_SECRET_KEY}

DATE_HMAC_HEX=$(/bin/echo -n "${DATE}" | openssl sha256 -hmac "${AWS_SIG_V4_AND_S3_SECRET_KEY}" | cut -f 2 -d' ')
DATE_HMAC_BIN=$(/bin/echo -n "${DATE_HMAC_HEX}" | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf)

REGION_HMAC_HEX=$(/bin/echo -n "${REGION}"  | openssl sha256 -hmac "${DATE_HMAC_BIN}" | cut -f 2 -d' ')
REGION_HMAC_BIN=$(/bin/echo -n "${REGION_HMAC_HEX}" | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf)

SERVICE_HMAC_HEX=$(/bin/echo -n "s3"  | openssl sha256 -hmac "${REGION_HMAC_BIN}" | cut -f 2 -d' ')
SERVICE_HMAC_BIN=$(/bin/echo -n "${SERVICE_HMAC_HEX}" | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf)

SIGNING_KEY_HEX=$(/bin/echo -n "aws4_request"  | openssl sha256 -hmac "${SERVICE_HMAC_BIN}" | cut -f 2 -d' ')
SIGNING_KEY_BIN=$(/bin/echo -n "${SIGNING_KEY_HEX}" | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf)

####################################

#### Sign string with signing key ## 

SIGNATURE_HEX=$(/bin/echo -ne "${STRING_TO_SIGN}" | openssl sha256 -hmac "${SIGNING_KEY_BIN}" | cut -f 2 -d' ')

####################################

#### Put it all together into a curl request ## 

curl https://${S3_HOST}${S3_KEY} \
    -H "Host: ${S3_HOST}" \
    -H "x-amz-content-sha256: UNSIGNED-PAYLOAD" \
    -H "x-amz-date: ${AMZ_DATE}" \
    -H "X-Amz-Security-Token: ${TOKEN}" \
    -H "Authorization: AWS4-HMAC-SHA256 Credential=${S3_ACCESS_KEY}/${DATE}/${REGION}/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date;X-Amz-Security-Token,Signature=${SIGNATURE_HEX}" -o $FILENAME

####################################

【讨论】:

  • 有趣。我用这个脚本做了一些测试,它有一段时间停止工作(返回 403 - 禁止)。然后你必须等待一段时间再试一次。
猜你喜欢
  • 2017-04-27
  • 2021-02-05
  • 1970-01-01
  • 2014-05-20
  • 1970-01-01
  • 1970-01-01
  • 2022-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多