I want to have nginx for user level access control to specific url,
For other user <uid>, they are limited to access http://myserver.com/<uid> (METHOD POST). like user larrycai can only POST to http://myserver.com/larrycai/xxx.
I don't want to have this control in upstream server.
Basic authentication is used for access authentication like below
server {
...
auth_basic "Auth";
auth_basic_user_file conf/htpasswd;
}
Now how can I map the authenticated user to its own url ? (I am new to nginx).
My use case is the nginx docker container in front of docker-registry to have better user access control.
UPDATE in 2015.1.11
The uid is not related with unix system, it is for application only, which is mapped to REST interface
Is it possible to use extra module like openresty (lua based) ?
I have been able to work out a solution to enable many users to pull containers from my docker-registry and only special authorised users to push to my registry using ngx_openresty-1.7.7.1
/usr/local/openresty/nginx/conf/nginx.conf
worker_processes 1;
error_log /var/log/lua.log notice;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# For versions of nginx > 1.3.9 that include chunked transfer encoding support
# Replace with appropriate values where necessary
upstream docker-registry {
server localhost:5000;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/log/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
server {
listen 443;
server_name docker-registry01.company.com;
ssl on;
ssl_certificate /etc/ssl/certs/docker-registry;
ssl_certificate_key /etc/ssl/private/docker-registry;
client_max_body_size 0; # disable any limits to avoid HTTP 413 for large image uploads
# required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
chunked_transfer_encoding on;
location / {
auth_basic "Restricted";
auth_basic_user_file docker-registry.htpasswd;
access_by_lua_file 'authorize.lua';
include docker-registry.conf;
}
location /_ping {
auth_basic off;
include docker-registry.conf;
}
location /v1/_ping {
auth_basic off;
include docker-registry.conf;
}
}
}
/usr/local/openresty/nginx/conf/docker-registry.conf
proxy_pass http://docker-registry;
proxy_set_header Host $http_host; # required for docker client's sake
proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
proxy_set_header Authorization ""; # see https://github.com/dotcloud/docker-registry/issues/170
proxy_read_timeout 900;
/usr/local/openresty/nginx/authorize.lua
-- authorization rules
local restrictions = {
all = {
["^/$"] = { "HEAD" }
},
user = {
["^/$"] = { "HEAD", "GET" },
["^/v1/search$"] = { "HEAD", "GET" },
["^/v1/repositories/.*$"] = { "HEAD", "GET" },
["^/v1/images/.*$"] = { "HEAD", "GET" }
},
admin = {
["^/$"] = { "HEAD", "GET" },
["^/v1/search$"] = { "HEAD", "GET" },
["^/v1/repositories/.*$"] = { "HEAD", "GET", "PUT" },
["^/v1/images/.*$"] = { "HEAD", "GET", "PUT" }
}
}
-- list of roles and users
local user_role = {
all = {"all"},
user = {"user", "user2", "user3", "etc..."},
admin = {"admin", "dave_albert", "other_admin", "jenkins"}
}
-- get authenticated user as role
local user = ngx.var.remote_user
local role = nil
for _role, user_list in pairs(user_role) do
for k,user_name in pairs(user_list) do
if user_name == user then
role = _role
end
end
end
-- exit 403 when no matching role has been found
if restrictions[role] == nil then
ngx.header.content_type = 'text/plain'
ngx.status = 403
ngx.say("403 Forbidden: You don't have access to this resource/role.")
return ngx.exit(403)
end
-- get URL
local uri = ngx.var.uri
-- get method
local method = ngx.req.get_method()
local allowed = false
for path, methods in pairs(restrictions[role]) do
-- path matched rules?
local p = string.match(uri, path)
local m = nil
-- method matched rules?
for _, _method in pairs(methods) do
m = m and m or string.match(method, _method)
end
if p and m then
allowed = true
end
end
if not allowed then
ngx.header.content_type = 'text/plain'
ngx.log(ngx.WARN, "Role ["..role.."] not allowed to access the resource ["..method.." "..uri.."]")
ngx.status = 403
ngx.say("403 Forbidden: You don't have access to this resource.")
return ngx.exit(403)
else
ngx.log(ngx.WARN, "User ["..user.."] accessing resource ["..method.." "..uri.."]")
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With