Nginx lua plugin for uploads authentication
Sometimes you want to allow your HTTP clients to upload files to a protected location without having to pass data through a secure intermediary proxy node that protect the access credentials. The clients must first request a signed URL from a third-party and then can upload the file using a HTTP POST or PUT, thus reducing latency.
For this example the signed URL has the following structure:
https://<fqdn>/<uri>?e=<timetamp>&s=<signature>
where:
- <signature>=hmac(<password>, <uri>|<http method>|<expire timestamp>)
- <timestamp> is the unix time designating the expiration of the URL
- <password> is a shared secret between the HTTP server and the third party involved.
The authentication scheme is similar to the Amazon AWS signature.
The code is listed bellow (access.lua):
local expire = ngx.var.arg_e local sign = ngx.var.arg_s local uri = ngx.var.uri local method = ngx.var.request_method local path = "" local secret = "password" local hmac = require "resty.hmac" local hmac_sha256 = hmac:new(secret, hmac.ALGOS.SHA256) if not hmac_sha256 then ngx.log(ngx.STDERR, "failed to create the hmac_sha256 object") return end --ngx.log(ngx.STDERR, "uri= " .. uri .. " method= " .. method .. " expire= " .. expire .. " sign= " .. sign) if expire ~= nul and sign ~= null and uri:find("upload") and method == "PUT" then local digest = hmac_sha256:final(uri..method..expire, true) ngx.log(ngx.STDERR, "time="..os.time() .. " inputData= " .. uri.."|"..method.."|"..expire .. " sha256: " .. digest) if digest == sign and tonumber(expire) > os.time() then ngx.log(ngx.STDERR, "Upload ok") return ngx.OK end elseif method == "GET" then return ngx.OK end return ngx.exit(403)
And the corresponding nginx server configurations:
location /upload/ { lua_code_cache on; access_by_lua_file 'sites-available/access.lua'; root /var/dav; client_body_temp_path /var/dav/temp; dav_methods PUT DELETE; create_full_put_path on; dav_access user:rw group:rw all:rw; autoindex off; }
The nginx server must be compiled with the openresty/lua-nginx-module.