external auth basic

Sergey Skvortsov skv at protey.ru
Fri Jul 6 16:13:31 MSD 2007


Задача:

Есть frontend (nginx) - скажем для https://internal.com.
frontend проксирует запросы к backend'ам.

Аутентификация - HTTP Basic (поскольку используется строго SSL, то
паранойя приглушённо молчит).

Но, сама аутентификация и авторизация происходит на backend'ах -
пользователи хранятся в LDAP-сервере, доступ к ресурсам регулируется на
основе их вхождения в LDAP-группы и другими странными способами (скажем
через authz_svn).

Кроме всего этого nginx отдает статику - которая тоже предмет контроля
доступа.

Что хочется - аутентифицировать по HTTP Basic через внешний "authenticator".

Т.е. вместо директивы "auth_basic_user_file" использовать нечто иное -
желательно как можно более гибкое.

Видятся варианты:

1. Заголовок "Authorization"

Идея проста - проверять в if () наличия заголовка "Authorization", если
его нет - форсировать процесс запроса credentials у пользователя.

Если же есть - передавать запрос далее backend'у, который уже сам всё
проверит.

server {
...

if ($http_authorization !~ Basic) {
	add_header	WWW-Authenticate	"Basic realm=\"closed site\"";
	return 401;
}

Вариант теоретически рабочий (только для обработки статики придется
делать где-то на backend'е специальный handler, который будет каждый раз
проверять credentials и при успешной авторизации возвращать
Accel-Redirect на реальный файл).

"теоретически" рабочий - потому что add_header сейчас срабатывает только
для 200|204|301|302|304.

Возможно, имеет смысл добавить директиву типа "error_add_header" - по
аналогии с "err_headers_out" в Apache/mod_perl.

2. FCGI_AUTHORIZER.

Мощный способ, поскольку кроме аутентификации может и производить
авторизацию. (Кстати, есть в lighttpd.)

location /restricted {
	auth_basic           	 "closed site";
	auth_basic_authnz_location	/check_user;
}

location /check_user {
	internal;
	fastcgi_pass	localhost:9000;
	fastcgi_role	authorizer;
	fastcgi_param	QUERY_STRING	$query_string;
	fastcgi_param	REMOTE_USER	$remote_user;
	fastcgi_param	REMOTE_PASSWD	$remote_passwd;
	fastcgi_param	AUTH_REALM	$auth_realm;
}

Далее вроде все понятно. С реализованным мультиплексированием запросов
был бы вообще отличный вариант.

3. "auth_http" - как для IMAP

location /restricted {
	auth_basic      "closed site";
	auth_http	127.0.0.1:80/auth;
}

Далее как обычно.

Что передавать: "Auth-User", "Auth-Pass"
Что возвращает handler: "Auth-Status" = (200|401|403)

4. perl handler

Аналигично чему-то вышеописанному - на вход дается тройка (username,
password, query_string) - на выходе решение 200|401|403.

----------------

Итог - в общем-то нужно решить задачку, а не создавать сверхгибкое решение.

Но, всё же хочется видеть right-way направление - ведь интуитивно есть
такая штука как "nginx style" :)

-- 
Sergey Skvortsov
mailto: skv at protey.ru





More information about the nginx-ru mailing list