Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,19 @@ nearly all AWS services.
## Example

```nginx

#You're limited by your max_body_size (and memory it may take up)
client_max_body_size 1G;
client_body_buffer_size 1024M;
client_body_in_single_buffer on;

map $request_uri $request_uri_no_parameters {
"~^(?P<path>.*?)(\?.*)*$" $path;
}

location / {
set $s3_host s3.amazonaws.com;
set $s3_uri $request_uri;
set $s3_uri $request_uri_no_parameters;
access_by_lua "local aws = require 'resty.aws'; aws.s3_set_headers(ngx.var.access_key, ngx.var.secret_key, ngx.var.s3_host, ngx.var.s3_uri)";
proxy_pass https://$s3_host$s3_uri;
}
Expand Down
64 changes: 49 additions & 15 deletions lib/resty/aws.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ local resty_hmac = require('resty.hmac')
local resty_sha256 = require('resty.sha256')
local str = require('resty.string')

local _M = { _VERSION = '0.1.2' }
local _M = { _VERSION = '0.1.3' }

local function get_iso8601_basic(timestamp)
return os.date('!%Y%m%dT%H%M%SZ', timestamp)
Expand All @@ -17,15 +17,15 @@ end
local function get_derived_signing_key(keys, timestamp, region, service)
local h_date = resty_hmac:new('AWS4' .. keys['secret_key'], resty_hmac.ALGOS.SHA256)
h_date:update(get_iso8601_basic_short(timestamp))
k_date = h_date:final()
local k_date = h_date:final()

local h_region = resty_hmac:new(k_date, resty_hmac.ALGOS.SHA256)
h_region:update(region)
k_region = h_region:final()
local k_region = h_region:final()

local h_service = resty_hmac:new(k_region, resty_hmac.ALGOS.SHA256)
h_service:update(service)
k_service = h_service:final()
local k_service = h_service:final()

local h = resty_hmac:new(k_service, resty_hmac.ALGOS.SHA256)
h:update('aws4_request')
Expand All @@ -49,12 +49,40 @@ local function get_sha256_digest(s)
return str.to_hex(h:final())
end

local function get_canonical_query_string()
local args = ngx.req.get_uri_args()
local query_string = ''
for key, val in pairs(args) do
if query_string ~= '' then
query_string = '&' .. query_string
end

if type(val) == "table" then
query_string = ngx.escape_uri(key) .. '=' .. ngx.escape_uri(val[0]) .. query_string --Get the first instance of said argument, ignore the others. (Note: Maybe we should just include all instances of said parameter?)
else
if val == true then
query_string = ngx.escape_uri(key) .. '=' .. query_string
else
query_string = ngx.escape_uri(key) .. '=' .. ngx.escape_uri(val) .. query_string
end
end
end

return query_string
end

local function get_hashed_canonical_request(timestamp, host, uri)
local digest = get_sha256_digest(ngx.var.request_body)
local canonical_request = ngx.var.request_method .. '\n'
.. uri .. '\n'
.. '\n'
.. 'host:' .. host .. '\n'
local digest
if ngx.var.request_body == nil and ngx.var.request_method == 'PUT' then
digest = 'UNSIGNED-PAYLOAD'
else
digest = get_sha256_digest(ngx.var.request_body)
end
local canonical_request =
ngx.var.request_method .. '\n'
.. uri .. '\n'
.. get_canonical_query_string() .. '\n'
.. 'host:' .. host .. '\n'
.. 'x-amz-content-sha256:' .. digest .. '\n'
.. 'x-amz-date:' .. get_iso8601_basic(timestamp) .. '\n'
.. '\n'
Expand Down Expand Up @@ -106,23 +134,29 @@ local function get_service_and_region(host)
return nil, nil
end

function _M.aws_set_headers(access_key, secret_key, host, uri)
function _M.aws_set_headers(access_key, secret_key, host, uri, region, service)
local creds = {
access_key = access_key,
secret_key = secret_key
}
local timestamp = tonumber(ngx.time())
local service, region = get_service_and_region(host)
if region == nil or service == nil then
service, region = get_service_and_region(host)
end
local auth = get_authorization(creds, timestamp, region, service, host, uri)

ngx.req.set_header('Authorization', auth)
ngx.req.set_header('Host', host)
ngx.req.set_header('x-amz-date', get_iso8601_basic(timestamp))
end

function _M.s3_set_headers(access_key, secret_key, host, uri)
_M.aws_set_headers(access_key, secret_key, host, uri)
ngx.req.set_header('x-amz-content-sha256', get_sha256_digest(ngx.var.request_body))
function _M.s3_set_headers(access_key, secret_key, host, uri, region, service)
_M.aws_set_headers(access_key, secret_key, host, uri, region, service)
if ngx.var.request_body == nil and ngx.var.request_method == 'PUT' then
ngx.req.set_header('x-amz-content-sha256', 'UNSIGNED-PAYLOAD')
else
ngx.req.set_header('x-amz-content-sha256', get_sha256_digest(ngx.var.request_body))
end
end

return _M
return _M