OCIのREST APIをCurlで使ってみる:バケット間でのオブジェクトのコピー

バケット内のオブジェクト一覧の取得、バケットへのファイルのアップロードについて書いてきましたが、ひとまず最後の今回は、バケット間でのオブジェクトのコピーについて、手順を整理しました。

ところどころ、前回・前々回と同じことを説明していますが、この記事単体でも分かるようにするためなので、ご了承ください。

以下のコマンドを順番に実行していくことで、REST APIによってバケット間でオブジェクトをコピーすることができます。
※Linuxのbashを環境を想定しています。また、IAMポリシーなどの設定は完了していることが前提となります。

テナンシのOCIDの設定

tenancy_ocid="<テナンシのOCID>"

ユーザのOCIDの設定

user_ocid="<ユーザのOCID>"

APIキー(公開鍵)のフィンガープリントの設定

key_fingerprint="<公開鍵のフィンガープリント(OCI画面上で確認可能)>"

APIキー(秘密鍵)のパス/ファイル名の設定

private_key_path="<秘密鍵のパス/ファイル名>"

秘密鍵・公開鍵はユーザ画面の「APIキー」の項目に登録されている必要があります。

リクエスト先ホストの設定

host="objectstorage.ap-tokyo-1.oraclecloud.com"

ホスト及びエンドポイントはリージョンによって異なり、上記のホストは東京リージョンの場合です。

Curlのメソッド及びリクエスト・ターゲットの設定

request_target="(request-target): post /n/<ネームスペース>/b/<バケット>/actions/copyObject"

オブジェクトのコピーは POST で行います。

APIのエンドポイントURLの設定

endpoint="https://objectstorage.ap-tokyo-1.oraclecloud.com/n/<ネームスペース>/b/<バケット>/actions/copyObject"

コピーするオブジェクトを指定するのではなく、コピー操作の指示を出すためのエンドポイントを叩きます。
コピー対象やコピー先の情報は、別途、リクエストボディとして用意しておき、POSTで送信します。

これまで同様、endpoint, host について、プライベートエンドポイントを用いてプライベート環境でREST APIを利用することも可能ですが、オブジェクトのコピーの場合、プライベートエンドポイントのアクセス・ターゲットとして、コピー元だけでなく、コピー先のバケットも設定されている必要があります。

現在時刻(UTC)の取得

date_value=$(date -u "+%a, %d %b %Y %H:%M:%S GMT")

ここで取得した時刻は認証情報の一部となり、リクエスト実行時、OCI側の時刻との差が5分以内でなければなりません。
5分を超えていると、その旨のメッセージが表示されて、APIの実行はエラーとなります。

リクエストのボディ(送信するデータ)の設定

body_data='{
  "sourceObjectName": "<コピー元オブジェクト>",
  "sourceObjectIfMatchETag": "*",
  "destinationRegion": "ap-tokyo-1",
  "destinationNamespace": "<コピー先ネームスペース>",
  "destinationBucket": "<コピー先バケット>",
  "destinationObjectName": "<コピー先オブジェクト>",
  "destinationObjectIfNoneMatchETag": "*",
  "destinationObjectMetadata": {}
}'

コピー元・コピー先のオブジェクトについて、<フォルダ名>/<ファイル名> の形で記載することで、バケット上でのフォルダ分けにも対応可能です。

送信するデータのタイプの設定

content_type="application/json"

リクエストのボディはjson形式です。

送信するデータのサイズを取得

content_length=$(echo -n "$body_data" | wc -c)

json形式の文字列を送信するため、送信するデータのサイズ=文字数となり、wcコマンドで取得することができます。

リクエストボディのSHA-256ハッシュを計算

x_content_sha256=$(echo -n "$body_data" | openssl dgst -binary -sha256 | openssl enc -e -base64)

署名対象の文字列の設定

signing_string="date: $date_value\nhost: $host\ncontent-length: $content_length\ncontent-type: $content_type\nx-content-sha256: $x_content_sha256\n$request_target"

\n を入れているのは、次の署名生成の際に改行コードを読み込ませて、上記の文字列をjsonの形式にするためです。

署名の生成

signed_string=$(echo -en "$signing_string" | openssl dgst -sha256 -sign "$private_key_path" | openssl enc -e -base64 | tr -d '\n')

署名対象の文字列に秘密鍵で署名して、base64で暗号化しています。
base64暗号化後に改行が含まれていると署名として機能しないため、最後に改行の削除を行っています。

認証ヘッダの作成

authorization_header="Signature version=\"1\",keyId=\"$tenancy_ocid/$user_ocid/$key_fingerprint\",algorithm=\"rsa-sha256\",headers=\"date host content-length content-type x-content-sha256 (request-target)\",signature=\"$signed_string\""

認証ヘッダの headers= には、署名対象の文字列を設定したときと同じ項目が、同じ順序で記載されている必要があります。

APIリクエストの実行

curl -X POST -H "Date: $date_value" -H "Host: $host" -H "Content-Length: $content_length" -H "Content-Type: $content_type" -H "x-content-sha256: $x_content_sha256" -H "Authorization: $authorization_header" -d "$body_data" "$endpoint"

ここまでの処理が正しく行われていれば、オブジェクトのコピーを行うことができるはずです。


いいなと思ったら応援しよう!