EtagをつかってS3にアップロードしたファイルの整合性をたしかめてみる（マルチパートアップロードなし）

※2024年7月追記
S3のEタグ周りについては本記事を含んで下記の記事をシリーズとして投稿しています。

- [EtagをつかってS3にアップロードしたファイルの整合性をたしかめてみる（マルチパートアップロードなし）](https://qiita.com/SAITO_Keita/items/29cf207b969537b2b68b)
- [EtagをつかってS3にアップロードしたファイルの整合性をたしかめてみる（マルチパートアップロードあり）](https://qiita.com/SAITO_Keita/items/21f9b5390c3487ac9957)
- [AWSマネジメントコンソールからS3にマルチパートアップロードした時の分割サイズについて](https://qiita.com/SAITO_Keita/items/99691f77b00b07a193bf)
- [PowerShellでS3のEtagを計算してみる（暗号化なし＆SSE-S3&マルチパートアップロード対応）](https://qiita.com/SAITO_Keita/items/5cf16cc82c4e8fd0ee56)

追記おしまい

ローカルからS3にアップロードしたファイルが正常にアップロードできているか確認したい場合、前提条件はつきますが`エンティティタグ (Etag)`を利用すると確認できるので紹介します。

## エンティティタグ (Etag)について

EtagはS3にアップロードしたファイルのオブジェクト概要にが表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/bfb50783-6175-e429-6539-06f8a52b552a.png)

このEtagについて下記ドキュメントに記載があります。

[Content-MD5 と ETag を使用して、アップロードされたオブジェクトを検証する](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/checking-object-integrity.html#checking-object-integrity-etag-and-md5)

S3ではアップロード時に追加チェックサムを利用してアップロードしたファイルの整合性を確認できますが。

このEtagに表示される値を利用してもアップロードしたファイルの整合性を確認できるとあり、本記事ではこちらを確認していきます。

## Etagの値は暗号化とマルチパートアップロードの有無によってことなる

一覧にまとめると下記になります

|種別|Etagの値|
|---|---|
|オブジェクトがプレーンテキスト|MD5 ダイジェスト|
|オブジェクトがSSE-S3で暗号化|MD5 ダイジェスト|
|オブジェクトがSSE-Cで暗号化|MD5 ダイジェスト ではない|
|オブジェクトがSSE-KMSで暗号化|MD5 ダイジェスト ではない|
|暗号化の有無関係なくマルチパートアップロード|MD5 ダイジェスト ではない|

暗号化なし、もしくは`SSE-S3`暗号のケースではEtagの値はMD5 ダイジェストとなり。

それ以外の暗号化方式（SSE-C,SSE-KMS）の場合はMD5　ダイジェストではない値になるようです。

またそもそもマルチパートアップロードした場合は暗号化方式によらずMD5 ダイジェストではない値になるようです。

このためローカルファイルのMD5を確認し、アップロードしたファイルのMD5が一致する事で整合性が確認できるのは暗号化なし　か　SSE-S3で暗号化したケースのみとなり、SS3-CとSSE-KMSで暗号化された場合はEtagでファイルの整合性を確認する事はできません。

本記事では、マルチパートアップロードをしないケースについて確認してみます。

## ドキュメント

[put-object](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/put-object.html)

[Content-MD5 と ETag を使用して、アップロードされたオブジェクトを検証する](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/checking-object-integrity.html#checking-object-integrity-etag-and-md5)

[Amazon S3 マネージドキーによるサーバー側の暗号化 (SSE-S3) の指定](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/specifying-s3-encryption.html)

[AWS KMS (SSE−KMS) によるサーバー側の暗号化の指定](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/specifying-kms-encryption.html)

[お客様が指定したキーによるサーバー側の暗号化 (SSE−C) の使用](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/ServerSideEncryptionCustomerKeys.html)

## 検証に利用する環境

- Windows 10 21H2
- PowerShell 7.4.0-preview.4
- aws-cli/2.13.3 Python/3.11.4 Windows/10 exe/AMD64 prompt/off

## aws-cliでマルチパートアップロードなしでアップロードして確認してみる

#### 補足事項

`aws-cli`ではマルチパートアップロードする閾値設定`multipart_threshold`のデフォルト設定 8mbとなり、`aws s3 cp`コマンドでは10mbのファイルをアップロードするとマルチパートアップロードされてしまうため、本記事では`aws s3api put-object`をつかってマルチパートアップロードしないようにアップロードしています。

また2023年7月現在ではs3バケットの暗号化設定がデフォルトになっており、暗号化なしは省いています。

```powershell:PowerShellでファイルを作成してアップロード
# fsutilでファイル作成
fsutil file createnew .\testfile $(10mb)

# SSE-S3でキーtestfile-sse-s3としてtestfileをアップロード
aws s3api put-object --bucket <<バケット名>> --key testfile-sse-s3 --body ./testfile --server-side-encryption AES256

# SSE-KMSでキーtestfile-sse-kmdとしてtestfileをアップロード
aws s3api put-object --bucket <<バケット名>> --key testfile-sse-kms --body ./testfile --server-side-encryption aws:kms --ssekms-key-id <<KMSキーID>>

# SSE-Cでキーtestfile-sse-cとしてtestfileをアップロード

# AESで利用する鍵を設定（32バイトの任意の文字列）
$key="7tkJjz;uqVMd@?yIg2<1i9lLsGFc=5AR"
aws s3api put-object --bucket <<バケット名>> --key testfile-sse-c --body ./testfile --sse-customer-algorithm AES256 --sse-customer-key $key
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/83655d22-98de-b955-8a93-63a065789256.png)

アップロード時にそれぞれEtagが出力されるので確認してみます。

|種別|Etagの値|今回アップロードしたファイルの値|
|---|---|---|
|SSE-S3を利用|MD5 ダイジェスト|f1c9645dbc14efddc7d8a322685f26eb|
|SSE-Cを利用|MD5 ダイジェスト ではない|3ea8628f5c993afe736bb2c944d31f06|
|SSE-KMSを利用|MD5 ダイジェスト ではない|90925a8ba3469e15cf0fa18809f11d3c|

## ローカルファイルのMD5を確認してみる

今回アップロードした元ファイル`testfile`のMD5を確認してみます。

`Get-FileHash`コマンドレットから取得できるため、こちらを実行します。

```powershell
Get-FileHash .\testfile -algorithm MD5
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/7367b9a7-9f46-5476-4ad1-f5054abd2e29.png)

`Get-FileHash`コマンドレットで取得できた値は、 `F1C9645DBC14EFDDC7D8A322685F26EB`となりました。

この値を比較してみると`SSE-S3`を利用してアップロードした場合の`ETag`の値と一致しました。

これでローカルファイルとアップロードされたファイルの整合性が確認できました。

他の暗号化方法についてはドキュメントにMD5ではないとだけ記載されており、MD5の値では無いことしかわからず、ETagで整合性を検証する事はできません。

## 総評

`Etag`に入力されている値について、暗号化なし、 SSE-S3ではファイル整合性を確かめるのに利用できます。

ただし他の暗号化やマルチアップロードでS3へ格納されると、MD5以外で計算された値に変わるため、`ETag`を利用して利用ためには前提条件の確認が必要となります。