Azure blob storage bucket origin (private)
Use Microsoft Azure authenticated requests to protect communication between your Fastly service and Azure.
VCL
Use this solution in your VCL service (click RUN below to test this solution or clone it to make changes):
Compute
Use this solution in your Compute service:
- JavaScript
- Rust
package.json
JavaScript
{"dependencies":{"crypto-js":"^4.1.1"}}
index.js
JavaScript
/// <reference types="@fastly/js-compute" />import * as crypto from "crypto-js";
// The name of your Azure Storage Accountconst ACCOUNT_NAME = "computeatedgedemo";// The Azure Storage Account shared key from your Azure Storage developer's account. It must be Base64 decoded.const ACCOUNT_KEY = "XXXXXXXX";// The backend domain name needs to be set as STORAGE_ACCOUNT_NAME.blob.core.windows.netconst HOST = "computeatedgedemo.blob.core.windows.net";const BLOB_CONTAINER_NAME = "compute-at-edge-demo";const MS_API_VERSION = "2017-11-09";
addEventListener("fetch", (event) => event.respondWith(handleRequest(event)));
async function handleRequest(event) { let req = fixupURL(event.request);
// Only generate authorize header for GET and HEAD request // Pass PURGE to backend as it is // Block other kinds of method if (req.method === "GET" || req.method === "HEAD") { authorizeRequest(req);
let res = await fetch(req, { backend: "azure_backend", });
// Remove MS headers returned from Azure Blob res.headers.delete("x-ms-request-id"); res.headers.delete("x-ms-blob-type"); res.headers.delete("x-ms-server-encrypted"); res.headers.delete("x-ms-version"); res.headers.delete("x-ms-creation-time"); res.headers.delete("x-ms-lease-status"); res.headers.delete("x-ms-lease-state"); res.headers.delete("content-md5"); res.headers.delete("server");
return res; } else if (req.method === "PURGE") { // When doing the purge, we need to make sure the cache key matches // Cache key is cacualted from URL and HOST header of request sent to backend // URL of backend request has no query string req.headers.set("host", HOST);
return await fetch(req, { backend: "azure_backend", }); } else { return new Response("This method is not allowed", { status: 405 }); }}
function authorizeRequest(req) { // The timestamp format should be something like // Fri, 01 Jan 2021 00:14:22 GMT const timestamp = new Date().toUTCString();
// Decode base64 format access key to binary key const decodedKey = crypto.enc.Base64.parse(ACCOUNT_KEY);
// Canonical headers must be sorted and concatenated with newlines. // If there are query params there is a separate spec for that, not supported here yet const canonicalizedHeaders = `x-ms-date:${timestamp}\nx-ms-version:${MS_API_VERSION}\n`;
// Canonical Resource is /account/cotainer/object const url = new URL(req.url); const canonicalizedResource = `/${ACCOUNT_NAME}${url.pathname}`; console.log(`canonicalizedResource = ${canonicalizedResource}`);
// Construct everything properly before signing // We are adding 4 newlines here, however the spec says we // can override any of these 4 headers with values if we want. // For now we are just blanking them out const stringToSign = `GET\n\n\n\n${canonicalizedHeaders}${canonicalizedResource}`; // HMAC-sign with SHA256 and Base64-encode the result const signature_binary = hmacSha256(decodedKey, stringToSign); const signature = crypto.enc.Base64.stringify(signature_binary);
const authorization = `SharedKeyLite ${ACCOUNT_NAME}:${signature}`;
req.headers.set("host", HOST); req.headers.set("authorization", authorization); req.headers.set("x-ms-date", timestamp); req.headers.set("x-ms-version", MS_API_VERSION);
console.log(`Path: ${url.pathname}, Authorization: ${authorization}`);}
function fixupURL(req) { let url = new URL(req.url); // Ignore the query string from client url.search = ""; // Request path for azure storage is /container/object url.pathname = `/${BLOB_CONTAINER_NAME}${url.pathname}`;
return new Request(url, req);}
function hmacSha256(signingKey, stringToSign) { return crypto.HmacSHA256(stringToSign, signingKey, { asBytes: true });}
This page is part of a series in the Static content topic.
User contributed notes
BETADo you see an error in this page? Do have an interesting use case, example or edge case people should know about? Share your knowledge and help people who are reading this page! (Comments are moderated; for support, please contact support@fastly.com)