NSS_Impersonation#

Using mod_nss’s NSSVerifyClient require + LookupUserByCertificate + GssapiImpersonate#

TL;DR: mod_nss’s NSSVerifyClient require + LookupUserByCertificate On + GssapiImpersonate On work for generic Apache setup but it is fragile and updates are likely needed to mod_lookup_identity and mod_nss.

This was an email summary, that’s why it’s written in an Ich form.

See also setup of this feature for FreeIPA WebUI.


Setup and test steps#

I have used RHEL 7.2, IPA-enrolled to RHEL 7.2 IPA. I’ve installed

  • mod_nss-1.0.11-6.el7.x86_64

  • mod_lookup_identity-0.9.3-1.el7.x86_64

  • sssd-dbus-1.13.0-40.el7.x86_64

and built mod_auth_gssapi from master (3e0f4e980b4bea2f4f347fc39ea3deddf95fe71e) with make -j && make install.

I’ve configured SSSD:

--- /etc/sssd/sssd.conf.orig    2016-06-16 04:55:01.056705019 -0400
+++ /etc/sssd/sssd.conf 2016-06-16 07:26:58.078165651 -0400
@@ -12,7 +12,7 @@
 ipa_server = _srv_, ipa.example.com
 dns_discovery_domain = example.com
 [sssd]
-services = nss, sudo, pam, ssh
+services = nss, sudo, pam, ssh, ifp
 config_file_version = 2

 domains = example.com

and run

setsebool -P httpd_dbus_sssd on
systemctl restart sssd

I have created HTTP/ service for the machine and got its keytab:

echo Secret123 | kinit admin
ipa service-add HTTP/$(hostname)
IPA_SERVER=$(awk '/^server =/ {print $3}' /etc/ipa/default.conf)
ipa-getkeytab -s $IPA_SERVER -k /etc/http.keytab -p HTTP/$(hostname)
chown apache /etc/http.keytab
chmod 600 /etc/http.keytab

On the IPA server, I’ve run

[root@ipa ~]# kadmin.local
Authenticating as principal admin/admin@EXAMPLE.COM with password.
kadmin.local:  modprinc +ok_to_auth_as_delegate HTTP/client.example.com
Principal "HTTP/client.example.com@EXAMPLE.COM" modified.
kadmin.local:  quit

I have created directory for the delegated credentials:

mkdir /var/run/httpd/gssapi_deleg
chown apache /var/run/httpd/gssapi_deleg

I have created user and associated client certificate (the test certificate alpha from mod_nss’s default /etc/httpd/alias) with it:

ipa user-add --first Robert --last Chase --random bob
ipa user-add-cert --certificate="$( certutil -L -d /etc/httpd/alias -a -n alpha | grep -v '.---' )" bob

I had to change bob’s password or I was getting CLIENT KEY EXPIRED later during gss_acquire_cred_impersonate_name:

`` kpasswd bob``

I have created test content:

# cat > /var/www/cgi-bin/set.cgi <<EOF
#!/bin/bash
echo Content-Type: text/plain
echo Pragma: no-cache
echo
set
EOF

chmod a+x /var/www/cgi-bin/set.cgi

Started Apache and tested I can talk to it via HTTPS:

`` SSL_DIR=/etc/httpd/alias curl -v -Lsi \ ```https://$(hostname):8443/cgi-bin/set.cgi <https://$(hostname):8443/cgi-bin/set.cgi>`__

I’ve configured the modules:

--- /etc/httpd/conf.d/nss.conf.orig     2015-09-22 16:51:00.000000000 -0400
+++ /etc/httpd/conf.d/nss.conf  2016-06-16 07:37:00.591724042 -0400
@@ -70,11 +70,13 @@
 #
 # Only renegotiate if the peer's hello bears the TLS renegotiation_info
 # extension. Default off.
-NSSRenegotiation off
+# NSSRenegotiation off
+NSSRenegotiation on

 # Peer must send Signaling Cipher Suite Value (SCSV) or
 # Renegotiation Info (RI) extension in ALL handshakes.  Default: off
-NSSRequireSafeNegotiation off
+# NSSRequireSafeNegotiation off
+NSSRequireSafeNegotiation on

 ##
 ## SSL Virtual Host Context
@@ -146,6 +148,16 @@
 #   Client certificate verification type.  Types are none, optional and
 #   require.
 #NSSVerifyClient none
+<Location /cgi-bin/set.cgi>
+NSSVerifyClient require
+NSSUserName SSL_CLIENT_CERT
+LookupUserByCertificate On
+
+GssapiImpersonate On
+GssapiDelegCcacheDir /var/run/httpd/gssapi_deleg
+GssapiCredStore keytab:/etc/http.keytab
+GssapiCredStore client_keytab:/etc/http.keytab
+</Location>

 #
 #   Online Certificate Status Protocol (OCSP).

uncommented LoadModule in

`` /etc/httpd/conf.modules.d/55-lookup_identity.conf``

and run

echo LoadModule auth_gssapi_module modules/mod_auth_gssapi.so > /etc/httpd/conf.modules.d/09-gssapi.conf
systemctl restart httpd

I’ve now run

`` SSL_DIR=/etc/httpd/alias curl -Lsi –cert alpha \ ```https://$(hostname):8443/cgi-bin/set.cgi <https://$(hostname):8443/cgi-bin/set.cgi>`__

and in the log I saw

==> /var/log/httpd/error_log <==
[Thu Jun 16 08:22:28.070370 2016] [:notice] [pid 18961] lookup_user_by_certificate found [bob]

==> /var/log/httpd/access_log <==
2620:52:0:1322:221:5eff:fe20:2f4e - -----BEGIN CERTIFICATE-----\nMIICeDCCAeGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJVUzEU\nMBIGA1UEChMLZXhhbXBsZS5jb20xGjAYBgNVBAMTE
UNlcnRpZmljYXRlIFNoYWNr\nMB4XDTE2MDYxNjA4NTM0MVoXDTIwMDYxNjA4NTM0MVowgaAxCzAJBgNVBAYTAlVT\nMRQwEgYDVQQKEwtleGFtcGxlLmNvbTEPMA0GA1UECxMGUGVvcGxlMRUwEwYKCZIm\niZPyLGQBARMFYWxwaGExFDA
SBgNVBAMTC0ZyYW5rIEFscGhhMT0wOwYJKoZIhvcN\nAQkBFi5hbHBoYUBxZS1ibGFkZS0xMC5pZG1xZS5sYWIuZW5nLmJvcy5yZWRoYXQu\nY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7XmqZ98Ohbom0YHr8yr5M\nvMeuE
ju+uVmv2vNEjAzrK3bdKcvqVHcx9sGJz376X6PrJxOthFiItxKpEWxshadK\nDwxrz0JPiDyZQW5FPYIuFx/vH8hnPE5LetTw7rf1ukUU4CpfnonLuH7LBwGmpUIl\neRV4ATUb0GYIF/P8gdtOZwIDAQABoyIwIDARBglghkgBhvhCAQEEB
AMCB4AwCwYD\nVR0PBAQDAgWgMA0GCSqGSIb3DQEBCwUAA4GBAGVMJU24Cjz9CPBmiW61l4B+ufI7\nLvyxCQirRq4rkus0fmkYFHd3+zB40dUcnM/o1Vv5dV3uCxPOjiZz72Ur/bVG3Igw\nI02zZc86+jV9mO5FSfu10myoUNExnsR3uKY
WZUW/5rl4GRMtFa8Gruk4cFa0+DJx\nL/dRR/x2uOqDY0Rb\n-----END CERTIFICATE-----\n [16/Jun/2016:08:22:28 -0400] "GET /cgi-bin/set.cgi HTTP/1.1" 200 4196

and /var/run/httpd/gssapi_deleg/bob@EXAMPLE.COM got created.

Issues#

mod_lookup_identity#

The correct functionality depends on the order in which mod_nss and mod_lookup_identity are loaded. By default, on RHEL 7.2, mod_nss uses

`` /etc/httpd/conf.modules.d/10-nss.conf``

and mod_lookup_identity uses

`` /etc/httpd/conf.modules.d/55-lookup_identity.conf``

(55-lookup_identity.conf has the LoadModule commented out), so that order works. But it would be good to add mod_nss to

`` \ ```https://github.com/adelton/mod_lookup_identity/blob/master/mod_lookup_identity.c#L749 <adelton/mod_lookup_identity>`__

to force mod_lookup_identity to be run after mod_nss.

New release mod_lookup_identity-0.9.7 was done to address this issue.

mod_nss#

Second issue is the fact that as shown by the access_log above, the r->user and REMOTE_USER are set back to the SSL_CLIENT_CERT value in the fixup phase, even if we’ve set it to bob and mod_auth_gssapi found bob there. It’s because the r->user is set both at

`` \ ```https://git.fedorahosted.org/cgit/mod_nss.git/tree/nss_engine_kernel.c#n627 <https://git.fedorahosted.org/cgit/mod_nss.git/tree/nss_engine_kernel.c#n627>`__

where we find it, but also in

`` \ ```https://git.fedorahosted.org/cgit/mod_nss.git/tree/nss_engine_kernel.c#n962 <https://git.fedorahosted.org/cgit/mod_nss.git/tree/nss_engine_kernel.c#n962>`__

That second operation should likely be only run when

`` (dc->nOptions & SSL_OPT_FAKEBASICAUTH)``

When I patch mod_nss that way, the curl will show

==> /var/log/httpd/error_log <==
[Thu Jun 16 08:40:41.175368 2016] [:notice] [pid 22993] lookup_user_by_certificate found [bob]

==> /var/log/httpd/access_log <==
2620:52:0:1322:221:5eff:fe20:2f4e - bob@EXAMPLE.TEST [16/Jun/2016:08:40:41 -0400] "GET /cgi-bin/set.cgi HTTP/1.1" 200 3310

which likely is exactly what we want.

I have filed https://bugzilla.redhat.com/show_bug.cgi?id=1347298 for this.