piresashwin
piresashwin

Reputation: 165

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?

Upvotes: 4

Views: 9763

Answers (4)

Mou Hsiao
Mou Hsiao

Reputation: 366

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'));
}

Upvotes: 12

keithyip
keithyip

Reputation: 1035

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);

Upvotes: 4

Tim B
Tim B

Reputation: 1877

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.

Upvotes: 3

aeijdenberg
aeijdenberg

Reputation: 2457

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.

Upvotes: 1

Related Questions