2
0

More than 3 years have passed since last update.

pythonで Azure Blob、AWS S3からMD5ハッシュ値を取得する

Posted at

はじめに

本年度から業務内容がWindowsアプリ開発からAWS関連の業務に代わり、
最初のタスクが「Azure Blob Storageから AWS S3に移行されたデータが正しく移行されているかの検証」でした。

aws s3にはアップロード時に、アップロード前と後のオブジェクトの整合性を検証する手段があるのですが、今回は既に全データ移行済みだったため、BlobとS3のメタデータを取得して格納されているMD5ハッシュ値で検証を実施しました。

ちなみに言語はpythonを使っています。

結論

  • オブジェクトのメタデータ取得(S3編)
  • オブジェクトのメタデータ取得(Blob編)
  • 終わり

オブジェクトのメタデータ取得(S3編)

pythonかつaws s3のメタデータを取得する方法は探せば多くの情報が見つかると思います。
下記のコードもその一例になります。

    from azure.storage.blob import BlobServiceClient

    # AWS CLIの aws configure コマンドで .aws/credentialsファイルに書き込むこと
    aws_access_key_id = ''
    aws_secret_access_key = ''

    bucket_name = ''
    key_name = ''

    s3_cli = boto3.client('s3',aws_access_key_id, aws_secret_access_key)
    # オブジェクトのメタデータを取得
    s3_resp = s3_cli.head_object(bucket_name, key_name)
    # レスポンスからMD5ハッシュが格納されているEtagを取得
    s3obj_etag = s3_resp['ETag'].strip('"')
    return s3obj_etag

key_idbucket_nameは自分の環境にあわせて値を代入してください。
boto3.client()でs3へアクセスするオブジェクトをまず取得します。
その後、head_object()でオブジェクトのメタデータを取得します。

    # オブジェクトのメタデータを取得
    s3_resp = s3_cli.head_object(bucket_name, key_name)

s3_respはjsonが返ってきます。返り値の中身は下記のようなデータが入っています。

"s_respの中身の例"
{'ResponseMetadata': {'RequestId': '9dad3fc3-0e30-1dbc-a754-06bdfcde1d5e',
  'HostId': '',
  'HTTPStatusCode': 200,
  'HTTPHeaders': {'date': 'Sun, 13 Dec 2020 22:43:10 GMT',
   'x-amz-request-id': '9dad3fc3-0e30-1dbc-a754-06bdfcde1d5e',
   'last-modified': 'Sun, 13 Dec 2020 22:40:57 GMT',
   'etag': '"669fdad9e309b552f1e9cf7b489c1f73-2"',
   'content-type': 'binary/octet-stream',
   'x-amz-server-side-encryption': 'AES256',
   'x-amz-version-id': 'fe14c26b-bba0-6edf-a754-06bdfcde1d5e',
   'accept-ranges': 'bytes',
   'content-length': '10485760',
   'server': 'CloudianS3'},
  'RetryAttempts': 0},
 'AcceptRanges': 'bytes',
 'LastModified': datetime.datetime(2020, 12, 13, 22, 40, 57, tzinfo=tzutc()),
 'ContentLength': 10485760,
 'ETag': '"669fdad9e309b552f1e9cf7b489c1f73-2"',
 'VersionId': 'fe14c26b-bba0-6edf-a754-06bdfcde1d5e',
 'ContentType': 'binary/octet-stream',
 'ServerSideEncryption': 'AES256',
 'Metadata': {}}

head_objectの返り値にETagというキーがあります。この値がMD5ハッシュ値になります。

'ETag': '"669fdad9e309b552f1e9cf7b489c1f73-2"'

数字型として使う場合は、下記のようにstrip()で "" を削除して使いましょう。

# レスポンスからMD5ハッシュが格納されているEtagを取得
# ""を除去
s3obj_etag = s3_resp['ETag'].strip('"')

以上でaws s3のMD5ハッシュ取得については終了です。

オブジェクトのメタデータ取得(Blob編)

s3と違ってazure blobのメタデータ取得については、探すのに時間がかかりました。
なので、ここからは皆さんのお役になる情報だと思います。

    from azure.storage.blob import BlobServiceClient

    # BLOB接続文字列
    connectionString = ''
    container_name = ''
    blob_name = ''

    blob_service_client = BlobServiceClient.from_connection_string(connectionString)
    blob_client = blob_service_client.get_blob_client(container_name, blob_name)

    # BLOBのすべてのユーザー定義メタデータ、標準HTTPプロパティ、およびシステムプロパティを受け取る
    prop = blob_client.get_blob_properties()
    bytearray = prop['content_settings']['content_md5']
    return bytearray.hex()

以下、解説になります。
from_connection_string()get_blob_client()を使ってBlobClientを取得します。

blob_service_client = BlobServiceClient.from_connection_string(connectionString)
blob_client = blob_service_client.get_blob_client(container_name, blob_name)

BlobClientクラスにはget_blob_properties()というAPIがあり、このAPIがBLOBのメタデータ(BlobProperties)を返してくれます。
ここで注意点なのですが、BlobPropertiesにはetagというキーがありますが、今回欲しいハッシュ値は、content_settingsキーの値ContentSettingscontent_md5というキーがありこちらになります。

    prop = blob_client.get_blob_properties()
    bytearray = prop['content_settings']['content_md5']
    return bytearray.hex()

content_md5はbytearray型なので、hex()で変換することでs3で取得した値と同じものになるかと思います。

終わり

以上になります。
先にs3のハッシュを取得できていたため、BlobPropertiesにはetagを見つけて返り値を確認した時は、なぜs3の返り値と値が異なるのかと頭を抱えていました。
Microsoftのドキュメントをきちんと確認することはやはり大事ですね。

皆さんはデータ移行時は必ずアップロード時に整合性を確認して、失敗した場合はリトライなどの処理をしましょう。データ数が多いので、移行後の整合性確認はお金の無駄でしかありません。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0