Search code examples
node.jsgoogle-cloud-platformgoogle-cloud-storagepre-signed-urlgoogle-cloud-cdn

Google Cloud Storage get signedUrl from CDN npm


I am using a code as the following to create a signed Url for my content:

var storage = require('@google-cloud/storage')();
var myBucket = storage.bucket('my-bucket');
var file = myBucket.file('my-file');

//-
// Generate a URL that allows temporary access to download your file.
//-
var request = require('request');

var config = {
  action: 'read',
  expires: '03-17-2025'
};

file.getSignedUrl(config, function(err, url) {
  if (err) {
    console.error(err);
    return;
  }

  // The file is now available to read from the URL.

});

This creates an Url that starts with https://storage.googleapis.com/my-bucket/

If I place that URL in the browser, it is readable.

However, i guess that URL is a direct access to the bucket file and is not passing through my configured CDN.

I see that in the docs (https://cloud.google.com/nodejs/docs/reference/storage/1.6.x/File#getSignedUrl) you can pass a cname option, which transforms the url to replace https://storage.googleapis.com/my-bucket/ to my bucket CDN.

HOWEVER when I copy the resulting URL, the sevice account or resulting url doesn't seem to have access to the resource.

I have added the firebase admin service account to the bucket but still I get no access.

Also, from the docs, the CDN signed url seems a lot different from the one signed through that API. Is it possible to create from the api a CDN signed url, or should i manually create it as explained in: https://cloud.google.com/cdn/docs/using-signed-urls?hl=en_US&_ga=2.131493069.-352689337.1519430995#configuring_google_cloud_storage_permissions?


Solution

  • For anyone interested in the node code for that signing:

        var url = 'URL of the endpoint served by Cloud CDN';
        var key_name = 'Name of the signing key added to the Google Cloud Storage bucket or service';
        var key = 'Signing key as urlsafe base64 encoded string';
        var expiration = Math.round(new Date().getTime()/1000) + 600; //ten minutes after, in seconds
    
        var crypto = require("crypto");
        var URLSafeBase64 = require('urlsafe-base64');
    
        // Decode the URL safe base64 encode key
        var decoded_key = URLSafeBase64.decode(key);
    
        // buILD URL
        var urlToSign = url 
                + (url.indexOf('?') > -1 ? "&" : "?")
                + "Expires=" + expiration
                + "&KeyName=" + key_name;
    
        //Sign the url using the key and url safe base64 encode the signature
        var hmac = crypto.createHmac('sha1', decoded_key); 
        var signature = hmac.update(urlToSign).digest();
        var encoded_signature = URLSafeBase64.encode(signature);
    
        //Concatenate the URL and encoded signature
        urlToSign += "&Signature=" + encoded_signature;