-
Notifications
You must be signed in to change notification settings - Fork 118
Add Windows/AD and UNIX commands and configuration to generate and use Keytabs with nginx #91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
vjt
wants to merge
4
commits into
stnoonan:main
Choose a base branch
from
ifad:master
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,19 +5,26 @@ This module implements adds [SPNEGO](http://tools.ietf.org/html/rfc4178) | |
support to nginx(http://nginx.org). It currently supports only Kerberos | ||
authentication via [GSSAPI](http://en.wikipedia.org/wiki/GSSAPI) | ||
|
||
Purpose of this fork | ||
-------------------- | ||
|
||
This fork only contains a README change from the original source | ||
http://github.com/stnoonan/spnego-http-auth-nginx-module that | ||
explains how to set up NGINX and Active Directory Kerberos authentication | ||
with multiple host names using the same service account. | ||
|
||
Prerequisites | ||
------------- | ||
|
||
Authentication has been tested with (at least) the following: | ||
|
||
* Nginx 1.2 through 1.7 | ||
* Nginx 1.2 through 1.15 | ||
* Internet Explorer 8 and above | ||
* Firefox 10 and above | ||
* Chrome 20 and above | ||
* Curl 7.x (GSS-Negotiate), 7.x (SPNEGO/fbopenssl) | ||
|
||
The underlying kerberos library used for these tests was MIT KRB5 v1.8. | ||
The underlying kerberos library used for these tests was MIT KRB5 v1.12. | ||
|
||
|
||
Installation | ||
|
@@ -65,7 +72,7 @@ application in order to set this header/nginx variable. The easiest way to disa | |
this behavior is to add the following configuration to your location config. | ||
|
||
proxy_set_header Authorization ""; | ||
|
||
A future version of the module may make this behavior an option, but this should | ||
be a sufficient workaround for now. | ||
|
||
|
@@ -158,8 +165,191 @@ Note that the module does not support [NTLMSSP](http://en.wikipedia.org/wiki/NTL | |
in Negotiate. NTLM, both v1 and v2, is an exploitable protocol and should be avoided | ||
where possible. | ||
|
||
Ubuntu 12.04 LTS packages for the latest version of Nginx compiled with the SPNEGO module | ||
are [available in this PPA](https://launchpad.net/~bcandrea/+archive/nginx-stable). | ||
|
||
|
||
Crash course to Windows KDC Configuration | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Split this out into a separate file and link it from the readme? Otherwise, lgtm. |
||
----------------------------------------- | ||
|
||
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. | ||
|
||
Help | ||
---- | ||
|
||
If you're unable to figure things out, please feel free to open an | ||
If you're unable to figure things out, please feel free to open an | ||
issue on Github and I'll do my best to help you. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete these lines :-).