Prerequisites:
You can configure many kinds of applications to rely on FreeIPA's
centralised authentication, including web applications. In this
unit you will configure the Apache web server to use Kerberos
authentication to authenticate users, PAM to enforce HBAC rules, and
mod_lookup_identity
to populate the request environment with
user attributes.
All activities in this unit take place on client
unless
otherwise specified. Access the host via ``vagrant ssh client``
to ensure you have sudo
access.
The demo web application is trivial. It just reads its request
environment and responds in plain text with a list of variables
starting with the string "REMOTE_"
. It should be up and running
already:
[client]$ curl http://client.ipademo.local NOT LOGGED IN REMOTE_* REQUEST VARIABLES: REMOTE_ADDR: 192.168.33.20 REMOTE_PORT: 34356
Create a service representing the web application on
client.ipademo.local
. A service principal name has the service
type as its first part, separated from the host name by a slash,
e.g. HTTP/www.example.com
. The host part must be a host
enrolled in FreeIPA.
You must be getting the hang of FreeIPA by now, so I'll leave the rest of this step up to you. (It's OK to ask for help!)
The service needs access to its Kerberos key in order to
authenticate users. Retrieve the key from the FreeIPA server and
store it in a keytab file (you will need a TGT for admin
):
[client]$ ipa-getkeytab -p HTTP/client.ipademo.local -k app.keytab Keytab successfully retrieved and stored in: app.keytab
We also have to move the file, change its ownership and apply the
proper SELinux labels to the keytab file so that the Apache process
which runs under the confined apache
user may read it:
[client]$ sudo mv app.keytab /etc/httpd [client]$ sudo chown apache:apache /etc/httpd/app.keytab [client]$ sudo restorecon /etc/httpd/app.keytab
In this section we will use mod_auth_gssapi to enable Kerberos Negotiate / SPNEGO authentication for a web application.
The Apache configuration for the demo application lives in the file
/etc/httpd/conf.d/app.conf
. Update the configuration (use
sudo vi
or sudo nano
) to enable Kerberos authentication:
<VirtualHost *:80> ServerName client.ipademo.local WSGIScriptAlias / /usr/share/httpd/app.py <Location /> AuthType GSSAPI AuthName "Kerberos Login" GssapiCredStore keytab:/etc/httpd/app.keytab Require valid-user </Location> <Directory /usr/share/httpd> <Files "app.py"> Require all granted </Files> </Directory> </VirtualHost>
When the configuration is in place, restart Apache:
[client]$ sudo systemctl restart httpd
To test that Kerberos Negotiate authentication is working, kinit
and make a request using curl
:
[client]$ kinit bob Password for [email protected]: [client]$ curl -u : --negotiate http://client.ipademo.local/ LOGGED IN AS: [email protected] REMOTE_* REQUEST VARIABLES: REMOTE_ADDR: 192.168.33.20 REMOTE_USER: [email protected] REMOTE_PORT: 42499
The REMOTE_USER
variable in the request environment indicates
that there is an authenticated user, and identifies that user.
Applications need to know more than just the username of a logged-in user. They want to know the user's name, to send mail to their email address and perhaps to know their group memberships or other attributes. In this section, we will use mod_lookup_identity to populate the HTTP request environment with variables providing information about the authenticated user.
mod_lookup_identity
retrieves user attributes from SSSD (via D-Bus).
Edit /etc/sssd/sssd.conf
; enable the SSSD ifp
InfoPipe
responder, permit the apache
user to query it, and configure the
attributes that you want to expose. Add the following configuration to
sssd.conf
:
[domain/ipademo.local] ... ldap_user_extra_attrs = mail, givenname, sn [sssd] services = nss, sudo, pam, ssh, ifp ... [ifp] allowed_uids = apache, root user_attributes = +mail, +givenname, +sn
Restart SSSD:
[client]$ sudo systemctl restart sssd
If you had not added an email address to your users when you created them, you will need to empty the SSSD cache:
[client]$ sudo sss_cache -E
You can test the SSSD InfoPipe directly via the dbus-send
utility:
[client]$ sudo dbus-send --print-reply --system \ --dest=org.freedesktop.sssd.infopipe /org/freedesktop/sssd/infopipe \ org.freedesktop.sssd.infopipe.GetUserAttr string:alice array:string:mail method return time=1528050430.867333 sender=:1.147 -> destination=:1.150 serial=5 reply_serial=2 array [ dict entry( string "mail" variant array [ string "[email protected]" ] ) ]
Now update the Apache configuration to populate the request
environment. The LookupUserXXX
directives define the mapping of
user attributes to request environment variables. Multi-valued
attributes can be expanded into multiple variables, as in the
LookupUserGroupsIter
directive. Do not forget the
LoadModule
directive at the top!
LoadModule lookup_identity_module modules/mod_lookup_identity.so <VirtualHost *:80> ServerName client.ipademo.local WSGIScriptAlias / /usr/share/httpd/app.py <Location /> AuthType GSSAPI AuthName "Kerberos Login" GssapiCredStore keytab:/etc/httpd/app.keytab Require valid-user LookupUserAttr mail REMOTE_USER_MAIL LookupUserAttr givenname REMOTE_USER_FIRSTNAME LookupUserAttr sn REMOTE_USER_LASTNAME LookupUserGroupsIter REMOTE_USER_GROUP </Location> ... </VirtualHost>
Default SELinux policy prevents Apache from communicating with SSSD
over D-Bus. Set httpd_dbus_sssd
to 1
:
[client]$ sudo setsebool -P httpd_dbus_sssd 1
Restart Apache:
[client]$ sudo systemctl restart httpd
Now make another request to the application and observe that user
information that was injected into the request environment by
mod_lookup_identity
is reflected in the response:
[client]$ curl -u : --negotiate http://client.ipademo.local/ LOGGED IN AS: [email protected] REMOTE_* REQUEST VARIABLES: REMOTE_USER_GROUP_N: 2 REMOTE_ADDR: 192.168.33.20 REMOTE_USER_FIRSTNAME: Alice REMOTE_USER_LASTNAME: Able REMOTE_USER: [email protected] REMOTE_USER_GROUP_2: ipausers REMOTE_USER_GROUP_1: sysadmin REMOTE_PORT: 42586 REMOTE_USER_EMAIL: [email protected]
The final task for this unit is to configure Apache to use FreeIPA's HBAC rules for access control. We will use mod_authnz_pam in conjunction with SSSD's PAM responder to achieve this.
First add an HBAC service named app
for the web application.
You can do this as admin
via the Web UI or CLI. Hint: the
hbacsvc
plugin provides this functionality.
Next, add an HBAC rule allowing members of the sysadmin
user
group access to app
(on any host):
[client]$ ipa hbacrule-add --hostcat=all sysadmin_app ------------------------------ Added HBAC rule "sysadmin_app" ------------------------------ Rule name: sysadmin_app Host category: all Enabled: TRUE [client]$ ipa hbacrule-add-user sysadmin_app --group sysadmin Rule name: sysadmin_app Host category: all Enabled: TRUE User Groups: sysadmin ------------------------- Number of members added 1 ------------------------- [client]$ ipa hbacrule-add-service sysadmin_app --hbacsvcs app Rule name: sysadmin_app Host category: all Enabled: TRUE User Groups: sysadmin Services: app ------------------------- Number of members added 1 -------------------------
Next, define the PAM service on client
. The name must match the
hbacsvc
name (in our case: app
), and the name is indicated
by the name of the file that configures the PAM stack. Create
/etc/pam.d/app
with the following contents:
account required pam_sss.so
Finally, update the Apache configuration. Find the line:
Require valid-user
Replace with:
Require pam-account app
Also add the LoadModule
directive to the top of the file:
LoadModule authnz_pam_module modules/mod_authnz_pam.so
Once again, we must set a special SELinux boolean to allow
mod_authnz_pam
to work:
[client]$ sudo setsebool -P allow_httpd_mod_auth_pam 1
Restart Apache and try and perform the same curl
request again
as alice
. Everything should work as before because alice
is
a member of the sysadmin
group. What happens when you are
authenticated as bob
instead?
This unit is now concluded. Now that you have mastered web app authentication, you'll want to configure TLS for your site. Proceed to Unit 6: Service certificates.