Oracle Cloud InfrastructureAPIへのリクエストに署名するためのミニPHPSDKの作成

このライブラリを作成するというアイデアは、無料の 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







ただし、残念ながら、これでは、たとえばリンクが「長時間再生」されている場合など、アクセスを取り消すことはできません。





,  API,  , .





, \\  ,  DNS   Email. API Reference and Endpoints.





, , , , - () Oracle Cloud  User Settings





OracleCloudプロファイルのアクション
Oracle Cloud

API Keys — Add API Key





APIキー-APIキーを追加します
API Keys - Add API Key

Download private key ( ),  Add





秘密鍵をダウンロードして追加
Download Private Key and Add

,





構成ファイルの例
Configuration File example

, 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から借用してい ますテストケース- 同じ場所から








All Articles