Erstellen eines Mini-PHP-SDK zum Signieren von Anforderungen an die Oracle Cloud Infrastructure API

Die Idee, diese Bibliothek zu schreiben, entstand, als ich das kostenlose  Oracle Cloud Infrastructure- Angebot voll ausnutzen wollte  , nämlich 10 GB Objektspeicher und 10 TB ausgehenden Datenverkehr pro Monat. Der Unterschied zu AWS S3 ist  enorm . Leider verfügt Oracle Cloud  nicht über  ein SDK für die immer noch beliebteste Programmiersprache für die Website-Entwicklung. Die gute Nachricht ist, dass der Dienst  teilweise  mit Amazon S3 kompatibel ist. Dies bedeutet, dass Sie vorhandene und gut dokumentierte  Entwicklertools verwenden können , auch für PHP.





Für diejenigen, die den Code sehen möchten, willkommen unter  https://github.com/hitrov/oci-api-php-request-sign .





Mit den verfügbaren Tools können Sie nahezu alle erdenklichen Vorgänge ausführen - zum Erstellen, Lesen und Löschen von Buckets und Objekten (Dateien). Papierkörbe können sowohl öffentlich (mit oder ohne Auflistung von Dateien) als auch privat sein. Es ist möglich, Dateien in einen privaten Warenkorb hochzuladen, der nur eine "geheime" URL enthält (manuell über die CLI  oder die Weboberfläche - Oracle Cloud-Konsole generiert  ). Tatsächlich reicht dies möglicherweise bereits für viele Szenarien aus, insbesondere wenn Sie Brute-Force-Dateinamen generieren, falls Sie diese nicht der Öffentlichkeit zugänglich machen möchten.





Ich war an der Möglichkeit interessiert, Dateien zu "teilen", dh öffentliche Links zu Dateien zu teilen und natürlich den Zugriff bei Bedarf einzuschränken. Mit einer kleinen Anzahl von Dateien können Sie dies manuell tun, aber wir sind hier versammelt, um programmgesteuerten Zugriff zu haben. AWS S3 nennt dies eine vorsignierte URL , während Oracle  sie als  vorauthentifizierte Anforderung bezeichnet .





Installieren des AWS PHP SDK





composer require aws/aws-sdk-php
      
      



Unten wird angezeigt, wo Sie Zugriff erhalten ( AWS_ACCESS_KEY_ID



und AWS_SECRET_ACCESS_KEY



.





Namespace kann gesehen werden





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"
    ...
  }
}
      
      



Diese Operation gibt als Antwort eine PSR-7-Anforderung zurück  , aus der Sie eine URL des Formulars generieren können





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







Leider erlaubt dies jedoch keinen Widerruf des Zugriffs, beispielsweise wenn der Link "langwierig" ist.





,  API,  , .





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





, , , , - () Oracle Cloud  User Settings





Oracle Cloud-Profilaktionen
Oracle Cloud

API Keys — Add API Key





API-Schlüssel - API-Schlüssel hinzufügen
API Keys - Add API Key

Download private key ( ),  Add





Private Key herunterladen und hinzufügen
Download Private Key and Add

,





Beispiel für eine Konfigurationsdatei
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).





Der REST-Aufruf für Oracle Cloud Infrastructure (OCI) mit Curl-Artikel hat mir geholfen  . Einige der Methodennamen stammen aus dem offiziellen  GoLang SDK . Testfälle -  vom selben Ort .








All Articles