Skip to content

Instantly share code, notes, and snippets.

@vvuksan
Last active January 27, 2017 16:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vvuksan/99bacbf1fd2140cea2f85ea70d30ab04 to your computer and use it in GitHub Desktop.
Save vvuksan/99bacbf1fd2140cea2f85ea70d30ab04 to your computer and use it in GitHub Desktop.
AWSv4 VCL signing
sub aws4_lambda_sign_request {
# Declare local variables we'll need
declare local var.date_stamp STRING;
declare local var.string_to_sign STRING;
declare local var.canonical_request STRING;
declare local var.credential_scope STRING;
declare local var.request_parameters STRING;
declare local var.canonical_querystring STRING;
declare local var.canonical_headers STRING;
declare local var.signed_headers STRING;
declare local var.signature STRING;
# JSON encoded request parameters
if ( req.postbody ) {
set var.request_parameters = req.postbody;
} else {
set var.request_parameters = "";
}
set req.http.Content-Type = "application/x-amz-json-1.0";
set req.http.x-amz-date = strftime({"%Y%m%dT%H%M%SZ"}, now);
set var.date_stamp = strftime({"%Y%m%d"}, now);
set var.canonical_querystring = "";
set var.canonical_headers = "content-type:" + req.http.Content-Type + LF + "host:" + req.http.host + LF + "x-amz-date:" + req.http.x-amz-date + LF;
set var.signed_headers = "content-type;host;x-amz-date";
set var.canonical_request = req.http.method + LF + req.url + LF + var.canonical_querystring + LF + var.canonical_headers + LF + var.signed_headers + LF + regsub(digest.hash_sha256(var.request_parameters),"^0x", "");
set var.credential_scope = var.date_stamp + "/" + req.http.region + "/" + req.http.service + "/aws4_request";
set var.string_to_sign = "AWS4-HMAC-SHA256" + LF + req.http.x-amz-date + LF + var.credential_scope + LF + regsub(digest.hash_sha256(var.canonical_request),"^0x", "");
set var.signature = digest.awsv4_hmac( req.http.secret_key, var.date_stamp, req.http.region, req.http.service, var.string_to_sign);
set req.http.Authorization = "AWS4-HMAC-SHA256" + " Credential=" + req.http.access_key + "/" + var.credential_scope + ", SignedHeaders=" + var.signed_headers + ", Signature=" + regsub(var.signature,"^0x", "");
# Unset request headers not needed for the response
unset req.http.Accept;
unset req.http.Accept-Language;
unset req.http.User-Agent;
# Remove
unset req.http.method;
unset req.http.secret_key;
unset req.http.access_key;
unset req.http.service;
unset req.http.region;
}
sub vcl_recv {
#FASTLY recv
# Must set these
set req.http.access_key = "XXXXXXXXXXXXXXX";
set req.http.secret_key = "XXXXXXXXXXXXX/XXXXXXX";
# Set region
set req.http.region = "ap-northeast-2";
# We need to reset the requested host to proper S3 end point
set req.http.Host = "XXXXXX.s3.amazonaws.com";
set req.http.method = "GET";
# Let's get
call aws4_sign_request;
if (req.request != "HEAD" && req.request != "GET" && req.request != "FASTLYPURGE") {
return(pass);
}
return(lookup);
}
sub vcl_fetch {
/* handle 5XX (or any other unwanted status code) */
if (beresp.status >= 500 && beresp.status < 600) {
/* deliver stale if the object is available */
if (stale.exists) {
return(deliver_stale);
}
if (req.restarts < 1 && (req.request == "GET" || req.request == "HEAD")) {
restart;
}
/* else go to vcl_error to deliver a synthetic */
error 503;
}
/* set stale_if_error and stale_while_revalidate (customize these values) */
set beresp.stale_if_error = 86400s;
set beresp.stale_while_revalidate = 60s;
#FASTLY fetch
if(req.restarts > 0 ) {
set beresp.http.Fastly-Restarts = req.restarts;
}
if (beresp.http.Set-Cookie) {
set req.http.Fastly-Cachetype = "SETCOOKIE";
return (pass);
}
if (beresp.http.Cache-Control ~ "private") {
set req.http.Fastly-Cachetype = "PRIVATE";
return (pass);
}
if (beresp.status == 500 || beresp.status == 503) {
set req.http.Fastly-Cachetype = "ERROR";
set beresp.ttl = 1s;
set beresp.grace = 5s;
return (deliver);
}
if (beresp.http.Expires || beresp.http.Surrogate-Control ~ "max-age" || beresp.http.Cache-Control ~"(s-maxage|max-age)") {
# keep the ttl here
} else {
# apply the default ttl
set beresp.ttl = 15m;
}
return(deliver);
}
sub vcl_hit {
#FASTLY hit
if (!obj.cacheable) {
return(pass);
}
return(deliver);
}
sub vcl_miss {
#FASTLY miss
return(fetch);
}
sub vcl_deliver {
if (resp.status >= 500 && resp.status < 600) {
/* restart if the stale object is available */
if (stale.exists) {
restart;
}
}
#FASTLY deliver
unset resp.http.x-amzn-Remapped-Content-Length;
unset resp.http.x-amzn-RequestId;
# Never true
if ( req.url ) {
# set resp.http.request_parameters = req.http.request_parameters;
# set resp.http.canonical_request = req.http.canonical_request;
# set resp.http.string_to_sign = req.http.string_to_sign;
# set resp.http.Auth = req.http.Authorization;
# set resp.http.x-amz-date = req.http.x-amz-date;
}
return(deliver);
}
sub vcl_error {
if (obj.status >= 500 && obj.status < 600) {
/* deliver stale object if it is available */
if (stale.exists) {
return(deliver_stale);
}
}
#FASTLY error
# Handle redirects
if (obj.status == 850) {
set obj.http.Location = obj.response;
set obj.status = 301;
return(deliver);
}
return(deliver);
}
sub vcl_pass {
#FASTLY pass
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment