将文件上传到S3时,aws-cli是否确认校验和,或者我是否需要自行管理?

时间:2014-10-02 19:48:16

标签: amazon-web-services amazon-s3

如果我使用aws-cli将数据上传到S3(即使用aws s3 cp),aws-cli是否做任何工作来确认S3中的结果文件是否与原始文件匹配,或者我是以某种方式需要自己管理吗?

基于this answerputObject()的Java API文档,看起来可以在上传后验证MD5校验和。但是,我无法找到关于aws-cli是否真的这样做的明确答案。

这对我来说很重要,因为我打算从备份过程中上传GPG加密的文件,我想要确信存储在S3中的内容实际上与原始文件匹配。

2 个答案:

答案 0 :(得分:6)

根据aws-cli github的the faq,在大多数情况下,在上传和下载过程中会检查校验和。

上传要点:

  • AWS CLI计算标准和标准的Content-MD5标头 分段上传。
  • 如果S3计算的校验和不匹配 提供的Content-MD5,S3不会存储对象而是存储 将返回AWS CLI的错误消息。
  • AWS CLI将在放弃和退出非零退出代码之前最多重试此错误5次。

答案 1 :(得分:1)

AWS支持页面How do I ensure data integrity of objects uploaded to or downloaded from Amazon S3?介绍了如何实现此目标。

首先确定您要上传的文件的base64编码的md5sum:

$ md5_sum_base64="$( openssl md5 -binary my-file | base64 )"

然后使用s3api上传文件:

$ aws s3api put-object --bucket my-bucket --key my-file --body my-file --content-md5 "$md5_sum_base64"

请注意使用--content-md5标志,此标志的帮助声明:

--content-md5  (string)  The  base64-encoded  128-bit MD5 digest of the part data.

这并没有多说为什么来使用此标记,但我们可以在API documentation for put object中找到此信息:

  

要确保数据没有损坏遍历网络,请使用Content-MD5标头。当您使用此标头时,Amazon S3会根据提供的MD5值检查对象,如果它们不匹配,则会返回错误。此外,您可以在将对象放入Amazon S3时计算MD5,并将返回的ETag与计算的MD5值进行比较。

使用此标志会导致S3验证文件哈希服务器端是否与指定值匹配。如果哈希匹配s3将返回ETag:

{
    "ETag": "\"599393a2c526c680119d84155d90f1e5\""
}

ETag值通常是十六进制md5sum(对于某些可能不是这种情况的情况,请参阅this question。)

如果哈希值与您指定的哈希值不匹配,则会收到错误。

A client error (InvalidDigest) occurred when calling the PutObject operation: The Content-MD5 you specified was invalid.

除此之外,您还可以将文件md5sum添加到文件元数据中作为附加检查:

$ aws s3api put-object --bucket my-bucket --key my-file --body my-file --content-md5 "$md5_sum_base64" --metadata md5chksum="$md5_sum_base64"

上传后,您可以发出head-object命令来检查值。

$ aws s3api head-object --bucket my-bucket --key my-file
{
    "AcceptRanges": "bytes",
    "ContentType": "binary/octet-stream",
    "LastModified": "Thu, 31 Mar 2016 16:37:18 GMT",
    "ContentLength": 605,
    "ETag": "\"599393a2c526c680119d84155d90f1e5\"",
    "Metadata": {    
        "md5chksum": "WZOTosUmxoARnYQVXZDx5Q=="    
    }    
}

这是一个bash脚本,它使用内容md5并添加元数据,然后验证S3返回的值是否与本地哈希匹配:

#!/bin/bash

set -euf -o pipefail

# assumes you have aws cli, jq installed

# change these if required
tmp_dir="$HOME/tmp"
s3_dir="foo"
s3_bucket="stack-overflow-example"
aws_region="ap-southeast-2"
aws_profile="my-profile"

test_dir="$tmp_dir/s3-md5sum-test"
file_name="MailHog_linux_amd64"
test_file_url="https://github.com/mailhog/MailHog/releases/download/v1.0.0/MailHog_linux_amd64"
s3_key="$s3_dir/$file_name"
return_dir="$( pwd )"

cd "$tmp_dir" || exit
mkdir "$test_dir"
cd "$test_dir" || exit

wget "$test_file_url"

md5_sum_hex="$( md5sum $file_name | awk '{ print $1 }' )"
md5_sum_base64="$( openssl md5 -binary $file_name | base64 )"

echo "$file_name hex    = $md5_sum_hex"
echo "$file_name base64 = $md5_sum_base64"

echo "Uploading $file_name to s3://$s3_bucket/$s3_dir/$file_name"
aws \
--profile "$aws_profile" \
--region "$aws_region" \
s3api put-object \
--bucket "$s3_bucket" \
--key "$s3_key" \
--body "$file_name" \
--metadata md5chksum="$md5_sum_base64" \
--content-md5 "$md5_sum_base64"

echo "Verifying sums match"

s3_md5_sum_hex=$( aws --profile "$aws_profile"  --region "$aws_region" s3api head-object --bucket "$s3_bucket" --key "$s3_key" | jq -r '.ETag' | sed 's/"//'g )
s3_md5_sum_base64=$( aws --profile "$aws_profile"  --region "$aws_region" s3api head-object --bucket "$s3_bucket" --key "$s3_key" | jq -r '.Metadata.md5chksum' )

if [ "$md5_sum_hex" == "$s3_md5_sum_hex" ] && [ "$md5_sum_base64" == "$s3_md5_sum_base64" ]; then
    echo "checksums match"
else
    echo "something is wrong checksums do not match:"

    cat <<EOM | column -t -s ' '
$file_name file hex:    $md5_sum_hex    s3 hex:    $s3_md5_sum_hex
$file_name file base64: $md5_sum_base64 s3 base64: $s3_md5_sum_base64
EOM

fi

echo "Cleaning up"
cd "$return_dir"
rm -rf "$test_dir"
aws \
--profile "$aws_profile" \
--region "$aws_region" \
s3api delete-object \
--bucket "$s3_bucket" \
--key "$s3_key"