L'idée d'écrire cette bibliothÚque est née lorsque j'ai voulu profiter pleinement de l' offre gratuite Oracle Cloud Infrastructure, à savoir 10 Go de stockage d'objets et 10 To de trafic sortant par mois. La différence avec AWS S3 est énorme . Malheureusement, Oracle Cloud n'a pas de SDK disponible pour le langage de programmation toujours le plus populaire pour le développement de sites Web. La bonne nouvelle est que le service est partiellement compatible avec Amazon S3, ce qui signifie que vous pouvez utiliser des outils de développement existants et bien documentés , y compris pour PHP.
Pour ceux qui ont hĂąte de voir le code, bienvenue sur https://github.com/hitrov/oci-api-php-request-sign .
En effet, avec les outils disponibles, vous pouvez effectuer presque toutes les opĂ©rations imaginables - pour crĂ©er, lire et supprimer des buckets et des objets (fichiers). Les corbeilles peuvent ĂȘtre Ă la fois publiques (avec ou sans liste de fichiers) et privĂ©es. Il est possible de tĂ©lĂ©charger des fichiers dans un panier privĂ©, n'ayant qu'une URL «secrĂšte» (gĂ©nĂ©rĂ©e manuellement Ă l'aide de la CLI ou de l'interface Web - console Oracle Cloud). En fait, cela peut dĂ©jĂ ĂȘtre suffisant pour de nombreux scĂ©narios, en particulier si vous gĂ©nĂ©rez des noms de fichiers par force brute au cas oĂč vous ne voudriez pas les exposer au public.
J'étais intéressé par la possibilité de "partager" des fichiers, c'est-à -dire de partager des liens publics vers des fichiers et, bien sûr, de restreindre l'accÚs si nécessaire. Avec un petit nombre de fichiers, vous pouvez le faire manuellement, mais nous sommes réunis ici pour avoir un accÚs par programme. AWS S3 appelle cela une URL pré-signée , tandis qu'Oracle l' appelle une demande pré-authentifiée .
Installation du kit AWS PHP SDK
composer require aws/aws-sdk-php
Ci-dessous, il sera montrĂ© oĂč accĂ©der ( AWS_ACCESS_KEY_ID
et AWS_SECRET_ACCESS_KEY
.
L'espace de noms peut ĂȘtre vu
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"
...
}
}
Cette opĂ©ration renvoie une requĂȘte PSR-7 en rĂ©ponse , Ă partir de laquelle vous pouvez gĂ©nĂ©rer une URL du formulaire
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
Mais, malheureusement, cela ne permet pas de révoquer l'accÚs, par exemple, si le lien est "longue durée".
, \\ , 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).
J'ai Ă©tĂ© aidĂ© par la procĂ©dure pas Ă pas de l'appel REST d'Oracle Cloud Infrastructure (OCI) avec l'article curl . Certains des noms de mĂ©thodes sont empruntĂ©s au SDK officiel de GoLang . Cas de test - du mĂȘme endroit .