Last active
January 27, 2017 16:27
-
-
Save vvuksan/99bacbf1fd2140cea2f85ea70d30ab04 to your computer and use it in GitHub Desktop.
AWSv4 VCL signing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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