Назад | Перейти на главную страницу

PAM с pam_krb5 для аутентификации запросов nginx

Мне известно о вопросах gazzilion pam / nginx здесь и в "Unix / Linux", но они либо остались без ответа, либо не связаны с моей настройкой - поэтому я пытаюсь снова :)

TL; dr

Хотя установка отлично работает с Apache+mod_kerb_auth комбинация, я не могу заставить автоматическую пересылку билетов работать при использовании nginx+pam_krb5 - хотя базовая аутентификация против кербероса работает. Вопрос в том, в чем может быть причина и / или как ее дальше отлаживать.

Ниже вы найдете все детали, конфигурации и среду.


Моя установка:

что работает:


Детали установки:

Конфигурация клиента Kerberos /etc/krb5.conf

[libdefaults]
  default_realm = KWTEST.LOCAL
  kdc_timesync = 1
  # https://web.mit.edu/kerberos/krb5-1.12/doc/basic/ccache_def.html
  # we do not want the keyring due to docker
  ccache_type = 3
  forwardable = true
  proxiable = true
  # no reverse lookup
  rdns = false

[realms]
  KWTEST.LOCAL = {
    kdc = kdc.kwtest.local
    admin_server = kdc.kwtest.local
  }

[login]
  krb4_convert = true
  krb4_get_tickets = false

[logging]
  default = FILE:/var/log/kdc.log:SYSLOG
  kdc = FILE:/var/log/kdc.log:SYSLOG

# https://web.mit.edu/kerberos/krb5-1.12/doc/admin/conf_files/krb5_conf.html?highlight=appdefaults#appdefaults
[appdefaults]
  forwardable = true
  # https://manpages.debian.org/stretch/libpam-heimdal/pam_krb5.5.en.html
  pam = {
    ignore_k5login=true
    debug=true
    forwardable = true
    proxiable = true
    minimum_uid = 0
    realm = KWTEST.LOCAL
    keytab = /mnt/config/kerberos/drupalwiki.keytab
  }

Конфигурация Pam в /etc/pam.d/dw-kerb-nginx

cat /etc/pam.d/dw-kerb-nginx

auth  required  pam_krb5.so keytab=/mnt/config/kerberos/drupalwiki.keytab minimum_uid=20 forwardable=true realm=KWTEST.LOCAL trace=/var/log/pamtrace silent=false debug=true
account  required  pam_unix.so keytab=/mnt/config/kerberos/drupalwiki.keytab minimum_uid=20 forwardable=true realm=KWTEST.LOCAL trace=/var/log/pamtrace silent=false debug=true

Конфигурация Nginx этого сервера по умолчанию в /etc/nginx/sites-enabled/default

cat /etc/nginx/sites-enabled/default

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/html;

    index index.html index.htm index.nginx-debian.html;

    server_name _;

        error_log /var/log/nginx/error.log debug;
        location / {
          auth_pam              "Secure Zone";
          auth_pam_service_name "dw-kerb-nginx";
          try_files $uri $uri/ =404;
    }
}

Совпадение номеров КВНО

#kdc KVNO
kvno HTTP/wiki.kwtest.local@KWTEST.LOCAL
HTTP/wiki.kwtest.local@KWTEST.LOCAL: kvno = 16

#client KVNO
klist -ke /mnt/config/kerberos/drupalwiki.keytab
Keytab name: FILE:/mnt/config/kerberos/drupalwiki.keytab
KVNO Principal
---- --------------------------------------------------------------------------
  16 HTTP/wiki.kwtest.local@KWTEST.LOCAL (arcfour-hmac)

Файл Service Keytab из /mnt/config/kerberos/drupalwiki.keytab перечисляет SPN

klist -ke /mnt/config/kerberos/drupalwiki.keytab
Keytab name: FILE:/mnt/config/kerberos/drupalwiki.keytab
KVNO Principal
---- --------------------------------------------------------------------------
  16 HTTP/wiki.kwtest.local@KWTEST.LOCAL (arcfour-hmac)

Войти с помощью keytab файл работает с использованием SPN

kinit -k -t /mnt/config/kerberos/drupalwiki.keytab HTTP/wiki.kwtest.local@KWTEST.LOCAL

klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: HTTP/wiki.kwtest.local@KWTEST.LOCAL

Valid starting       Expires              Service principal
01/07/2019 12:50:18  01/07/2019 22:50:18  krbtgt/KWTEST.LOCAL@KWTEST.LOCAL
    renew until 01/08/2019 12:50:18

Вопрос (что-то не работает):

Пересылка билетов, поэтому существующие клиентские билеты не проверяются, вместо этого предоставляется форма базовой аутентификации для ввода учетных данных - если я это сделаю, я могу пройти аутентификацию. Таким образом, базовая аутентификация krb уже работает, только не пересылка / проверка билетов.

Имейте в виду, что один и тот же клиент (OSX Safari, OSX curl, Linux Curl), точно такой же сервер Debian Stretch работает с Apache2+mod_ker_auth. Так что вряд ли могут быть прямые проблемы с сервисом keytab файл или /etc/krb5.conf, иначе apache2 тоже не работал бы, верно?

Как я тестировал

Тестирование с моего клиента OSX с использованием

# wikiuser is an user in the same AD/KDC ( not the user of the SPN)
kinit wikiuser@KWTEST.LOCAL

# ticket exists
klist
Credentials cache: API:34173A61-DFBB-4191-A39C-62EF67F1AC39
        Principal: wikiuser@KWTEST.LOCAL

  Issued                Expires               Principal
Jan  7 13:26:38 2019  Jan  7 23:26:20 2019  krbtgt/KWTEST.LOCAL@KWTEST.LOCAL

# the actual test
curl -u : --negotiate http://wiki.kwtest.local/index.html
<html>
<head><title>401 Authorization Required</title></head>
<body bgcolor="white">
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.10.3</center>
</body>
</html>

Выполнение того же теста при остановке nginx и запуске apache2

# on the Debian Service box
service nginx stop && service apache2 start

Теперь на моей коробке OSX

kinit
curl -u : --negotiate http://wiki.kwtest.local/index.html
worked!%

Что я пытался исправить


Позвольте мне сейчас, если я забыл что-то в деталях установки или информации, я прекрасно понимаю, что Kerberos сложен и разумен для всех этих вещей, я надеюсь, что включил все детали

Короткий ответ на этот вопрос: с nginx_pam это вообще невозможно.

Технический термин / протокол, о котором я прошу, - это аутентификация Kerberos на основе GSSAPI или SPENGO, поэтому пользователь автоматически входит в систему, если у него есть существующий билет Kerberos.

nginx_pam не реализует SPENGO / GSSAPI, поэтому это никогда не сработает. Что должно произойти

  1. при первом запросе клиент запрашивает ресурс (еще не отправляет заголовок аутентификации)

  2. наш nginx передаст это через nginx_pam в pam, затем pam должен вернуть «unauthorized» (без заголовков auth). Теперь Nginx должен возвращать браузеру «401» с заголовком «WWW-Authorize :gotiate» (затем браузер автоматически отправляет новый запрос с ограниченным тикетом в заголовке «Авторизация».

  3. nginx теперь должен распаковать этот билет (декодирование на основе 64 и т. д.) и передать билет в pam (pam_krb)

  4. pam вернет либо "ok", либо "запрещено" (не разрешено для этого пользователя). первое - 200, второе - 403 для nginx, переданное клиенту

Шаг 2 не реализован nginx_pam. Кроме того, я предполагаю (не уверен), что pam скорее поддерживает только «авторизованный» или «не авторизованный», поэтому логические, а не «неаутентифицированные», «авторизованные», «запрещенные» ... так что шаги 2 и 4 не могут быть определены (одинаковы)

Решение: Я переключился на https://github.com/stnoonan/spnego-http-auth-nginx-module для правильной реализации на основе GSSAPI.