如何使用nginx进行用户级访问控制
How to do user level access control using nginx
我想要 nginx 用于特定 url、
的用户级访问控制
对于其他用户 <uid>
,他们只能访问 http://myserver.com/<uid>
(方法 POST
)。像用户 larrycai
只能 POST 到 http://myserver.com/larrycai/xxx
。
我不想在上游服务器中使用此控件。
基本认证用于如下访问认证
server {
...
auth_basic "Auth";
auth_basic_user_file conf/htpasswd;
}
现在如何将经过身份验证的用户映射到它自己的 url? (我是 nginx 的新手)。
我的用例是 docker-registry 前面的 nginx docker 容器有更好的用户访问控制。
2015.1.11 更新
uid
与unix系统无关,仅供应用,映射到REST接口
是否可以使用像 openresty 这样的额外模块(基于lua)?
你看不到,在你的配置中获取用户。
您可以通过
限制某些访问
location /larrycai {
deny all;
}
总而言之,你不能通过 nginx 限制它。
您可以编写一个 PHP 脚本,但这似乎不是您想要的。
我已经能够找到一个解决方案,使许多用户能够从我的 docker-注册表中提取容器,并且只有特殊授权的用户才能使用 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
我想要 nginx 用于特定 url、
的用户级访问控制对于其他用户 <uid>
,他们只能访问 http://myserver.com/<uid>
(方法 POST
)。像用户 larrycai
只能 POST 到 http://myserver.com/larrycai/xxx
。
我不想在上游服务器中使用此控件。
基本认证用于如下访问认证
server {
...
auth_basic "Auth";
auth_basic_user_file conf/htpasswd;
}
现在如何将经过身份验证的用户映射到它自己的 url? (我是 nginx 的新手)。
我的用例是 docker-registry 前面的 nginx docker 容器有更好的用户访问控制。
2015.1.11 更新
uid
与unix系统无关,仅供应用,映射到REST接口
是否可以使用像 openresty 这样的额外模块(基于lua)?
你看不到,在你的配置中获取用户。
您可以通过
限制某些访问location /larrycai {
deny all;
}
总而言之,你不能通过 nginx 限制它。 您可以编写一个 PHP 脚本,但这似乎不是您想要的。
我已经能够找到一个解决方案,使许多用户能够从我的 docker-注册表中提取容器,并且只有特殊授权的用户才能使用 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