Как сделать контроль доступа на уровне пользователя с помощью 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).

Мой вариант использования — контейнер док-станции nginx перед реестром докеров, чтобы иметь лучший контроль доступа пользователей.

ОБНОВЛЕНИЕ в 2015.1.11

uid не связан с системой unix, он предназначен только для приложения, которое отображается на интерфейс REST.

Можно ли использовать дополнительный модуль, например openresty (на основе lua)?


person Larry Cai    schedule 10.01.2015    source источник
comment
Ваш запрос немного сложен, он либо проходит, либо отклоняется, независимо от метода (может быть обходной путь, но это, вероятно, будет связано с условиями), тогда есть ваша система unix, которая никоим образом не может связать HTTP-запрос с системный пользователь, поэтому авторизация на основе пользователя слишком сложна   -  person Mohammad AbuShady    schedule 10.01.2015
comment
спасибо, обновите вопрос, чтобы уточнить, что uid не связан с unix, и он может использовать дополнительный модуль nginx   -  person Larry Cai    schedule 11.01.2015
comment
У меня нет большого опыта работы с модулями lua, если возможно, я рекомендую вам создать эту логику авторизации в вашем приложении, а не в самом веб-сервере, это было бы проще в обращении и более удобно в обслуживании.   -  person Mohammad AbuShady    schedule 11.01.2015
comment
спасибо, это может быть возможно. Но это даже сложно для меня, поскольку я использую официальный образ реестра Docker напрямую, я не хочу его трогать ;-)   -  person Larry Cai    schedule 11.01.2015
comment
Попробуйте: github.com/casbin/lua-casbin   -  person Yang Luo    schedule 26.03.2021


Ответы (2)


Мне удалось разработать решение, позволяющее многим пользователям извлекать контейнеры из моего реестра докеров, и только специально уполномоченным пользователям отправлять их в мой реестр с помощью 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
person Dave Albert    schedule 24.02.2015

Вы не можете видеть, получить пользователя в вашем конфиге.

Вы можете ограничить некоторый доступ через

location /larrycai {
    deny all;
}

В общем, вы не можете ограничить это через nginx. Вы можете написать PHP-скрипт, но это не то, что вы хотели бы иметь.

person Cr41s3    schedule 10.01.2015
comment
Я знаю. Но другого пути нет. - person Cr41s3; 10.01.2015
comment
обновите вопрос, чтобы узнать, можно ли здесь использовать дополнительный модуль, спасибо, контроль. - person Larry Cai; 11.01.2015