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"
ここまでの処理が正しく行われていれば、オブジェクトのコピーを行うことができるはずです。