Keeping Your Secrets Between Cloud Object Storage and Your Browser (Part 2)
Cloud Object Storage provides a limitless, super reliable repository of your unstructured data. Images, documents, whatever. Once the data is safely uploaded to Object Storage, you may wish to serve out selected content to your web users. How could you achieve this without exposing your secret keys to a client-side app?
The answer is pre-signed URLs, as demonstrated in this article on uploading content to Object Storage. This time we’ll be looking a deploying a serverless function that calculates the pre-signed URL. Here’s how it works:
- The web app makes an HTTP GET call to an IBM Cloud Functions action to indicate that it wishes to download a file
- The serverless action calculates a time-limited, pre-signed URL that allows the download of the specified object. The URL is sent out as an HTTP 302 Redirect response.
- The browser’s request is redirected to the pre-signed URL, and the browser fetches the file directly from Object Storage.
Our serverless function is there to keep your Object Storage credentials safe. By using an HTTP 302 response, the browser is automatically redirected to the calculated URL — it doesn’t have any work to do.
Install the serverless action
Assuming you already have
- Signed up for an IBM Cloud account.
- Signed up for an IBM Cloud Object Storage service and created a new bucket.
- Enabled CORS on your object storage bucket so that browsers can access your files directly.
- Installed the bx wsk tool so that you can deploy IBM Cloud Functions code from your command line.
Then you are ready to clone the code:
Set some environment variables with your object storage credentials:
And run the deployment script:
The deployment script will output the URL of your new action, for example:
You can use this URL in a web page to render an image from your object storage bucket:
How does this work?
The serverless action knows your object storage credentials. It is configured with them at deployment time. The only extra piece of information it needs is the ID of the object you need access to (i.e., the file name of the file).
When you call:
And pass in
landscape.png as a run-time parameter, the serverless action calculates a URL which is digitally signed with your object storage's private key. This is good enough to let the IBM Object Storage serve out data on the following conditions:
- The HTTP method is correct (e.g. GET).
- The object ID (filename) is correct (e.g., landscape.png).
- The HTTP call is made before the link expires. I’ve set the expiry time to 60 seconds. After this time the link is useless.
If you needed to, you could add extra security in the serverless action. For example, you could only supply URLs to logged-in users.
What about uploading data to object storage from a browser?
We’ve got you covered there too. See part one of this two-part series, where I cover uploading content to object storage from a browser using a similar technique.
If you’re on a credentials best-practices kick like I’ve been, I humbly suggest you read my article on protecting environment variables in Node.js applications too:
Environment Variables, or Keeping Your Secrets Secret in a Node.js App
Imagine you have some Node.js code that uses an external API which needs an API key: