mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-01-11 08:41:55 -06:00
1519 lines
49 KiB
ReStructuredText
1519 lines
49 KiB
ReStructuredText
..
|
|
Copyright 2015, 2016 Red Hat, Inc.
|
|
|
|
This work is licensed under the Creative Commons Attribution 4.0
|
|
International License. To view a copy of this license, visit
|
|
http://creativecommons.org/licenses/by/4.0/.
|
|
|
|
|
|
Introduction
|
|
============
|
|
|
|
FreeIPA_ is a centralised identity management system. In this
|
|
workshop you will learn how to deploy FreeIPA servers and enrol
|
|
client machines, define and manage user and service identities, set
|
|
up access policies, configure network services to take advantage of
|
|
FreeIPA's authentication and authorisation facilities and issue
|
|
X.509 certificates for services.
|
|
|
|
.. _FreeIPA: http://www.freeipa.org/page/Main_Page
|
|
|
|
|
|
Curriculum overview
|
|
-------------------
|
|
|
|
- `Unit 1: Installing the FreeIPA server`_
|
|
- `Unit 2: Enrolling client machines`_
|
|
- `Unit 3: User management and Kerberos authentication`_
|
|
- `Unit 4: Host-based access control (HBAC)`_
|
|
- `Unit 5: Web application authentication and authorisation`_
|
|
- `Unit 6: Certificate management`_
|
|
- `Unit 7: Replica installation`_
|
|
|
|
|
|
Editing files on VMs
|
|
--------------------
|
|
|
|
Parts of the workshop involve editing files on virtual
|
|
machines. The ``vi`` and GNU ``nano`` editors are available on the
|
|
VMs. If you are not familiar with ``vi`` or you are unsure of what to use, you
|
|
should choose ``nano``.
|
|
|
|
|
|
Example commands
|
|
----------------
|
|
|
|
This guide contains many examples of commands. Some of the commands
|
|
should be executed on your host, others on a particular guest VM.
|
|
For clarity, commands are annotated with the host on which they are
|
|
meant to be executed, as in these examples::
|
|
|
|
$ echo "Run it on virtualisation host (no annotation)"
|
|
|
|
[server]$ echo "Run it on FreeIPA server"
|
|
|
|
[client]$ echo "Run it on IPA-enrolled client"
|
|
|
|
...
|
|
|
|
|
|
Preparation
|
|
===========
|
|
|
|
Some preparation is needed prior to the workshop. The workshop is
|
|
designed to be carried out in a Vagrant_ environment that configures
|
|
three virtual machines with all software network configuration ready
|
|
for the workshop.
|
|
|
|
several VMs. **The goal of the preparation** is to be able to
|
|
successfully ``vagrant up`` the VMs as the first step of the
|
|
workshop.
|
|
|
|
.. _Vagrant: https://www.vagrantup.com/
|
|
|
|
|
|
Requirements
|
|
------------
|
|
|
|
For the FreeIPA workshop you will need to:
|
|
|
|
- Install **Vagrant** and **VirtualBox 4.3** (VirtualBox 5 is not
|
|
supported by Vagrant). (On Fedora, you can use **libvirt**
|
|
instead of VirtualBox).
|
|
|
|
- Use Git to clone the repository containing the ``Vagrantfile``
|
|
|
|
- Fetch the Vagrant *box* for the workshop
|
|
|
|
- Add entries for the guest VMs to your hosts file (so you can
|
|
access them by their hostname)
|
|
|
|
Please set up these items **prior to the workshop**. More detailed
|
|
instructions follow.
|
|
|
|
|
|
Install Vagrant and VirtualBox
|
|
------------------------------
|
|
|
|
Fedora
|
|
^^^^^^
|
|
|
|
If you intend to use the ``libvirt`` provider (recommended), install
|
|
``vagrant-libvirt`` and ``vagrant-libvirt-doc``::
|
|
|
|
$ sudo dnf install -y vagrant-libvirt vagrant-libvirt-doc
|
|
|
|
Also ensure you have the latest versions of ``selinux-policy`` and
|
|
``selinux-policy-targeted``.
|
|
|
|
Allow your regular user ID to start and stop Vagrant boxes. A PolicyKit rule
|
|
will be added that allows users in the ``vagrant`` group to control VMs through
|
|
libvirt. The necessary rule is included in the ``vagrant-libvirt-doc``
|
|
package. Run the following commands to add your local user to the vagrant
|
|
group and to copy the necessary rule to the right place::
|
|
|
|
$ usermod -a -G vagrant $USER
|
|
$ cp /usr/share/vagrant/gems/doc/vagrant-libvirt-*/polkit/10-vagrant-libvirt.rules \
|
|
/etc/polkit-1/rules.d
|
|
|
|
On **Fedoda 24** you need to enable ``virtlogd``::
|
|
|
|
$ systemctl enable virtlogd.socket
|
|
$ systemctl start virtlogd.socket
|
|
|
|
Finally restart the services::
|
|
|
|
$ systemctl restart libvirtd
|
|
$ systemctl restart polkit
|
|
|
|
Otherwise, you will use VirtualBox and the ``virtualbox`` provider.
|
|
VirtualBox needs to build kernel modules, and that means that you must
|
|
first install kernel headers and Dynamic Kernel Module Support::
|
|
|
|
$ sudo dnf install -y vagrant kernel-devel dkms
|
|
|
|
Next, install VirtualBox from the official VirtualBox package repository.
|
|
Before using the repo, check that its contents match what appears
|
|
in the transcript below (to make sure it wasn't tampered with)::
|
|
|
|
$ sudo curl -o /etc/yum.repos.d/virtualbox.repo \
|
|
http://download.virtualbox.org/virtualbox/rpm/fedora/virtualbox.repo
|
|
|
|
$ cat /etc/yum.repos.d/virtualbox.repo
|
|
[virtualbox]
|
|
name=Fedora $releasever - $basearch - VirtualBox
|
|
baseurl=http://download.virtualbox.org/virtualbox/rpm/fedora/$releasever/$basearch
|
|
enabled=1
|
|
gpgcheck=1
|
|
repo_gpgcheck=1
|
|
gpgkey=https://www.virtualbox.org/download/oracle_vbox.asc
|
|
|
|
$ sudo dnf install -y VirtualBox-4.3
|
|
|
|
Finally, load the kernel modules::
|
|
|
|
$ sudo modprobe vboxdrv vboxnetadp
|
|
|
|
|
|
Mac OS X
|
|
^^^^^^^^
|
|
|
|
Install Vagrant for Mac OS X from
|
|
https://www.vagrantup.com/downloads.html.
|
|
|
|
Install VirtualBox 4.3 for **OS X hosts** from
|
|
https://www.virtualbox.org/wiki/Download_Old_Builds_4_3.
|
|
|
|
Install Git from https://git-scm.com/download/mac or via your
|
|
preferred package manager.
|
|
|
|
|
|
Debian / Ubuntu
|
|
^^^^^^^^^^^^^^^
|
|
|
|
Install Vagrant and Git::
|
|
|
|
$ sudo apt-get install -y vagrant git
|
|
|
|
**Virtualbox 4.3** may be available from the system package manager,
|
|
depending your your release. Find out which version of VirtualBox is
|
|
available::
|
|
|
|
$ apt list virtualbox
|
|
Listing... done
|
|
virtualbox/trusty-updates,trusty-security 4.3.10-dfsg-1ubuntu5 amd64
|
|
|
|
If version 4.3 is available, install it via ``apt-get``::
|
|
|
|
$ sudo apt-get install -y virtualbox
|
|
|
|
If VirtualBox 4.3 was not available in the official packages for
|
|
your release, follow the instructions at
|
|
https://www.virtualbox.org/wiki/Linux_Downloads to install it.
|
|
|
|
|
|
Windows
|
|
^^^^^^^
|
|
|
|
Install Vagrant via the ``.msi`` available from
|
|
https://www.vagrantup.com/downloads.html.
|
|
|
|
Install VirtualBox 4.3 for **Windows hosts** from
|
|
https://www.virtualbox.org/wiki/Download_Old_Builds_4_3.
|
|
|
|
You will also need to install an SSH client, and Git. Git for
|
|
Windows also comes with an SSH client so just install Git from
|
|
https://git-scm.com/download/win.
|
|
|
|
|
|
Clone this repository
|
|
---------------------
|
|
|
|
This repository contains the ``Vagrantfile`` that is used for the
|
|
workshop, which you will need locally.
|
|
|
|
::
|
|
|
|
$ git clone https://github.com/freeipa/freeipa-workshop.git
|
|
|
|
|
|
Fetch Vagrant box
|
|
-----------------
|
|
|
|
Please fetch the Vagrant box prior to the workshop. It is > 500MB
|
|
so it may not be feasible to download it during the workshop.
|
|
|
|
::
|
|
|
|
$ vagrant box add ftweedal/freeipa-workshop
|
|
|
|
|
|
If you are running an older version of Vagrant that does not know
|
|
about the *Atlas* service where the box is hosted, you can add it
|
|
by URL instead::
|
|
|
|
$ vagrant box add ftweedal/freeipa-workshop \
|
|
https://atlas.hashicorp.com/ftweedal/boxes/freeipa-workshop/versions/0.0.7/providers/virtualbox.box
|
|
|
|
|
|
Add hosts file entries
|
|
----------------------
|
|
|
|
*This step is necessary if you want to access the FreeIPA Web UI in
|
|
the VM from a browser on your host, but otherwise this step is optional. All
|
|
workshop units can be completed using the CLI.*
|
|
|
|
Add the following entries to your hosts file::
|
|
|
|
192.168.33.10 server.ipademo.local
|
|
192.168.33.11 replica.ipademo.local
|
|
192.168.33.20 client.ipademo.local
|
|
|
|
On Unix systems (including Mac OS X), the hosts file is ``/etc/hosts``
|
|
(you need elevated permissions to edit it.)
|
|
|
|
On Windows, edit ``C:\Windows\System32\system\drivers\etc\hosts`` as
|
|
*Administrator*.
|
|
|
|
|
|
Unit 1: Installing the FreeIPA server
|
|
=======================================
|
|
|
|
In this unit you will install a FreeIPA server. All tasks in
|
|
subsequent units require the services and data provided by the
|
|
server.
|
|
|
|
First, in the directory containing the ``Vagrantfile`` (the clone of
|
|
this repository), execute ``vagrant up`` to bring up the Vagrant
|
|
environment. (If you are using the VirtualBox provider on a platform
|
|
where that is not the default, e.g. Fedora, you will also need the
|
|
``--provider virtualbox`` option).
|
|
|
|
::
|
|
|
|
$ vagrant up --provider virtualbox
|
|
|
|
The Vagrant environment contains three hosts:
|
|
|
|
- ``server.ipademo.local``
|
|
- ``replica.ipademo.local``
|
|
- ``client.ipademo.local``
|
|
|
|
From the directory containing the ``Vagrantfile``, SSH into the
|
|
``server`` machine::
|
|
|
|
$ vagrant ssh server
|
|
|
|
|
|
On ``server``, start the FreeIPA server installation program::
|
|
|
|
[server]$ sudo ipa-server-install --no-host-dns --mkhomedir
|
|
|
|
The ``--no-host-dns`` argument is needed because there are no reverse
|
|
DNS records for the Vagrant environment. For production deployment,
|
|
this important sanity check should not be skipped. The ``--mkhomedir``
|
|
flag configure PAM to create missing home directories when users log
|
|
into the host for the first time. FreeIPA supports automount so
|
|
consider using that for production deployments.
|
|
|
|
You will be asked a series of questions. Accept the defaults for most
|
|
of the questions, except as outlined below.
|
|
|
|
Configure FreeIPA's DNS server::
|
|
|
|
Do you want to configure integrated DNS (BIND)? [no]: yes
|
|
|
|
|
|
Accept default values for the server hostname, domain name and realm::
|
|
|
|
Enter the fully qualified domain name of the computer
|
|
on which you're setting up server software. Using the form
|
|
<hostname>.<domainname>
|
|
Example: master.example.com.
|
|
|
|
|
|
Server host name [server.ipademo.local]:
|
|
|
|
Warning: skipping DNS resolution of host server.ipademo.local
|
|
The domain name has been determined based on the host name.
|
|
|
|
Please confirm the domain name [ipademo.local]:
|
|
|
|
The kerberos protocol requires a Realm name to be defined.
|
|
This is typically the domain name converted to uppercase.
|
|
|
|
Please provide a realm name [IPADEMO.LOCAL]:
|
|
|
|
|
|
Enter passwords for *Directory Manager* (used to manage the
|
|
directory server) and *admin* (the main account used for FreeIPA
|
|
administration). Use something simple that you're not going to
|
|
forget during the workshop!
|
|
|
|
::
|
|
|
|
Certain directory server operations require an administrative user.
|
|
This user is referred to as the Directory Manager and has full access
|
|
to the Directory for system management tasks and will be added to the
|
|
instance of directory server created for IPA.
|
|
The password must be at least 8 characters long.
|
|
|
|
Directory Manager password:
|
|
Password (confirm):
|
|
|
|
The IPA server requires an administrative user, named 'admin'.
|
|
This user is a regular system account used for IPA server administration.
|
|
|
|
IPA admin password:
|
|
Password (confirm):
|
|
|
|
|
|
Do not configure a DNS forwarder (you will want to configure a DNS
|
|
forwarder for a real-world deployment but it is not needed for this
|
|
workshop) and accept the defaults for configuring the reverse zone::
|
|
|
|
Checking DNS domain ipademo.local., please wait ...
|
|
Do you want to configure DNS forwarders? [yes]: no
|
|
No DNS forwarders configured
|
|
Do you want to search for missing reverse zones? [yes]:
|
|
|
|
|
|
Next, you will be presented with a summary of the server
|
|
configuration and asked for final confirmation. Give confirmation to begin the
|
|
server installation::
|
|
|
|
The IPA Master Server will be configured with:
|
|
Hostname: server.ipademo.local
|
|
IP address(es): 192.168.33.10
|
|
Domain name: ipademo.local
|
|
Realm name: IPADEMO.LOCAL
|
|
|
|
BIND DNS server will be configured to serve IPA domain with:
|
|
Forwarders: No forwarders
|
|
Forward policy: only
|
|
Reverse zone(s): No reverse zone
|
|
|
|
Continue to configure the system with these values? [no]: yes
|
|
|
|
The installation takes a few minutes; you will see output indicating
|
|
the progress.
|
|
|
|
When it completes, run ``kinit admin`` and enter your *admin*
|
|
password to obtain a Kerberos ticket granting ticket (TGT) for the
|
|
``admin`` user::
|
|
|
|
[server]$ kinit admin
|
|
Password for admin@IPADEMO.LOCAL: <enter password>
|
|
|
|
Run ``klist`` to view your current Kerberos tickets::
|
|
|
|
[server]$ klist
|
|
Ticket cache: KEYRING:persistent:1000:1000
|
|
Default principal: admin@IPADEMO.LOCAL
|
|
|
|
Valid starting Expires Service principal
|
|
10/15/15 01:48:59 10/16/15 01:48:57 krbtgt/IPADEMO.LOCAL@IPADEMO.LOCAL
|
|
|
|
The FreeIPA server is now set up and you are ready to begin
|
|
enrolling client machines, creating users, managing services, and
|
|
more!
|
|
|
|
To prepare for the next unit, exit the ``server`` SSH session (but
|
|
do not shut the VM down).
|
|
|
|
|
|
Unit 2: Enrolling client machines
|
|
===================================
|
|
|
|
In this unit, you will enrol a *host* as a client of your FreeIPA
|
|
domain. This means that *users* in your FreeIPA realm (or Active
|
|
Directory realms for which there is a trust with FreeIPA) can log
|
|
into the client machine (subject to access policies) and that *services*
|
|
on the client can leverage FreeIPA's authentication and
|
|
authorisation services.
|
|
|
|
From the directory that contains the ``Vagrantfile``, SSH into the
|
|
``client`` machine::
|
|
|
|
$ vagrant ssh client
|
|
|
|
|
|
On ``client``, start the FreeIPA client enrolment program::
|
|
|
|
[client]$ sudo ipa-client-install --mkhomedir
|
|
|
|
The FreeIPA server should be detected through DNS autodiscovery.
|
|
(If DNS discovery fails, e.g. due to client machine having incorrect
|
|
``/etc/resolv.conf`` configuration, you would be prompted to
|
|
manually enter the domain and server hostname instead).
|
|
|
|
The autodetected server settings will be displayed; confirm to
|
|
proceed::
|
|
|
|
[client]$ sudo ipa-client-install
|
|
Discovery was successful!
|
|
Client hostname: client.ipademo.local
|
|
Realm: IPADEMO.LOCAL
|
|
DNS Domain: ipademo.local
|
|
IPA Server: server.ipademo.local
|
|
BaseDN: dc=ipademo,dc=local
|
|
|
|
Continue to configure the system with these values? [no]: yes
|
|
|
|
You might see a warning about time synchronisation, which for this
|
|
workshop can be ignored. Next you will be be prompted to enter
|
|
credentials of a user authorised to enrol hosts (``admin``)::
|
|
|
|
User authorized to enroll computers: admin
|
|
Password for admin@IPADEMO.LOCAL:
|
|
|
|
The enrolment now proceeds; no further input is required. You will
|
|
see output detailing the operations being completed. Unlike
|
|
``ipa-server-install``, client enrolment only takes a few seconds.
|
|
|
|
Users in your FreeIPA domain can now log into FreeIPA-enrolled
|
|
hosts, subject to *Host-based access control* (HBAC) rules. Users
|
|
logged onto the host can also acquire Kerberos tickets for accessing
|
|
*services* in your domain.
|
|
|
|
|
|
Unit 3: User management and Kerberos authentication
|
|
=====================================================
|
|
|
|
This unit introduces the ``ipa`` CLI program and the web
|
|
interface. We will perform some simple administrative tasks: adding
|
|
groups and users and managing group membership.
|
|
|
|
Web UI
|
|
------
|
|
|
|
Visit ``https://server.ipademo.local/``. You'll get a TLS
|
|
*untrusted issuer* warning which you can dismiss (by adding a temporary
|
|
exception). Log in as ``admin``.
|
|
|
|
Welcome to the FreeIPA Web UI. Most management activities can be
|
|
performed here, or via the ``ipa`` CLI program. Use the Web UI to
|
|
perform the following actions:
|
|
|
|
1. Add a *User* with the username ``alice``.
|
|
2. Add a *User Group* for system administrators named ``sysadmin``.
|
|
3. Add ``alice`` to the ``sysadmin`` group.
|
|
|
|
|
|
CLI
|
|
---
|
|
|
|
Make sure you have a Kerberos ticket for ``admin`` (reminder:
|
|
``kinit admin``).
|
|
|
|
Most FreeIPA adminstrative actions can be carried out using the
|
|
``ipa`` CLI program. Let's see what commands are available::
|
|
|
|
[server]% ipa help commands
|
|
automember-add Add an automember rule.
|
|
automember-add-condition Add conditions to an automember rule.
|
|
automember-default-group-remove Remove default (fallback) group for all unmatched entries.
|
|
automember-default-group-set Set default (fallback) group for all unmatched entries.
|
|
automember-default-group-show Display information about the default (fallback) automember groups.
|
|
...
|
|
|
|
Whoa! There are nearly 400 commands! We'll be using only a handful
|
|
of these today. Note that command completion is enabled in the
|
|
shell, so you can type a partial command and press ``<TAB>`` a
|
|
couple of times to see what commands are available, e.g. all the
|
|
commands starting with ``cert-``::
|
|
|
|
[server]$ ipa cert-<TAB>
|
|
cert-find cert-request cert-show
|
|
cert-remove-hold cert-revoke cert-status
|
|
|
|
|
|
You'll notice that commands are grouped by *plugin*. You can read a
|
|
general overview of a plugin by running ``ipa help <plugin>``, and
|
|
specific information on a particular command by running ``ipa help
|
|
<command>``.
|
|
|
|
Add a user named ``bob`` from the CLI. See if you can work out how
|
|
to do this using the CLI help commands. (**hint**: the ``user``
|
|
plugin provides the command).
|
|
|
|
|
|
User authentication
|
|
-------------------
|
|
|
|
We have seen how to authenticate as ``admin``. The process is the
|
|
same for regular users - just ``kinit <username>``!
|
|
|
|
Try to authenticate as ``bob``::
|
|
|
|
[server]$ kinit bob
|
|
kinit: Generic preauthentication failure while getting initial credentials
|
|
|
|
If you did *not* encounter this error, congratulations - you must be
|
|
a disciplined reader of documentation! To set an initial password
|
|
when creating a user via the ``ipa user-add`` command you must
|
|
supply the ``--password`` flag (the command will prompt for the
|
|
password).
|
|
|
|
Use the ``ipa passwd`` command to (re)set a user's password::
|
|
|
|
[server]$ ipa passwd bob
|
|
New Password:
|
|
Enter New Password again to verify:
|
|
----------------------------------------
|
|
Changed password for "bob@IPADEMO.LOCAL"
|
|
----------------------------------------
|
|
|
|
Whenever a user has their password reset (including the first time
|
|
it is set), the next ``kinit`` will prompt them to enter a new
|
|
password::
|
|
|
|
[server]$ kinit bob
|
|
Password for bob@IPADEMO.LOCAL:
|
|
Password expired. You must change it now.
|
|
Enter new password:
|
|
Enter it again:
|
|
|
|
|
|
Now ``bob`` has a TGT (run ``klist`` to confirm) which he can use to
|
|
authenticate himself to other hosts and services. Try logging into
|
|
``client.ipademo.local``::
|
|
|
|
[server]$ ssh bob@client.ipademo.local
|
|
Creating home directory for bob.
|
|
[bob@client]$
|
|
|
|
You are now logged into the client as ``bob``. Type ``^D`` or
|
|
``exit`` to log out and return to the ``server`` shell. If you run
|
|
``klist`` again, you will see not only the TGT but a *service ticket*
|
|
that was automatically acquired to log in to
|
|
``client.ipademo.local`` without prompting for a password. Kerberos
|
|
is a true *single sign-on* protocol!
|
|
|
|
::
|
|
|
|
[server]$ klist
|
|
Ticket cache: KEYRING:persistent:1000:krb_ccache_dYtyLyU
|
|
Default principal: bob@IPADEMO.LOCAL
|
|
|
|
Valid starting Expires Service principal
|
|
15/10/15 07:15:11 16/10/15 07:15:02 host/client.ipademo.local@IPADEMO.LOCAL
|
|
15/10/15 07:15:03 16/10/15 07:15:02 krbtgt/IPADEMO.LOCAL@IPADEMO.LOCAL
|
|
|
|
|
|
|
|
Unit 4: Host-based access control (HBAC)
|
|
==========================================
|
|
|
|
FreeIPA's *host-based access control* (HBAC) feature allows you to
|
|
define policies that restrict access to hosts or services based on
|
|
the user attempting to log in and that user's groups, the host that
|
|
they are trying to access (or its *Host Groups*), and (optionally)
|
|
the service being accessed.
|
|
|
|
In this unit, we will define an HBAC policy that restricts
|
|
access to ``client.ipademo.local`` to members of the
|
|
``sysadmin`` user group.
|
|
|
|
|
|
Adding a host group
|
|
-------------------
|
|
|
|
Instead of defining the HBAC rule to directly talk about
|
|
``client.ipademo.local``, create a *Host Group* named ``webservers``
|
|
and add ``client.ipademo.local`` to it. You can do this via the Web
|
|
UI or the ``ipa`` CLI program (don't forget to ``kinit admin``; see
|
|
if you can work out what plugin provides the host group
|
|
functionality).
|
|
|
|
**Hint:** if you use the CLI will need to run two commands - one to
|
|
create the host group, and one to add ``client.ipademo.local`` as a
|
|
member of the host group.
|
|
|
|
|
|
Disabling the ``allow_all`` HBAC rule
|
|
-------------------------------------
|
|
|
|
HBAC rules are managed via the ``hbacrule`` plugin. You can
|
|
complete the following actions via the Web UI as well, but we will
|
|
cover the CLI commands.
|
|
|
|
List the existing HBAC rules::
|
|
|
|
[server]$ ipa hbacrule-find
|
|
-------------------
|
|
1 HBAC rule matched
|
|
-------------------
|
|
Rule name: allow_all
|
|
User category: all
|
|
Host category: all
|
|
Service category: all
|
|
Description: Allow all users to access any host from any host
|
|
Enabled: TRUE
|
|
----------------------------
|
|
Number of entries returned 1
|
|
----------------------------
|
|
|
|
The FreeIPA server is installed with a single default ``allow_all``
|
|
rule. This rule must be disabled for other HBAC rules to take
|
|
effect. Look for a command that can do this, and run it.
|
|
|
|
|
|
Creating HBAC rules
|
|
-------------------
|
|
|
|
HBAC rules are built up incrementally. The rule is created, then
|
|
users or groups, hosts or hostsgroups and HBAC services are added to
|
|
the rule. The following transcript details the process::
|
|
|
|
[server]$ ipa hbacrule-add sysadmin_webservers
|
|
-------------------------------------
|
|
Added HBAC rule "sysadmin_webservers"
|
|
-------------------------------------
|
|
Rule name: sysadmin_webservers
|
|
Enabled: TRUE
|
|
|
|
[server]$ ipa hbacrule-add-host sysadmin_webservers --hostgroup webservers
|
|
Rule name: sysadmin_webservers
|
|
Enabled: TRUE
|
|
Host Groups: webservers
|
|
-------------------------
|
|
Number of members added 1
|
|
-------------------------
|
|
|
|
[server]$ ipa hbacrule-add-user sysadmin_webservers --group sysadmin
|
|
Rule name: sysadmin_webservers
|
|
Enabled: TRUE
|
|
User Groups: sysadmin
|
|
Host Groups: webservers
|
|
-------------------------
|
|
Number of members added 1
|
|
-------------------------
|
|
|
|
[server]$ ipa hbacrule-mod sysadmin_webservers --servicecat=all
|
|
----------------------------------------
|
|
Modified HBAC rule "sysadmin_webservers"
|
|
----------------------------------------
|
|
Rule name: sysadmin_webservers
|
|
Service category: all
|
|
Enabled: TRUE
|
|
User Groups: sysadmin
|
|
Host Groups: webservers
|
|
|
|
The ``--servicecat=all`` option applies this rule for all services on
|
|
matching hosts. It could have been set during the ``hbacrule-add``
|
|
command instead.
|
|
|
|
|
|
Testing HBAC rules
|
|
------------------
|
|
|
|
You can test HBAC rule evaluation using the ``ipa hbactest``
|
|
command::
|
|
|
|
[server]$ ipa hbactest --host client.ipademo.local --service sshd --user bob
|
|
---------------------
|
|
Access granted: False
|
|
---------------------
|
|
Not matched rules: sysadmin_webservers
|
|
|
|
Poor ``bob``. He won't be allowed in because he is not a member of
|
|
the ``sysadmin`` group. What about ``alice``?
|
|
|
|
``kinit`` as ``bob`` and try to log in to the client::
|
|
|
|
[server]$ kinit bob
|
|
Password for bob@IPADEMO.LOCAL:
|
|
[server]$ ssh bob@client.ipademo.local
|
|
packet_write_wait: Connection to UNKNOWN port 0: Broken pipe
|
|
|
|
Then try ``alice``::
|
|
|
|
[server]$ kinit alice
|
|
Password for alice@IPADEMO.LOCAL:
|
|
[server]$ ssh alice@client.ipademo.local
|
|
Creating home directory for alice.
|
|
[alice@client]$
|
|
|
|
|
|
Unit 5: Web application authentication and authorisation
|
|
==========================================================
|
|
|
|
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.
|
|
|
|
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
|
|
----------------
|
|
|
|
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 correspond to an
|
|
existing host in the directory.
|
|
|
|
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!)
|
|
|
|
|
|
Retrieve Kerberos keytab
|
|
------------------------
|
|
|
|
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 -s server.ipademo.local \
|
|
-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
|
|
|
|
|
|
Enable Kerberos authentication
|
|
------------------------------
|
|
|
|
In this section we will use mod_auth_gssapi_ to enable Kerberos
|
|
Negotiate / SPNEGO authentication for a web application.
|
|
|
|
.. _mod_auth_gssapi: https://github.com/modauthgssapi/mod_auth_gssapi
|
|
|
|
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 bob@IPADEMO.LOCAL:
|
|
|
|
[client]$ curl -u : --negotiate http://client.ipademo.local/
|
|
LOGGED IN AS: bob@IPADEMO.LOCAL
|
|
|
|
REMOTE_* REQUEST VARIABLES:
|
|
|
|
REMOTE_ADDR: 192.168.33.20
|
|
REMOTE_USER: bob@IPADEMO.LOCAL
|
|
REMOTE_PORT: 42499
|
|
|
|
The ``REMOTE_USER`` variable in the request environment indicates
|
|
that there is a logged-in user and identifies that user.
|
|
|
|
|
|
Populating request environment with user attributes
|
|
----------------------------------------------------
|
|
|
|
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: http://www.adelton.com/apache/mod_lookup_identity/
|
|
|
|
|
|
``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 sender=:1.117 -> dest=:1.119 reply_serial=2
|
|
array [
|
|
dict entry(
|
|
string "mail"
|
|
variant array [
|
|
string "alice@ipademo.local"
|
|
]
|
|
)
|
|
]
|
|
|
|
|
|
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!
|
|
|
|
::
|
|
|
|
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. Flip ``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: alice@IPADEMO.LOCAL
|
|
|
|
REMOTE_* REQUEST VARIABLES:
|
|
|
|
REMOTE_USER_GECOS: Alice Able
|
|
REMOTE_USER_GROUP_N: 2
|
|
REMOTE_ADDR: 192.168.33.20
|
|
REMOTE_USER_FIRSTNAME: Alice
|
|
REMOTE_USER_LASTNAME: Able
|
|
REMOTE_USER: alice@IPADEMO.LOCAL
|
|
REMOTE_USER_GROUP_2: ipausers
|
|
REMOTE_USER_GROUP_1: sysadmin
|
|
REMOTE_PORT: 42586
|
|
REMOTE_USER_EMAIL: alice@ipademo.local
|
|
|
|
|
|
HBAC for web services
|
|
---------------------
|
|
|
|
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.
|
|
|
|
.. _mod_authnz_pam: http://www.adelton.com/apache/mod_authnz_pam/
|
|
|
|
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?
|
|
|
|
|
|
Unit 6: Certificate management
|
|
================================
|
|
|
|
You probably noticed that the web service was not hosted over HTTPS,
|
|
so there is no TLS-based authentication or confidentiality. In this
|
|
unit, we will issue an X.509 certificate for the web service via
|
|
the *certmonger* program.
|
|
|
|
Certmonger supports multiple CAs including FreeIPA's CA, and can
|
|
generate keys, issue certifiate requests, track certificates, and
|
|
renew tracked certificates when the expiration time approaches.
|
|
Certmonger works with NSS, so we will also use ``mod_nss`` with
|
|
Apache, rather than ``mod_ssl``.
|
|
|
|
Let's start by confirming that the HTTP service does not yet have a
|
|
certificate::
|
|
|
|
[client]$ ipa service-show HTTP/client.ipademo.local
|
|
Principal: HTTP/client.ipademo.local@IPADEMO.LOCAL
|
|
Keytab: True
|
|
Managed by: client.ipademo.local
|
|
|
|
Enable and start certmonger::
|
|
|
|
[client]$ sudo systemctl enable certmonger
|
|
Created symlink from /etc/systemd/system/multi-user.target.wants/certmonger.service to /usr/lib/systemd/system/certmonger.service.
|
|
[client]$ sudo systemctl start certmonger
|
|
|
|
Now let's request a certificate. We will generate keys and store
|
|
certificates in the NSS database at ``/etc/httpd/alias``::
|
|
|
|
[client]$ sudo ipa-getcert request -d /etc/httpd/alias -n app \
|
|
-K HTTP/client.ipademo.local \
|
|
-D client.ipademo.local
|
|
New signing request "20151026222558" added.
|
|
|
|
Let's break down some of those command arguments.
|
|
|
|
``-d <path>``
|
|
Path to NSS database
|
|
``-n <nickname>``
|
|
*Nickname* to use for storing the key and certificate
|
|
``-K <principal>``
|
|
Kerberos service principal; because different kinds of services may
|
|
be accessed at one hostname, this argument is needed to tell
|
|
certmonger which service principal is the subject
|
|
``-D <dnsname>``
|
|
Requests the given domain name to appear in the *Subject
|
|
Alternative Name (SAN)* extension. The hostname will appear in
|
|
the *Common Name (CN)* field but this practice is deprecated, so
|
|
it is important to also include it in the SAN extension.
|
|
|
|
Another important argument is ``-N <subject-name>`` but this
|
|
defaults to the system hostname, which in our case
|
|
(``client.ipademo.local``) is appropriate.
|
|
|
|
Let's check the status of our certificate request using the tracking
|
|
identifier given in the ``ipa-getcert request`` output::
|
|
|
|
[client]$ sudo getcert list -i 20151026222558
|
|
Number of certificates and requests being tracked: 1.
|
|
Request ID '20151026222558':
|
|
status: MONITORING
|
|
stuck: no
|
|
key pair storage: type=NSSDB,location='/etc/httpd/alias',nickname='app',token='NSS Certificate DB'
|
|
certificate: type=NSSDB,location='/etc/httpd/alias',nickname='app',token='NSS Certificate DB'
|
|
CA: IPA
|
|
issuer: CN=Certificate Authority,O=IPADEMO.LOCAL
|
|
subject: CN=client.ipademo.local,O=IPADEMO.LOCAL
|
|
expires: 2017-10-26 22:26:00 UTC
|
|
dns: client.ipademo.local
|
|
principal name: HTTP/client.ipademo.local@IPADEMO.LOCAL
|
|
key usage: digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment
|
|
eku: id-kp-serverAuth,id-kp-clientAuth
|
|
pre-save command:
|
|
post-save command:
|
|
track: yes
|
|
auto-renew: yes
|
|
|
|
Confirm that the certificate was issued and that certmonger is now
|
|
``MONITORING`` the certificate and will ``auto-renew`` it when it is
|
|
close to expiration. Now if you run ``ipa service-show``, you will
|
|
see a number of attributes related to the certificate, including the
|
|
certificate itself. Can you work out how to save the PEM-encoded
|
|
certificate to a file?
|
|
|
|
You can also see that the certificate is present in the NSS
|
|
database, identified by the specified nickname::
|
|
|
|
[client]# sudo certutil -d /etc/httpd/alias -L -n app
|
|
Certificate:
|
|
Data:
|
|
Version: 3 (0x2)
|
|
Serial Number: 11 (0xb)
|
|
Signature Algorithm: PKCS #1 SHA-256 With RSA Encryption
|
|
Issuer: "CN=Certificate Authority,O=IPADEMO.LOCAL"
|
|
Validity:
|
|
Not Before: Mon Oct 26 22:26:00 2015
|
|
Not After : Thu Oct 26 22:26:00 2017
|
|
Subject: "CN=client.ipademo.local,O=IPADEMO.LOCAL"
|
|
...
|
|
Signed Extensions:
|
|
...
|
|
Name: Certificate Subject Alt Name
|
|
DNS name: "client.ipademo.local"
|
|
...
|
|
|
|
|
|
Now we can reconfigure Apache to serve our app over TLS. Update
|
|
``app.conf`` to listen on port 443 and add the NSS directives::
|
|
|
|
...
|
|
|
|
Listen 443
|
|
|
|
<VirtualHost *:443>
|
|
NSSEngine on
|
|
NSSCertificateDatabase /etc/httpd/alias
|
|
NSSNickname app
|
|
NSSCipherSuite +aes_128_sha_256,+aes_256_sha_256,+ecdhe_ecdsa_aes_128_gcm_sha_256,+ecdhe_ecdsa_aes_128_sha,+ecdhe_ecdsa_aes_256_gcm_sha_384,+ecdhe_ecdsa_aes_256_sha,+ecdhe_rsa_aes_128_gcm_sha_256,+ecdhe_rsa_aes_128_sha,+ecdhe_rsa_aes_256_gcm_sha_384,+ecdhe_rsa_aes_256_sha,+rsa_aes_128_gcm_sha_256,+rsa_aes_128_sha,+rsa_aes_256_gcm_sha_384,+rsa_aes_256_sha
|
|
|
|
ServerName client.ipademo.local
|
|
...
|
|
|
|
|
|
Restart Apache and make a request to the app over HTTPS::
|
|
|
|
[client]$ sudo systemctl restart httpd
|
|
[client]$ curl -u : --negotiate https://client.ipademo.local
|
|
LOGGED IN AS: alice@IPADEMO.LOCAL
|
|
|
|
REMOTE_* REQUEST VARIABLES:
|
|
|
|
REMOTE_USER_MAIL: alice@ipademo.local
|
|
REMOTE_USER_GECOS: Alice Able
|
|
REMOTE_USER: alice@IPADEMO.LOCAL
|
|
REMOTE_USER_GROUP_N: 1
|
|
REMOTE_ADDR: 192.168.33.20
|
|
REMOTE_USER_FIRSTNAME: Alice
|
|
REMOTE_USER_LASTNAME: Able
|
|
REMOTE_USER_GROUP_1: ipausers
|
|
REMOTE_PORT: 47894
|
|
|
|
|
|
Unit 7: Replica installation
|
|
==============================
|
|
|
|
FreeIPA is designed to be run in a replicated multi-master
|
|
environment. In this unit, we will deploy a single FreeIPA
|
|
replica. For recommended production topologies, see
|
|
http://www.freeipa.org/page/Deployment_Recommendations#Replicas.
|
|
|
|
If you have disabled the ``allow_all`` HBAC rule, add a new rule
|
|
that will **allow ``admin`` to access the ``sshd`` service on any
|
|
host**.
|
|
|
|
As of FreeIPA 4.3, replica installation is accomplished by
|
|
*promoting* an enrolled client machine to a server.
|
|
|
|
SSH to the ``replica`` VM and enrol it per `Unit 2: Enrolling
|
|
client machines`_.
|
|
|
|
Now promote the client to server. We will set up the replica
|
|
*without* CA or DNS, but in a production deployment there should be
|
|
at least one instance of these services in each datacentre. These
|
|
components can be added later via ``ipa-ca-install(1)`` and
|
|
``ipa-dns-install(1)``.
|
|
|
|
::
|
|
|
|
[replica]$ sudo ipa-replica-install
|
|
Password for admin@IPADEMO.LOCAL:
|
|
|
|
Run connection check to master
|
|
Connection check OK
|
|
Configuring NTP daemon (ntpd)
|
|
[1/4]: stopping ntpd
|
|
[2/4]: writing configuration
|
|
...
|
|
|
|
The rest of the replica installation process is almost identical to
|
|
server installation. One important difference is the initial
|
|
replication of data to the new Directory Server instance::
|
|
|
|
[28/43]: setting up initial replication
|
|
Starting replication, please wait until this has completed.
|
|
Update in progress, 7 seconds elapsed
|
|
Update succeeded
|
|
|
|
After ``ipa-replica-install`` finishes, the replica is operational.
|
|
|
|
|
|
Unit 8: Sudo rule management
|
|
============================
|
|
|
|
Sudo is a program that allows users to run programs as another user
|
|
with different privileges (possibly ``root``). Sudo rules provide
|
|
fine-grained control over who can execute which processes, as which
|
|
users. FreeIPA allows centralised management of Sudo rules. To
|
|
simplify management, Sudo rules can refer to User Groups, Host
|
|
Groups and *Command Groups* as well as individual users, hosts and
|
|
commands.
|
|
|
|
The goal of this unit is to allow ``alice`` (being a ``sysadmin``)
|
|
to run any command on any FreeIPA-enrolled machine, and to allow
|
|
``bob`` (who is merely a web server administrator) to control
|
|
``httpd`` on hosts that are ``webservers``.
|
|
|
|
|
|
Permitting ``alice`` to run all commmands
|
|
-----------------------------------------
|
|
|
|
Let's deal with ``alice`` first. Before we do anything else, log in
|
|
as ``alice`` and attempt to run the ``id`` command as ``root``.
|
|
Observe that the action is denied::
|
|
|
|
[client]$ su -l alice
|
|
Password:
|
|
[alice@client]$ sudo id
|
|
[sudo] password for alice:
|
|
alice is not allowed to run sudo on client. This incident will be reported.
|
|
[alice@client]$ exit
|
|
logout
|
|
|
|
Now define the ``sysadmin_sudo`` rule, which allows members of the
|
|
``sysadmin`` User Group to to run any command on any host::
|
|
|
|
[client]$ ipa sudorule-add sysadmin_sudo \
|
|
--hostcat=all --runasusercat=all --runasgroupcat=all --cmdcat=all
|
|
-------------------------------
|
|
Added Sudo Rule "sysadmin_sudo"
|
|
-------------------------------
|
|
Rule name: sysadmin_sudo
|
|
Enabled: TRUE
|
|
Host category: all
|
|
Command category: all
|
|
RunAs User category: all
|
|
RunAs Group category: all
|
|
|
|
Next add the ``sysadmin`` User Group to the Sudo rule::
|
|
|
|
[client]$ ipa sudorule-add-user sysadmin_sudo --group sysadmin
|
|
Rule name: sysadmin_sudo
|
|
Enabled: TRUE
|
|
Host category: all
|
|
Command category: all
|
|
RunAs User category: all
|
|
RunAs Group category: all
|
|
User Groups: sysadmin
|
|
-------------------------
|
|
Number of members added 1
|
|
-------------------------
|
|
|
|
Now attempt to ``sudo id`` as ``alice`` again::
|
|
|
|
[client]$ su -l alice
|
|
Password:
|
|
[alice@client]$ sudo id
|
|
[sudo] password for alice:
|
|
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
|
|
|
|
This time the action was allowed, and we can see from the output
|
|
that ``alice`` indeed executed the ``id`` command as ``root``.
|
|
|
|
|
|
Permitting ``bob`` to run web administration commands
|
|
-----------------------------------------------------
|
|
|
|
Now let us turn our attention to ``bob``. The goal is to allow
|
|
``bob`` and other web servers administrators to run commands related
|
|
to web server administration (and only such commands). First, let's
|
|
observe that ``bob`` currently cannot restart Apache::
|
|
|
|
[client]$ su -l bob
|
|
Password:
|
|
[bob@client]$ sudo systemctl restart httpd
|
|
[sudo] password for bob:
|
|
Sorry, user bob is not allowed to execute '/bin/systemctl restart httpd' as root on client.ipademo.local.
|
|
|
|
Make a new User Group named ``webadmin`` and add ``bob`` as a
|
|
member. Add an ``hbacrule`` that allows ``bob`` to log into hosts
|
|
that are members of the ``webservers`` Host Group.
|
|
|
|
Now define the ``webadmin_sudo`` rule. Note that we *do not* use
|
|
``--hostcat=all`` or ``cmdcat=all`` this time.
|
|
|
|
::
|
|
|
|
[client]$ ipa sudorule-add webadmin_sudo \
|
|
--runasusercat=all --runasgroupcat=all
|
|
-------------------------------
|
|
Added Sudo Rule "webadmin_sudo"
|
|
-------------------------------
|
|
Rule name: webadmin_sudo
|
|
Enabled: TRUE
|
|
RunAs User category: all
|
|
RunAs Group category: all
|
|
[client]$
|
|
|
|
Add the ``webadmin`` User Group and ``webservers`` Host Group to the rule::
|
|
|
|
[client]$ ipa sudorule-add-user webadmin_sudo --group webadmin
|
|
Rule name: webadmin_sudo
|
|
Enabled: TRUE
|
|
RunAs User category: all
|
|
RunAs Group category: all
|
|
User Groups: webadmin
|
|
-------------------------
|
|
Number of members added 1
|
|
-------------------------
|
|
[client]$ ipa sudorule-add-host webadmin_sudo --hostgroup webservers
|
|
Rule name: webadmin_sudo
|
|
Enabled: TRUE
|
|
RunAs User category: all
|
|
RunAs Group category: all
|
|
User Groups: webadmin
|
|
Host Groups: webservers
|
|
-------------------------
|
|
Number of members added 1
|
|
-------------------------
|
|
|
|
Next, define *Sudo Commands* and a *Sudo Command Group* for
|
|
web server administration::
|
|
|
|
[client]$ ipa sudocmd-add "/usr/bin/systemctl start httpd"
|
|
---------------------------------------------------
|
|
Added Sudo Command "/usr/bin/systemctl start httpd"
|
|
---------------------------------------------------
|
|
Sudo Command: /usr/bin/systemctl start httpd
|
|
[client]$ ipa sudocmd-add "/usr/bin/systemctl restart httpd"
|
|
-----------------------------------------------------
|
|
Added Sudo Command "/usr/bin/systemctl restart httpd"
|
|
-----------------------------------------------------
|
|
Sudo Command: /usr/bin/systemctl restart httpd
|
|
[client]$ ipa sudocmdgroup-add webadmin_cmds
|
|
----------------------------------------
|
|
Added Sudo Command Group "webadmin_cmds"
|
|
----------------------------------------
|
|
Sudo Command Group: webadmin_cmds
|
|
[client]$ ipa sudocmdgroup-add-member webadmin_cmds \
|
|
--sudocmds "/usr/bin/systemctl start httpd" \
|
|
--sudocmds "/usr/bin/systemctl restart httpd"
|
|
Sudo Command Group: webadmin_cmds
|
|
Member Sudo commands: /usr/bin/systemctl start httpd, /usr/bin/systemctl restart httpd
|
|
-------------------------
|
|
Number of members added 2
|
|
-------------------------
|
|
|
|
Finally, add this new command group to the Sudo rule::
|
|
|
|
[client]$ ipa sudorule-add-allow-command webadmin_sudo \
|
|
--sudocmdgroups webadmin_cmds
|
|
Rule name: webadmin_sudo
|
|
Enabled: TRUE
|
|
RunAs User category: all
|
|
RunAs Group category: all
|
|
User Groups: webadmin
|
|
Host Groups: webservers
|
|
Sudo Allow Command Groups: webadmin_cmds
|
|
-------------------------
|
|
Number of members added 1
|
|
-------------------------
|
|
|
|
Now log in again as ``bob`` and observe that we have reached our goal: he can
|
|
restart (or start) Apache, but not run other commands via ``sudo``::
|
|
|
|
[client]$ su -l bob
|
|
Password:
|
|
[bob@client]$ sudo systemctl restart httpd
|
|
[sudo] password for bob:
|
|
[bob@client]$ sudo id
|
|
Sorry, user bob is not allowed to execute '/bin/id' as root on client.ipademo.local.
|
|
|
|
|
|
Unit 9: SELinux User Maps
|
|
=========================
|
|
|
|
SELinux is a *mandatory access controls* mechanism for Linux,
|
|
providing more powerful and flexible access control than traditional
|
|
Unix permissions. Users have an SELinux *context* consisting of a
|
|
*user*, *role* and *type*. The goal of this unit is to cause users
|
|
to be *confined* by an SELinux *role-based access control (RBAC)*
|
|
policy when the log into hosts that are members of the
|
|
``webservers`` Host Group.
|
|
|
|
..
|
|
- users can have different selinux policy on diff hosts
|
|
|
|
**Note:** SELinux contexts are applied during PAM-based login, so
|
|
when testing our changes in this unit ``su -l <user>`` will not
|
|
suffice: it is necessary to log in via SSH. You can do this from
|
|
any of the VMs (even ``client`` itself).
|
|
|
|
Log in as ``alice`` and run ``id -Z`` to see her current SELinux
|
|
context::
|
|
|
|
[alice@client]$ id -Z
|
|
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
|
|
|
|
``alice`` is currently *unconfined*. We want her to be confined to
|
|
the ``staff_u`` context when she logs in, to limit the impact of an
|
|
account compromise.
|
|
|
|
SELinux User Maps can refer to users and hosts directly, or they can
|
|
inherit the users and hosts of an existing HBAC rule. Because
|
|
access control is defined by HBAC, it is a good administration
|
|
practice to link SELinux User Maps to HBAC rules, so that when users
|
|
or hosts are added to the HBAC rule, the correct SELinux context
|
|
will automatically be used.
|
|
|
|
Recall that members of the ``sysadmin`` User Group already have
|
|
access to ``webservers`` via the ``sysadmin_webservers`` rule that
|
|
was created in `Unit 4: Host-based access control (HBAC)`_. Create
|
|
the SELinux User Map::
|
|
|
|
[client]$ ipa selinuxusermap-add sysadmin_staff_t \
|
|
--hbacrule sysadmin_webservers --selinuxuser staff_u:s0-s0:c0.c1023
|
|
-----------------------------------------
|
|
Added SELinux User Map "sysadmin_staff_t"
|
|
-----------------------------------------
|
|
Rule name: sysadmin_staff_t
|
|
SELinux User: staff_u:s0-s0:c0.c1023
|
|
HBAC Rule: sysadmin_webservers
|
|
Enabled: TRUE
|
|
|
|
|
|
Now login in as ``alice`` over SSH and observe that she is confined
|
|
by the ``staff_u`` policy::
|
|
|
|
[server]$ ssh alice@client.ipademo.local
|
|
alice@client.ipademo.local's password:
|
|
Last login: Fri Sep 2 05:47:03 2016
|
|
[alice@client]$ id -Z
|
|
staff_u:staff_r:staff_t:s0-s0:c0.c1023
|
|
|
|
|
|
**Note:** in production use you should ensure that only one HBAC
|
|
rule allows access for a given user/host/SELinux User Map
|
|
combination. Only one SELinux policy will be applied, and if
|
|
multiple policies match, the winning policy may be chosen
|
|
inconsistently.
|
|
|
|
|
|
Unconfined ``sudo``
|
|
-------------------
|
|
|
|
``alice`` is now confined by the ``staff_u`` policy, but being a
|
|
``sysadmin`` she needs to be unconfined when running commands via
|
|
``sudo``. With the current configuration, commands run via ``sudo``
|
|
inherit a user's context, as the following commands demonstrate::
|
|
|
|
[alice@client]$ sudo -s
|
|
[sudo] password for alice:
|
|
sh-4.3# id -Z
|
|
staff_u:staff_r:staff_t:s0-s0:c0.c1023
|
|
sh-4.3# systemctl restart httpd
|
|
Failed to restart httpd.service: Access denied
|
|
See system logs and 'systemctl status httpd.service' for details.
|
|
sh-4.3#
|
|
|
|
Now let's make it so that ``alice`` can do her job. We need to
|
|
update the Sudo rule to change the SELinux context::
|
|
|
|
[alice@client]$ ipa sudorule-add-option sysadmin_sudo --sudooption type=unconfined_t
|
|
-------------------------------------------------------------
|
|
Added option "type=unconfined_t" to Sudo Rule "sysadmin_sudo"
|
|
-------------------------------------------------------------
|
|
Rule name: sysadmin_sudo
|
|
Enabled: TRUE
|
|
Host category: all
|
|
Command category: all
|
|
RunAs User category: all
|
|
RunAs Group category: all
|
|
Sudo Option: type=unconfined_t
|
|
[alice@client]$ ipa sudorule-add-option sysadmin_sudo --sudooption role=unconfined_r
|
|
-------------------------------------------------------------
|
|
Added option "role=unconfined_r" to Sudo Rule "sysadmin_sudo"
|
|
-------------------------------------------------------------
|
|
Rule name: sysadmin_sudo
|
|
Enabled: TRUE
|
|
Host category: all
|
|
Command category: all
|
|
RunAs User category: all
|
|
RunAs Group category: all
|
|
Sudo Option: type=unconfined_t, role=unconfined_r
|
|
|
|
Now when ``alice`` runs ``sudo`` it changes the SELinux context of
|
|
the program being run::
|
|
|
|
[alice@client]$ sudo -s
|
|
sh-4.3# id -Z
|
|
staff_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
|
|
sh-4.3# systemctl restart httpd
|
|
sh-4.3#
|