Skip to content

Instantly share code, notes, and snippets.

@rezan
Created April 15, 2020 15:47
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 rezan/18d86a70cac248a855bbec5480565a65 to your computer and use it in GitHub Desktop.
Save rezan/18d86a70cac248a855bbec5480565a65 to your computer and use it in GitHub Desktop.
AWS Secrets Manager Varnish VCL Implementation
#
# AWS Secrets Manager v1.0
#
import crypto;
import http;
import json;
import kvstore;
import utils;
sub vcl_init
{
# Init the secret storage
new aws_secret = kvstore.init();
}
sub aws_get_secret
{
#
# aws_secret kvstore must be initialized:
#
# aws_secret.init_conf("/etc/varnish/aws_secret.conf");
#
# OR:
#
# aws_secret.set("access-key", "AKAI...");
# aws_secret.set("secret-key", "...");
# aws_secret.set("region", "us-west-2");
# aws_secret.set("secret-id", "mykey");
# aws_secret.set("version-stage", "AWSPREVIOUS"); //optional, default AWSCURRENT
#
# Response:
#
# aws_secret.get("secret");
# aws_secret.get("response-status");
# aws_secret.get("response-code");
# aws_secret.get("response-body");
#
# Setup
aws_secret.delete("secret");
aws_secret.delete("response-status");
aws_secret.delete("response-code");
aws_secret.delete("response-body");
# Incorrect configuration error
if (!aws_secret.get("access-key") || !aws_secret.get("secret-key") ||
!aws_secret.get("region") || !aws_secret.get("secret-id")) {
return (fail("Configuration not found. Required: access-key, secret-key, region, secret-id"));
}
# More setup
aws_secret.set("_payload", {"
{
"SecretId": "} + json.stringify(aws_secret.get("secret-id")) + {",
"VersionStage": "} + json.stringify(aws_secret.get("version-stage", "AWSCURRENT")) + {"
}
"});
# Prepare the AWS secretsmanager v4 signed request
http.init(0, LOW);
http.req_set_method(0, "POST");
http.req_set_url(0, "https://secretsmanager." + aws_secret.get("region") + ".amazonaws.com/");
http.req_set_sparam(0, "POSTFIELDS", aws_secret.get("_payload"));
http.req_set_header(0, "Content-Type", "application/x-amz-json-1.1");
http.req_set_header(0, "Host", "secretsmanager." + aws_secret.get("region") + ".amazonaws.com");
http.req_set_header(0, "x-amz-target", "secretsmanager.GetSecretValue");
http.req_set_header(0, "x-amz-date", utils.time_format("%Y%m%dT%H%M%SZ"));
http.req_set_header(0, "s3-datestamp", utils.time_format("%Y%m%d"));
http.req_set_header(0, "s3-signed-headers", "host;x-amz-content-sha256;x-amz-date;x-amz-target");
http.req_set_header(0, "s3-scope", http.req_get_header(0, "s3-datestamp") + "/" +
aws_secret.get("region") + "/secretsmanager/aws4_request");
http.req_set_header(0, "x-amz-content-sha256",
crypto.hex_encode(crypto.hash(sha256, aws_secret.get("_payload"))));
http.req_set_header(0, "s3-canonical-request",
crypto.hex_encode(crypto.hash(sha256,
"POST" + utils.newline() +
"/" + utils.newline() +
"" + utils.newline() +
"host:" + http.req_get_header(0, "Host") + utils.newline() +
"x-amz-content-sha256:" + http.req_get_header(0, "x-amz-content-sha256") + utils.newline() +
"x-amz-date:" + http.req_get_header(0, "x-amz-date") + utils.newline() +
"x-amz-target:" + http.req_get_header(0, "x-amz-target") + utils.newline() +
utils.newline() +
http.req_get_header(0, "s3-signed-headers") + utils.newline() +
http.req_get_header(0, "x-amz-content-sha256"))
));
http.req_set_header(0, "s3-signature",
crypto.hex_encode(crypto.hmac(sha256,
crypto.hmac(sha256,
crypto.hmac(sha256,
crypto.hmac(sha256,
crypto.hmac(sha256,
crypto.blob("AWS4" + aws_secret.get("secret-key")),
http.req_get_header(0, "s3-datestamp")),
aws_secret.get("region")),
"secretsmanager"),
"aws4_request"),
"AWS4-HMAC-SHA256" + utils.newline() +
http.req_get_header(0, "x-amz-date") + utils.newline() +
http.req_get_header(0, "s3-scope") + utils.newline() +
http.req_get_header(0, "s3-canonical-request"))
));
http.req_set_header(0, "Authorization",
"AWS4-HMAC-SHA256 " +
"Credential=" + aws_secret.get("access-key") + "/" +
http.req_get_header(0, "s3-scope") + ", " +
"SignedHeaders=" + http.req_get_header(0, "s3-signed-headers") + ", " +
"Signature=" + http.req_get_header(0, "s3-signature"));
http.req_unset_header(0, "s3-prefix");
http.req_unset_header(0, "s3-datestamp");
http.req_unset_header(0, "s3-signed-headers");
http.req_unset_header(0, "s3-scope");
http.req_unset_header(0, "s3-canonical-request");
http.req_unset_header(0, "s3-signature");
# Send the request
http.req_send(0);
http.resp_wait(0);
# Set the response fields
aws_secret.set("response-status", http.resp_get_status(0));
aws_secret.set("response-code", http.resp_get_errorcode(0));
aws_secret.set("response-body", http.resp_get_body(0));
# Find the SecretString in the payload
if (http.resp_get_status(0) == 200) {
json.parse(http.resp_get_body(0));
if (json.is_object() && json.get("SecretString")) {
aws_secret.set("secret", json.get("SecretString"));
}
}
# Done
http.finish(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment