このライブラリを作成するというアイデアは、無料の Oracle Cloud Infrastructure製品、つまり1か月あたり10GBのオブジェクトストレージと10TBの送信トラフィックを最大限に活用したいと思ったときに生まれました 。 AWSS3との違いは 非常に大きいです。残念ながら、Oracle Cloudに は 、Webサイト開発で最も人気のあるプログラミング言語に使用できるSDKがありません。 幸いなことに、このサービスはAmazon S3と 部分的に互換性があります。つまり、PHPを含め、既存の十分に文書化された開発者ツールを使用できます 。
コードを見たいと思っている人は、https://github.com/hitrov/oci-api-php-request-signにようこそ 。
実際、利用可能なツールを使用すると、バケットやオブジェクト(ファイル)の作成、読み取り、削除など、考えられるほぼすべての操作を実行できます。ごみ箱は、パブリック(リストファイルの有無にかかわらず)とプライベートの両方にすることができます。「シークレット」URL(CLI またはWebインターフェース(Oracle Cloudコンソール)を使用して手動で生成)のみを持つプライベートバスケットにファイルをアップロードすることができます 。実際、これは多くのシナリオですでに十分である可能性があります。特に、一般に公開したくない場合にブルートフォースファイル名を生成する場合はなおさらです。
ファイルを「共有」する機能、つまりファイルへのパブリックリンクを共有する機能、そしてもちろん、必要に応じてアクセスを制限する機能に興味がありました。ファイルの数が少ない場合は手動で行うことができますが、プログラムでアクセスできるようにここに集められています。AWS S3はこれを事前署名済みURLと呼び、Oracleはこれを事前認証済みリクエストと呼び ます 。
AWS PHPSDKのインストール
composer require aws/aws-sdk-php
その下に、アクセスを取得する場所(AWS_ACCESS_KEY_ID
およびAWS_SECRET_ACCESS_KEY
。
名前空間が表示されます
require('vendor/autoload.php');
$namespaceName = 'frpegp***';
$bucketName = 'test******05';
$region = 'eu-frankfurt-1';
$endpoint = "https://$namespaceName.compat.objectstorage.$region.oraclecloud.com";
$s3 = new Aws\S3\S3Client([
'version' => 'latest',
'region' => $region,
'endpoint' => $endpoint,
'signature_version' => 'v4',
'use_path_style_endpoint' => true,
'credentials' => [
'key' => 'AKI***YYJ', // remove if you have env var AWS_ACCESS_KEY_ID
'secret' => 'ndK***cIf', // remove if you have env var AWS_SECRET_ACCESS_KEY
],
]);
$cmd = $s3->getCommand('GetObject', [
'Bucket' => $bucketName,
'Key' => 'fff.txt'
]);
$request = $s3->createPresignedRequest($cmd, '+20 minutes');
var_dump($request);
object(GuzzleHttp\Psr7\Request)#146 (7) {
["method":"GuzzleHttp\Psr7\Request":private]=>
string(3) "GET"
["uri":"GuzzleHttp\Psr7\Request":private]=>
object(GuzzleHttp\Psr7\Uri)#148 (7) {
["scheme":"GuzzleHttp\Psr7\Uri":private]=>
string(5) "https"
...
["host":"GuzzleHttp\Psr7\Uri":private]=>
string(64) "{namespace}.compat.objectstorage.eu-frankfurt-1.oraclecloud.com"
...
["path":"GuzzleHttp\Psr7\Uri":private]=>
string(21) "/{bucket}/fff.txt"
["query":"GuzzleHttp\Psr7\Uri":private]=>
string(329) "X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=&&&%2F20210211%2Feu-frankfurt-1%2Fs3%2Faws4_request&X-Amz-Date=20210211T093350Z&X-Amz-SignedHeaders=host&X-Amz-Expires=1200&X-Amz-Signature=1e1b1***6ac992"
...
}
}
この操作は、応答としてPSR-7要求を返し 、そこからフォームのURLを生成できます。
https://{namespace}.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/{bucket}/fff.txt?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=***%2F20210210%2Feu-frankfurt-1%2Fs3%2Faws4_request&X-Amz-Date=20210210T185244Z&X-Amz-SignedHeaders=host&X-Amz-Expires=1200&X-Amz-Signature=a167a***9a857
ただし、残念ながら、これでは、たとえばリンクが「長時間再生」されている場合など、アクセスを取り消すことはできません。
, \\ , DNS Email. API Reference and Endpoints.
, , , , - () Oracle Cloud User Settings
API Keys — Add API Key
Download private key ( ), Add
,
, AWS PHP SDK, Customer Secret Keys ( AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
Amazon.
Oracle Cloud Infrastructure mini PHP SDK ( !)
composer require hitrov/oci-api-php-request-sign
PSR-4 .
require 'vendor/autoload.php';
use Hitrov\OCI\Signer;
( , , ).
OCI_TENANCY_ID=ocid1.tenancy.oc1..aaaaaaaaba3pv6wkcr4jqae5f15p2b2m2yt2j6rx32uzr4h25vqstifsfdsq OCI_USER_ID=ocid1.user.oc1..aaaaaaaat5nvwcna5j6aqzjcaty5eqbb6qt2jvpkanghtgdaqedqw3rynjq OCI_KEY_FINGERPRINT=20:3b:97:13:55:1c:5b:0d:d3:37:d8:50:4e:c5:3a:34 OCI_PRIVATE_KEY_FILENAME=/path/to/privatekey.pem
.
$signer = new Signer;
https://github.com/hitrov/oci-api-php-request-sign#alternatives-for-providing-credentials , .
CreatePreauthenticatedRequest.
( )
public function getHeaders(
string $url, string $method = 'GET', ?string $body = null, ?string $contentType = 'application/json', string $dateString = null
): array
$curl = curl_init();
$url = 'https://objectstorage.eu-frankfurt-1.oraclecloud.com/n/{namespaceName}/b/{bucketName}/p/';
$method = 'POST';
$body = '{"accessType": "ObjectRead", "name": "read-access-to-image.png", "objectName": "path/to/image.png", "timeExpires": "2021-03-01T00:00:00-00:00"}';
$headers = $signer->getHeaders($url, $method, $body, 'application/json');
var_dump($headers);
$curlOptions = [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 5,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $headers,
];
if ($body) {
// not needed for GET or HEAD requests
$curlOptions[CURLOPT_POSTFIELDS] = $body;
}
curl_setopt_array($curl, $curlOptions);
$response = curl_exec($curl);
echo $response;
curl_close($curl);
array(6) {
[0]=>
string(35) "date: Mon, 08 Feb 2021 20:49:22 GMT"
[1]=>
string(50) "host: objectstorage.eu-frankfurt-1.oraclecloud.com"
[2]=>
string(18) "content-length: 76"
[3]=>
string(30) "content-type: application/json"
[4]=>
string(62) "x-content-sha256: X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE="
[5]=>
string(538) "Authorization: Signature version=\"1\",keyId=\"ocid1.tenancy.oc1..aaaaaaaaba3pv6wkcr4jqae5f15p2b2m2yt2j6rx32uzr4h25vqstifsfdsq/ocid1.user.oc1..aaaaaaaat5nvwcna5j6aqzjcaty5eqbb6qt2jvpkanghtgdaqedqw3rynjq/20:3b:97:13:55:1c:5b:0d:d3:37:d8:50:4e:c5:3a:34\",algorithm=\"rsa-sha256\",headers=\"date (request-target) host content-length content-type x-content-sha256\",signature=\"LXWXDA8VmXXc1NRbMmXtW61IS97DfIOMAnlj+Gm+oBPNc2svXYdhcXNJ+oFPoi9qJHLnoUiHqotTzuVPXSG5iyXzFntvkAn3lFIAja52iwwwcJflEIXj/b39eG2dCsOTmmUJguut0FsLhCRSX0eylTSLgxTFGoQi7K/m18nafso=\""
}
{
"accessUri": "/p/AlIlOEsMok7oE7YkN30KJUDjDKQjk493BKbuM-ANUNGdBBAHzHT_5lFlzYC9CQiA/n/{namespaceName}/b/{bucketName}/o/path/to/image.png",
"id": "oHJQWGxpD+2PhDqtoewvLCf8/lYNlaIpbZHYx+mBryAad/q0LnFy37Me/quKhxEi:path/to/image.png",
"name": "read-access-to-image.png",
"accessType": "ObjectRead",
"objectName": "path/to/image.png",
"timeCreated": "2021-02-09T11:52:45.053Z",
"timeExpires": "2021-03-01T00:00:00Z"
}
!
, . , – .
1) , « » (SIGNING_HEADERS_NAMES).
date
· (request-target)
· host
POST|PUT|PATCH
· content-length
· content-type
· x-content-sha256
$signingHeadersNames = $signer->getSigningHeadersNames('POST');
2) SHA256 «» – base64
$bodyHashBase64 = $signer->getBodyHashBase64($body);
3) ,
date: Mon, 08 Feb 2021 20:51:33 GMT (request-target): post /n/{namespaceName}/b/{bucketName}/p/ host: objectstorage.eu-frankfurt-1.oraclecloud.com content-length: 76 content-type: application/json x-content-sha256: X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=
$signingString = $signer->getSigningString($url, $method, $body, 'application/json');
(2). , , 5 .
4) (3) RSA-SHA256
$signature = $signer->calculateSignature($signingString, $privateKeyString);
5) KEY_ID , API Key, ,
"{OCITENANCYID}/{OCIUSERID}/{OCIKEY_FINGERPRINT}"
$keyId = $signer->getKeyId();
6) ( 1
Oracle)
Authorization: Signature version=\"1\",keyId=\"{KEY_ID}\",algorithm=\"rsa-sha256\",headers=\"{SIGNING_HEADERS_NAMES_STRING}\",signature=\"{SIGNATURE}\"
SIGNING_HEADERS_NAMES_STRING – (1), .
date (request-target) host content-length content-type x-content-sha256
$signingHeadersNamesString = implode(' ', $signingHeadersNames);
$authorizationHeader = $signer->getAuthorizationHeader($keyId, $signingHeadersNamesString, $signature);
Authorization: Signature version=\"1\",keyId=\"ocid1.tenancy.oc1..aaaaaaaaba3pv6wkcr4jqae5f15p2b2m2yt2j6rx32uzr4h25vqstifsfdsq/ocid1.user.oc1..aaaaaaaat5nvwcna5j6aqzjcaty5eqbb6qt2jvpkanghtgdaqedqw3rynjq/20:3b:97:13:55:1c:5b:0d:d3:37:d8:50:4e:c5:3a:34\",algorithm=\"rsa-sha256\",headers=\"date (request-target) host content-length content-type x-content-sha256\",signature=\"LXWXDA8VmXXc1NRbMmXtW61IS97DfIOMAnlj+Gm+oBPNc2svXYdhcXNJ+oFPoi9qJHLnoUiHqotTzuVPXSG5iyXzFntvkAn3lFIAja52iwwwcJflEIXj/b39eG2dCsOTmmUJguut0FsLhCRSX0eylTSLgxTFGoQi7K/m18nafso=\"
- . var_dump()
- (3), (request-target) . , , (6).
Oracle Cloud Infrastructure(OCI)のREST呼び出しのウォークスルーとcurlの記事に助けられました 。一部のメソッド名は、公式のGoLangSDKから借用してい ます。テストケース- 同じ場所から。