Skip to content

Instantly share code, notes, and snippets.

@Ara4Sh
Forked from justincormack/nginx.conf
Created August 28, 2019 18:01
Show Gist options
  • Save Ara4Sh/9dcf8b103843a74e830fd505a748f904 to your computer and use it in GitHub Desktop.
Save Ara4Sh/9dcf8b103843a74e830fd505a748f904 to your computer and use it in GitHub Desktop.
Using Lua and Nginx to proxy Amazon web services example
# example location parts of nginx.conf
# add your own AWS keys, server lines etc, and set your aws domains, paths
http {
# you will need the luacrypto in the cpath, download from http://luacrypto.luaforge.net/
lua_package_cpath "/home/justin/lua/luacrypto-0.2.0/src/l?.so.0.2.0;;";
server {
listen 80;
location ~ "^/sdb.*$" {
set $aws_access_key "%AWS_ACCESS_KEY%";
set $aws_secret_key "%AWS_SECRET_KEY%";
set $domain "index.node3.org";
set_by_lua_file $query "..path to../sdb.lua";
rewrite .* /?$query break;
proxy_pass http://sdb.amazonaws.com;
}
location ~ "^/s3/(.*)$" {
set $aws_access_key "%AWS_ACCESS_KEY%";
set $aws_secret_key "%AWS_SECRET_KEY%";
set $bucket "repo.node3.org";
set $key $1;
set_by_lua $now "return ngx.cookie_time(ngx.time())";
set $string_to_sign "$request_method\n$http_content_md5\n$http_content_type\n\nx-amz-date:$now\n/$bucket/$key";
set_by_lua $aws_signature "
local crypto = require 'crypto'
digest = crypto.hmac.digest('sha1', ngx.var.string_to_sign, ngx.var.aws_secret_key, true)
return ngx.encode_base64(digest)
";
proxy_set_header x-amz-date $now;
proxy_set_header Authorization "AWS $aws_access_key:$aws_signature";
rewrite .* /$key break;
proxy_set_header Host $bucket.s3.amazonaws.com;
proxy_pass http://s3.amazonaws.com;
}
}
}
local crypto = require 'crypto'
a = ngx.var.args
ts = {}
ks = {}
es = {}
function kv(s)
local l
if #s == 0 then return end
l = string.find(s, '=', 1, true)
if l == nil then
return s, ''
else
return string.sub(s, 1, l - 1), string.sub(s, l + 1)
end
end
-- unreserved characters are unchanged, others % encoded.
-- http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/index.html?Query_QueryAuth.html
-- A-Z, a-z, 0-9, hyphen ( - ), underscore ( _ ), period ( . ), and tilde ( ~ ).
-- note we do not re-urlencode inbound data, as nginx does not decode, so this should be encoded using these same rules to pass signature
function psub(c)
return '%' .. string.format('%2X', string.byte(c, 1))
end
function urlencode(s)
return string.gsub(s, '[^a-zA-Z0-9%-_%.~]', psub)
end
function extra(k, v)
local uv = urlencode(v)
es[k] = uv
if ts[k] == nil then
ts[k] = uv
table.insert(ks, k)
end
end
local utc = ngx.utctime()
local now = string.sub(utc, 1, 10) .. 'T' .. string.sub(utc, 12) .. 'Z'
ll = 0
local l, s, k, v
while true do
l = string.find(a, '&', ll, true)
if l ~= nil then
s = string.sub(a, ll, l - 1)
else
s = string.sub(a, ll)
end
k, v = kv(s)
if k then
ts[k] = v
table.insert(ks, k)
end
if l == nil then break end
ll = l + 1
end
extra('Timestamp', now)
extra('Version', '2009-04-15')
extra('SignatureMethod', 'HmacSHA256')
extra('SignatureVersion', '2')
extra('AWSAccessKeyId', ngx.var.aws_access_key)
extra('DomainName', ngx.var.domain)
table.sort(ks)
for k, v in pairs(ks) do
ks[k] = v .. '=' .. ts[v]
end
string_to_sign = 'GET\nsdb.amazonaws.com\n/\n' .. table.concat(ks, '&')
signature = ngx.encode_base64(crypto.hmac.digest('sha256', string_to_sign, ngx.var.aws_secret_key, true))
-- note we return additional query string, as nginx rewrite leaves original parameters
ee = {}
for k, v in pairs(es) do
table.insert(ee, k .. '=' .. v)
end
query = table.concat(ee, '&') .. '&Signature=' .. urlencode(signature)
return query
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment