1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
Crash course to Windows KDC Configuration
=========================================
On the AD side, you need to:
* Create a new user, whose name should be the service name you'll be using
Kerberos authentication on. E.g. `app.example`.
* Set the "User cannot change password" and "Password never expires" options
on the account. If you are using AES-128 or AES-256, set also the "This
account supports Kerberos AES 128 bit encryption" option or the 256 bit one.
It is recommended to use AES, see [here](https://blogs.technet.microsoft.com/petergu/2013/04/14/interpreting-the-supportedencryptiontypes-registry-key/)
for more details.
* Set a strong password on it. Feel free to forget it, you are not going to
insert it anywhere.
* From a Windows `cmd.exe` window, generate the service principals and keytabs
for this user using [`ktpass`](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/ktpass).
You need an SPN named `host/foo.example.com`, and another named
`HTTP/foo.example.com`.
It is **crucial** that `foo.example.com` is the DNS name of your web site in the
intranet, and it is an `A` record.
Given that `app.example` is the account name you created, you would execute,
**in this exact order**:
C:\> ktpass -princ host/foo.example.com@EXAMPLE.COM -mapuser
EXAMPLECOM\app.example -pass * -out host.foo.keytab -ptype KRB5_NT_PRINCIPAL
-crypto AES256-SHA1
C:\> ktpass -princ HTTP/foo.example.com@EXAMPLE.COM -mapuser
EXAMPLECOM\app.example -pass * -out http.foo.keytab -ptype KRB5_NT_PRINCIPAL
-crypto AES256-SHA1
* If you need to support multiple host names using the same service account,
you can issue further `ktpass` commands, but **ensure to issue the `host/`
one first and the `HTTP/` one after**. Example:
C:\> ktpass -princ host/bar.example.com@EXAMPLE.COM -mapuser
EXAMPLECOM\app.example -pass * -out host.bar.keytab -ptype KRB5_NT_PRINCIPAL
-crypto AES256-SHA1
C:\> ktpass -princ HTTP/bar.example.com@EXAMPLE.COM -mapuser
EXAMPLECOM\app.example -pass * -out http.bar.keytab -ptype KRB5_NT_PRINCIPAL
-crypto AES256-SHA1
* Verify that the correct SPNs are created using [`setspn`](https://social.technet.microsoft.com/wiki/contents/articles/717.service-principal-names-spns-setspn-syntax-setspn-exe.aspx)
C:\> setspn -Q */foo.example.com
it should yield both the `HTTP/` and `host/` SPNs, both mapped to the
`app.example` user. Example with a service accessible via both
`foo.example.com` and `bar.example.com`:
C:\Temp>setspn -Q */foo.example.com
Checking domain DC=example,DC=com
CN=app.example,OU=Service Accounts,DC=example,DC=com
HTTP/bar.example.com
host/bar.example.com
HTTP/foo.example.com
host/bar.example.com
`setspn` lists the entries in the reverse order they were created. So **it is crucial
that the HTTP and host entries are in pairs, in that order**.
Crash course to UNIX KRB5 and nginx configuration
-------------------------------------------------
* Verify that your UNIX machine is using the same DNS server as your DC, most
likely it'll use the DC itself.
* Create an `/etc/krb5.conf` configuration file, replacing the realm and kdc
host names with your own AD setup:
[libdefaults]
default_tgs_enctypes = aes256-cts-hmac-sha1-96
default_tkt_enctypes = aes256-cts-hmac-sha1-96
default_keytab_name = FILE:/etc/krb5.keytab
default_realm = EXAMPLE.COM
ticket_lifetime = 24h
kdc_timesync = 1
ccache_type = 4
forwardable = false
proxiable = false
[realms]
EXAMPLE.COM = {
kdc = dc.example.com
admin_server = dc.example.com
default_domain = example.com
}
[domain_realm]
.kerberos.server = EXAMPLE.COM
.example.com = EXAMPLE.COM
* Copy the keytab files (`host.foo.keytab`, `http.foo.keytab`, etc) created
with `ktpass` on Windows to your UNIX machine.
* Create a `krb5.keytab` using `ktutil`, concatenating together the keytabs
generated by `ktpass`:
# ktutil
ktutil: rkt host.foo.keytab
ktutil: rkt http.foo.keytab
ktutil: rkt host.bar.keytab
ktutil: rkt http.bar.keytab
ktutil: wkt /etc/krb5.keytab
ktutil: quit
* Verify that the created keytab file has been built correctly:
# klist -kt /etc/krb5.keytab
Keytab name: FILE:/etc/krb5.keytab
KVNO Timestamp Principal
---- ----------------- --------------------------------------------------------
1 02/19/13 04:02:48 host/foo.example.com@EXAMPLE.COM
2 02/19/13 04:02:48 HTTP/foo.example.com@EXAMPLE.COM
3 02/19/13 04:02:48 host/bar.example.com@EXAMPLE.COM
4 02/19/13 04:02:48 HTTP/bar.example.com@EXAMPLE.COM
Key version numbers (`KVNO`) will be different in your case.
* Verify that you are able to authenticate using the keytab, without password:
# kinit -5 -V -k -t /etc/krb5.keytab HTTP/bar.example.com
Authenticated to Kerberos v5
# klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: HTTP/foo.example.com@EXAMPLE.COM
Valid starting Expires Service principal
02/19/13 17:37:42 02/20/13 03:37:40 krbtgt/EXAMPLE.COM@EXAMPLE.COM
renew until 02/20/13 17:37:42
Please note that you will be able to authenticate **only** with the **LAST**
SPN that has been configured via `ktpass`, as windows user accounts keep the
mapping only with a single SPN, and that is the one displayed in the "User
logon name" field in the "Account" pane of an user account details screen of
Active Directory Users and Computers, or the first result of `setspn -Q`.
* Make the keytab file readable only by root and the nginx group:
# chmod 440 /etc/krb5.keytab
# chown root:nginx /etc/krb5.keytab
* Configure a SPNEGO-protected location in the nginx configuration file:
server {
server_name foo.example.com;
ssl on;
ssl_certificate example.com.crt;
ssl_certificate_key example.com.crt;
location / {
root /some/where;
index index.html;
auth_gss on;
auth_gss_realm EXAMPLE.COM;
auth_gss_keytab /etc/krb5.keytab;
auth_gss_service_name HTTP;
}
}
The SPN will be built as follows:
$auth_gss_service_name / $server_name @ $auth_gss_realm
In the above example, it'll be `HTTP/foo.example.com@EXAMPLE.COM`. You can
specify a fully-qualified SPN in the `auth_gss_service_name` configuration
option, in this case the `server_name` won't be added automatically.
|