Get Azure File from snapshot with php - php

Is there any documentation to get a SAS URL to download a file from a Snapshot of a Azure Share File?
Using this is easy to download a direct Azure File with SAS, but not any snapshot:
GenerateFileDownloadLinkWithSAS (https://github.com/Azure/azure-storage-php/blob/master/samples/FileSamples.php)
Here my code:
use MicrosoftAzure\Storage\Common\Exceptions\ServiceException;
use MicrosoftAzure\Storage\Common\Internal\Resources;
use MicrosoftAzure\Storage\Common\Internal\StorageServiceSettings;
use MicrosoftAzure\Storage\Common\Models\Range;
use MicrosoftAzure\Storage\Common\Models\Metrics;
use MicrosoftAzure\Storage\Common\Models\RetentionPolicy;
use MicrosoftAzure\Storage\Common\Models\ServiceProperties;
use MicrosoftAzure\Storage\File\FileRestProxy;
use MicrosoftAzure\Storage\File\FileSharedAccessSignatureHelper;
use MicrosoftAzure\Storage\File\Models\CreateShareOptions;
use MicrosoftAzure\Storage\File\Models\ListSharesOptions;
use MicrosoftAzure\Storage\File\Models\ListDirectoriesAndFilesOptions;
function MapFileURL($shareName,$filePath)
{
global $fileRestProxy;
global $mapConString;
$prepareFilePath = implode('/', array_map(function ($v)
{
return rawurlencode($v);
}, explode('/', $filePath))
);
// Create a SharedAccessSignatureHelper
$settings = StorageServiceSettings::createFromConnectionString($mapConString);
$accountName = $settings->getName();
$accountKey = $settings->getKey();
$helper = new FileSharedAccessSignatureHelper(
$accountName,
$accountKey
);
$endDate=MapIsoDate(time() + 13300);
// Generate a file readonly SAS token
// Refer to following link for full candidate values to construct a service level SAS
// https://learn.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas
$sas = $helper->generateFileServiceSharedAccessSignatureToken(
Resources::RESOURCE_TYPE_FILE,
$shareName . "/" . $prepareFilePath,
'r', // Read
$endDate
);
$connectionStringWithSAS = Resources::FILE_ENDPOINT_NAME.'='.'https://'.$accountName.'.'.Resources::FILE_BASE_DNS_NAME.';'.Resources::SAS_TOKEN_NAME.'='.$sas;
$fileClientWithSAS = FileRestProxy::createFileService($connectionStringWithSAS);
// Get a downloadable file URL
$fileUrlWithSAS = sprintf(
'%s%s?%s',
(string)$fileClientWithSAS->getPsrPrimaryUri(),
$shareName . "/" . $prepareFilePath,
$sas
);
return $fileUrlWithSAS;
}
What would be missing to be able to download the file from a Azure File snapshot?

What would be missing to be able to download the file from a Azure
File snapshot?
What you need to do is append the share's snapshot date/time to your SAS URL. Something like:
https://account.file.core.windows.net/share/file.png?sastoken&snapshot=2021-05-01T13:49:56.0000000Z

Here is the code that works:
function MapSnapshotFileURL($shareName, $filePath, $snapshotTime)
{
global $fileRestProxy;
global $mapConString;
// Preparar path para enviar a la funciĆ³n azure.
$prepareFilePath = implode('/', array_map(function ($v)
{
return rawurlencode($v);
}, explode('/', $filePath))
);
// Create a SharedAccessSignatureHelper
$settings = StorageServiceSettings::createFromConnectionString($mapConString);
$accountName = $settings->getName();
$accountKey = $settings->getKey();
$helper = new FileSharedAccessSignatureHelper(
$accountName,
$accountKey
);
$endDate=MapIsoDate(time() + 13300);
//$endDate='2019-07-16T08:30:00Z';
// Generate a file readonly SAS token
// Refer to following link for full candidate values to construct a service level SAS
// https://learn.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas
$sas = $helper->generateFileServiceSharedAccessSignatureToken(
Resources::RESOURCE_TYPE_FILE,
$shareName . "/" . $prepareFilePath,
'r', // Read
$endDate // '2020-01-01T08:30:00Z' // A valid ISO 8601 format expiry time
);
$connectionStringWithSAS = Resources::FILE_ENDPOINT_NAME.'='.'https://'.$accountName.'.'.Resources::FILE_BASE_DNS_NAME.';'.Resources::SAS_TOKEN_NAME.'='.$sas;
$fileClientWithSAS = FileRestProxy::createFileService($connectionStringWithSAS);
// Get a downloadable file URL
$fileUrlWithSAS = sprintf(
'%s%s?%s&%s',
(string)$fileClientWithSAS->getPsrPrimaryUri(),
$shareName . "/" . $prepareFilePath,
$sas,
"snapshot=".$snapshotTime
);
return $fileUrlWithSAS;
}

Related

Google Cloud signed URL with PHP

My needs are simple... One would think. I'm just trying to create a signed URL with a PHP script to prevent download abuse of a file hosted on Google Cloud Storage. I've found several examples, none that worked. This one came the closest:
<?php
$filepath = 'my file.zip'; // do not include the bucket name, no slash in the beginning
$bucket = 'mybucket';
$key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; // key
$secret = 'xxxxxxxxxxxxxxxxxxxxxxx'; // secret
function getSignedGoogleCloudStorageUrl($filepath, $bucket, $secret, $key, $duration = 300)
{
$expires = new \DateTime('+ ' . $duration . ' seconds');
$seconds = $expires->format('U');
$objectPieces = explode('/', $filepath);
array_walk($objectPieces, function (&$piece) {
$piece = rawurlencode($piece);
});
$objectName = implode('/', $objectPieces);
$resource = sprintf(
'/%s/%s',
$bucket,
$objectName
);
$headers = []; // you may add any headers needed here
$toBeSignedArray = [
'GET',
'', // contentMd5, can be left blank
'', // contentType, can be left blank
$seconds,
implode("\n", $headers) . $resource,
];
$toBeSignedString = implode("\n", $toBeSignedArray);
$encodedSignature = urlencode(base64_encode(hash_hmac('sha1', $toBeSignedString, $secret, true)));
$query = [];
$query[] = 'GoogleAccessId=' . $key;
$query[] = 'Expires=' . $seconds;
$query[] = 'Signature=' . $encodedSignature;
return "https://storage.googleapis.com/{$bucket}/{$filepath}?" . implode('&', $query);
}
echo getSignedGoogleCloudStorageUrl($filepath, $bucket, $secret, $key);
?>
However, it always produces the same result after the 1st use until I clear the cache on the web server.
Any help or other working examples would be great. Thanks.

Get URL from Firebase Storage (PHP)

I have URL gs://bucket-name.appspot.com/photos/1F0CB8D1-511E-47F2-AA31-8EC131E38672.jpg,
but I need URL http://.... for show photo on site.
How I can get it? Please, explain in PHP.
What you're looking for is called a signed URL in Google Cloud Storage, and you can generate a signed URL in PHP with:
$storage = new StorageClient();
$bucket = $storage->bucket($bucketName);
$object = $bucket->object($objectName);
$url = $object->signedUrl(
# This URL is valid for 15 minutes
new \DateTime('15 min'),
[
'version' => 'v4',
]
);
print('Generated GET signed URL:' . PHP_EOL);
print($url . PHP_EOL);
print('You can use this URL with any user agent, for example:' . PHP_EOL);
print('curl ' . $url . PHP_EOL);

How to generate Signed URL for google cloud storage objects using PHP

The method i tried using was with openssl
$fp = fopen($key, 'r'); //open the PEM file
$priv_key = fread($fp,8192);
fclose($fp);
$pkeyid = openssl_get_privatekey($priv_key,"password");
openssl_sign($response["data_to_sign"], $signature, $pkeyid,'sha256');
$sign = base64_encode($signature)
Is this the correct Method to generate signature for signed urls in google?
You can try Google Cloud Storage PHP SDK, it's a good choice for keeping your codes clean.
cloud-storage PHP SDK
Install package to your project by following this page
on Packagist,
then
function getSignedGcsUrl($objPath/* which is your target object path */, $duration = 50)
{
$storageClient = new StorageClient([
'projectId' => /* your gcp projectId here */,
'keyFilePath' => /* your gcp keyFilePath here */,
]);
$bucket = $storageClient->bucket($objPath);
$object = $bucket->object();
$url = $object->signedUrl(new \DateTime('+ ' . $duration . ' seconds'));
return $url;
}
laravel-google-cloud-storage (for Laravel)
Install and configurate superbalist/laravel-google-cloud-storage by following this page:
on Github,
then
public static function getSignedGcsUrl($objPath, $duration = 50)
{
return Storage::disk('gcs'/* following your filesystem configuration */)
->getAdapter()
->getBucket()
->object($objPath)
->signedUrl(new \DateTime('+ ' . $duration . ' seconds'));
}
I put all the answers together. This should work in out of the box project. If you have space in the paths, you will need to rawurlencode the individual components, not urlencode.
function signedGoogleStorageURL($bucketName, $resourcePath, $duration = 10, $method = 'GET')
{
$expires = time() + $duration;
$content_type = ($method == 'PUT') ? 'application/x-www-form-
urlencoded' : '';
$to_sign = ($method . "\n" .
/* Content-MD5 */ "\n" .
$content_type . "\n" .
$expires . "\n" .
"/" . $bucketName . $resourcePath);
$sign_result = AppIdentityService::signForApp($to_sign);
$signature = urlencode(base64_encode($sign_result['signature']));
$email = AppIdentityService::getServiceAccountName();
return ('https://storage.googleapis.com/' . $bucketName .
$resourcePath .
'?GoogleAccessId=' . $email .
'&Expires=' . $expires .
'&Signature=' . $signature);
}
$signedPath = signedGoogleStorageURL(AppIdentityService::getDefaultVersionHostname(), "/my_folder/my_file", 60);
One thing to note that I spent about two hours on:
The GoogleAccessId you pass into the URL is the Email Address in the "Certificate" section of the Google Cloud Console. It's not the OAuth Client ID with a string replacement as Google suggests in their documentation.
There's an example here that signs a URL for Google Cloud Storage using PHP:
https://groups.google.com/forum/#!msg/google-api-php-client/jaRYDWdpteQ/xbNTLfDhUggJ
However - I note this is tagged with Google App Engine... If your code is running inside of Google App Engine, you should use the built-in App Identity service - (note this will only work once your application is deployed in production, not while running locally) - this means you will not need to download or handle any private keys:
require_once 'google/appengine/api/app_identity/AppIdentityService.php';
$sign_result = AppIdentityService::signForApp( $message );
You will need to make sure that the service account associated with the App Engine application is added to the team for the project that owns the Cloud Storage bucket.

AWS Multipart upload SDK not working

I need Help on AWS multi-part Upload using PHP 5.3
I am using
1. WAMP Server.
2. PHP 5.3
3. OS: Windows 8
I am trying to upload a Big file to My Amazon S3 bucket.
And tried in many ways. I followed the code procedure from
http://docs.aws.amazon.com/AmazonS3/latest/dev/LLuploadFilePHP.html
I wrote PHP code but I don't know what mistake I did.
My Code:
<?php
require_once './sdk/sdk.class.php';
use \AmazonS3;
$ufile = $_FILES['ufile'];
$filepath = $ufile['tmp_name'];
$bucket = '**My_bkt**';
var_dump($ufile);
print $keyname = \date("Y") . "/" . \date("F") . "/" . \date("d") . "/" . $ufile['name'] . "<BR />";
$api_key = "***my_api_key***";
$secret_key = "***my_secret_key***";
// Define a megabyte.
define('MB', 1048576);
// Instantiate the class
//$s3 = new AmazonS3();
$s3 = new AmazonS3(array(
'key' => $api_key,
'secret' => $secret_key,
));
// 1. Initiate a new multipart upload.
/* #var $response type */
$response = $s3->initiate_multipart_upload($bucket, $keyname);
// Get the Upload ID.
$upload_id = (string) $response->body->UploadId;
// 2. Upload parts.
// Get part list for a given input file and given part size.
// Returns an associative array.
$parts = $s3->get_multipart_counts(filesize($filepath), 3 * MB);
foreach ($parts as $i => $part) {
// Upload part and save response in an array.
$responses[] = $s3->upload_part($bucket, $keyname, $upload_id, array(
'fileUpload' => $filepath,
'partNumber' => ($i + 1),
'seekTo' => (integer) $part['seekTo'],
'length' => (integer) $part['length'],
)
);
}
// 3. Complete multipart upload. We need all part numbers and ETag values.
$parts = $s3->list_parts($bucket, $keyname, $upload_id);
$response = $s3->complete_multipart_upload($bucket, $keyname, $upload_id, $parts);
var_dump($response);
Please help me.
I know you're using the older SDK 1 here, so my answer doesn't apply directly to what you've posted. That said, SDK 1.x is no longer being updated and SDK 2.x is what all new work should be using (as per the AWS SDK for PHP team).
If you do update your project to use SDK 2, then take a look at S3Client::upload(). It should greatly simplify what you're trying to do here.
I have Updated My SDK and Changed My Code like bellow,
////////////////// AWS Code Begin ////////////////////
/////////////////////////// Step 1 /////////////////////////////
$ufile = $_FILES['Filedata'];
$filename = $ufile['tmp_name'];
$filesize = $ufile['size'];
/* * ************ Calculating Number of Parts ******************* */
$number_of_parts = 0;
$r = $filesize % PART; // Remainder
$q = floor($filesize / PART); // Quotient
if ($r != 0) {
$number_of_parts = $q + 1;
} else {
$number_of_parts = $q;
}
$bucket = 'isource123';
$keyname = date("Y") . "/" . date("F") . "/" . date("d") . "/" . $ufile['name'];
///////////////////////////// Step 2 /////////////////////////////
// Create a service builder using a configuration file
$aws = Aws::factory('./aws/Aws/Common/Resources/aws-config.php');
// Get the client from the builder by namespace
$client = $aws->get('S3');
$uploader = \Aws\S3\Model\MultipartUpload\UploadBuilder::newInstance()
->setClient($client)
->setSource($filename)
->setBucket($bucket)
->setKey($keyname)
->setOption('Metadata', array('Foo' => 'Bar'))
->setOption('CacheControl', 'max-age=3600')
->setConcurrency($number_of_parts)
->build();
try {
$uploader->upload();
echo "Upload complete.\n";
} catch (MultipartUploadException $e) {
$uploader->abort();
echo "Upload failed.\n";
}
I updated My SDK to version 2 and it's working fine.

How set Meta data key in php for Rackspace Cloud API

I am using Cloud File API of Rackspace Cloud server in PHP, I want to generate a temp url to download files for direct to my server for this i am using get_temp() method of this api but before use to this method i have to set Meta Data key for my container. How would i do this.
public function get_temp_url($key, $expires, $method)
{
$expires += time();
$url = $this->container->cfs_http->getStorageUrl() . '/' . $this->container->name . '/' . $this->name;
return $url . '?temp_url_sig=' . hash_hmac('sha1', strtoupper($method) .
"\n" . $expires . "\n" . parse_url($url, PHP_URL_PATH), $key) .
'&temp_url_expires=' . $expires;
}
The comments on this page include an example of how to set this:
http://docs.rackspace.com/files/api/v1/cf-devguide/content/Set_Account_Metadata-d1a4460.html
Also, if you use the new Cloud Files API...
https://github.com/rackspace/php-opencloud
...it includes a SetTempUrlSecret method in the ObjectStore class that will do this for you.

Categories