3

I am aware of the gazzilion pam / nginx questions here and on "Unix/Linux" but they are either unanswered or not related to my setup - so i try again :)

TL;dr

While the setup works perfectly with an Apache+mod_kerb_auth combination, i fail to get automatic ticket forwarding working when using nginx+pam_krb5 - basic authentication against kerberos works though. The question is, what could be the cause and/or how to further debug it.

Below you find all the details, configs and environment


My setup:

  • Windows 2012 DC in a lab (freshly installed and configured for KDC)
  • Debian Stretch Linux as our "Service"
  • On that Debian box i have:kerb-client MIT, Apache2+mod_kerb_auth and nignx+nginx_pam+pam
  • a MacOS client

what is working:

  • I have the usual setup with keytab-file, /etc/krb5.conf with all the realm/default_realm bits and pieces. (see below)
  • I can kinit using the keytab file and my SPN: HTTP/wiki.kwtest.local (see below)
  • Using Apache2 + mod_kerb_auth on the same Debian Server, it works entirely including the ticket forwarding ( confirms that krb5.conf / keytab / KDC /infra setup works i guess). So i can use kinit + curl --negotiate or Safari on my OSX and get access right away.
  • Adding the pam auth ( see below ) and the pam setup, i can authenticate entering the AD user credentials when accessing through safari ( curl gets 401 right away due to -u ) ... but ticket forwarding/verification does not work

Setup-Details:

Kerberos client configuration /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 configuration at /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 configuration of that default server at /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;
    }
}

KVNO numbers match

#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 file from /mnt/config/kerberos/drupalwiki.keytab lists the 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)

Login with the keytab file works using the 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

Question (things not working):

Ticket forwarding, so existing client tickets, are not validated, instead a basic-auth form is presented to enter the credentials - if i do so, i can authenticate. So basic krb authentication already works, just not ticket forwarding/validation.

Please be aware, that the exact same client (OSX Safari, OSX curl, Linux Curl), the exact same Debian Stretch server does work with Apache2+mod_ker_auth. So it hardly can be a straight forward issues with the service keytab file or /etc/krb5.conf, otherwise apache2 would not work either, right?

How i tested

Testing from my OSX client using

# 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>

Doing the same test, while stopping nginx and startin apache2

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

Now on my OSX box

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

What i have tried to fix it

  • tried to get pam as verbose as possible using rsyslog and the debug=true / trace=/var/log/pamtrace settings, but i never got any output in there. PAM seems just failing log the auth attempt at all somehow. Only when i fill auth the basic form and actually authenticate successfully, i see this attempt in the logs - but the failed attempt using the existing tickets does not log anything at all
  • playing around with all the pam_krb5 parameters and settings like realm and such, but i cannot get it working nevertheless
  • used a linux client to test with curl, same result

Let me now if i forgot anything in the setup details or informations, i am perfectly aware that kerberos is complex and sensible to all those things, i hope to have included all the bits and pieces

Eugen Mayer
  • 277
  • 1
  • 4
  • 15

1 Answers1

2

The short answer to this question is, that is not possible with nginx_pam at all.

The technical term / protocol i ask for is "GSSAPI" or SPENGO based kerberos ticket authentication, so a user is automatically logged in if he has a existing kerberos ticket.

nginx_pam does not implement SPENGO/GSSAPI thus that will never work. What should happen is

  1. on the first request the client asks for a resource (does not send any authentication header yet)

  2. our nginx will pass that down through nginx_pam to pam, pam should then return "unauthorized" (no auth headers present). Nginx should now return a "401" with an header "WWW-Authorize: negotiate" to the browser (the browser then automatically sends a new request with the kerb ticket in the "Authorization" header

  3. nginx should now unpack that ticket (based64 decode and such) and pass the ticket to pam (pam_krb)

  4. pam will either return "ok" or "forbidden" ( not allowed for this user ).. the former is 200, the latter 403 for nginx passed to the client

Step 2 is not implemented by nginx_pam. Also, i am guessing ( not sure ), that pam rather only supports "authorized" or "not authorized", so boolean, not "unauthenticated", "authorized", "forbidden" .. .. so step 2 and 4 cannot be determinated (are the same)

Solution: I switched to https://github.com/stnoonan/spnego-http-auth-nginx-module for a proper GSSAPI based implementation.

Eugen Mayer
  • 277
  • 1
  • 4
  • 15