Import Upstream version 4.12.4

This commit is contained in:
geos_one
2025-08-12 22:28:56 +02:00
parent 03a8170b15
commit 9181ee2487
1629 changed files with 874094 additions and 554378 deletions

View File

@@ -0,0 +1,165 @@
.. _1-server-install:
Copyright 2015-2018 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/.
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 configures 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]:
Do you want to create reverse zone for IP 192.168.33.10 [yes]:
Please specify the reverse zone name [33.168.192.in-addr.arpa.]:
Using reverse zone(s) 33.168.192.in-addr.arpa.
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
The CA will be configured with:
Subject DN: CN=Certificate Authority,O=IPADEMO.LOCAL
Subject base: O=IPADEMO.LOCAL
Chaining: self-signed
BIND DNS server will be configured to serve IPA domain with:
Forwarders: No forwarders
Forward policy: only
Reverse zone(s): 33.168.192.in-addr.arpa.
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). The next essential unit is
:ref:`Unit 2: Enrolling client machines <2-client-install>`.
Alternatively, if you would like to immediately install a replica
server (essential for production deployments), you can take a detour
to :ref:`Unit 7: Replica installation <7-replica-install>`.

View File

@@ -0,0 +1,134 @@
.. _10-ssh-key-management:
Unit 10: SSH user and host key management
=========================================
**Prerequisites:**
- :ref:`Unit 3: User management and Kerberos authentication <3-user-management>`
In this module you will explore how to use FreeIPA as a backend
provider for SSH keys. Instead of distributing ``authorized_keys``
and ``known_hosts`` files, SSH keys are uploaded to their
corresponding user and host entries in FreeIPA.
Using FreeIPA as a backend store for SSH user keys
--------------------------------------------------
OpenSSH can use *public-private key pairs* to authenticate users. A
user wanting to access a host can get her *public key* added to an
``authorized_keys`` file on the target host. When the user attempts
to log in, she presents her public key and the host grants access if
her key is in an ``authorized_keys`` file. There are system-wide
and per-user ``authorized_keys`` files, but if the target systems do
not mount a network-backed home directory (e.g. NFS), then the user
must copy her public key to every system she intends to log in to.
On FreeIPA-enrolled systems, SSSD can be configured to cache and
retrieve user SSH keys so that applications and services only have
to look in one location for user public keys. FreeIPA provides the
centralized repository of keys, which users can manage themselves.
Administrators do not need to worry about distributing, updating or
verifying user SSH keys.
Generate a user keypair on the client system::
[client]$ sudo -i -u alice
[alice@client]$
[alice@client]$ ssh-keygen -C alice@ipademo.local
Generating public/private rsa key pair.
Enter file in which to save the key (/home/alice/.ssh/id_rsa):
Created directory '/home/alice/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/alice/.ssh/id_rsa.
Your public key has been saved in /home/alice/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:KZ1MQCvaGAGZxKaMxmWBexzH98NPBsTsuo1uf/42SB0 alice@ipademo.local
The key's randomart image is:
+---[RSA 2048]----+
| .+=.o*oo |
| oo+=*o* . . |
| + ++o.=o+ . .+E|
| o o..o.oo o o +=|
|. .. ...S + o . .|
| . . .. . * |
| . + . |
| . |
| |
+----[SHA256]-----+
The public key is stored in ``/home/alice/.ssh/id_rsa.pub`` in an
OpenSSH-specific format. ``alice`` can now upload it to her user
entry in FreeIPA::
[alice@client]$ kinit alice
Password for alice@IPADEMO.LOCAL:
[alice@client]$ ipa user-mod alice \
--sshpubkey="$(cat /home/alice/.ssh/id_rsa.pub)"
---------------------
Modified user "alice"
---------------------
User login: alice
First name: Alice
Last name: Able
Home directory: /home/alice
Login shell: /bin/sh
Email address: alice@ipademo.local
UID: 1278000001
GID: 1278000001
SSH public key: ssh-rsa
AAAAB3NzaC1yc2EAAAADAQABAAABAQDH8pLi61DjkEPqNZnfOgGLLZfLdu9EqVL9UrZeXD3M/j3ig+xeDCCO80YjzuND0UZE4CHgA+uGrtoinQMYkt/FRkm/ie8wcinP/8BxSoOeYSHDNG+cG3iSNJrDiHoqPeQ/+nzBS5n6HWy18N5IMNoqC+f9f2VDuHWZCKqPHMLD29MAX6vOgawdHWFcAk416O+EgS43w3ub89+VPz3Egz4z9K+gjpoboFHk94n7n09B+qyzzImVMsz9vMFSr0rcaVRd9Tb0Q6HlUXkU7aH1Vjkl/DJdQalCpPYJXujkRYAZIs1ouU5IBuuq6k54fk1vBmwjv2tK2NkpvfWfhaxQVwdn
alice@ipademo.local
SSH public key fingerprint: C4:62:89:7A:65:F9:82:12:EF:08:96:D1:C9:7D:51:A5 alice@ipademo.local
(ssh-rsa)
Account disabled: False
Password: True
Member of groups: ipausers, sysadmin
Indirect Member of Sudo rule: sysadmin_sudo
Indirect Member of HBAC rule: sysadmin_all
Kerberos keys available: True
During enrolment of the systems, SSSD has been configured to use
FreeIPA as one of its identity domains and OpenSSH has been
configured to use SSSD for managing user keys.
If you have disabled the ``allow_all`` HBAC rule, add a new rule
that will **allow ``alice`` to access the ``sshd`` service on any
host**.
Logging in to the server using SSH public key authentication should
now work::
[alice@client]$ ssh -o GSSAPIAuthentication=no server.ipademo.local
Enter passphrase for key '/home/alice/.ssh/id_rsa':
Last login: Tue Feb 2 15:10:13 2016
[alice@server]$
To verify that the SSH public key was used for authentication, you
can check the ``sshd`` log on the server::
[server]$ sudo journalctl -u sshd -S "5 minutes ago" --no-pager
-- Logs begin at Mon 2018-06-04 19:01:11 UTC, end at Mon 2018-06-11 04:55:19 UTC. --
Jun 11 04:51:52 server.ipademo.local sshd[8570]: Accepted publickey for alice from 192.168.33.20 port 57596 ssh2: RSA SHA256:KZ1MQCvaGAGZxKaMxmWBexzH98NPBsTsuo1uf/42SB0
Using FreeIPA as a backend store for SSH host keys
--------------------------------------------------
OpenSSH uses public keys to authenticate hosts. When a client
attempts to log in over SSH, the target host presents its public
key. The first time the host authenticates, the user may have to
examine the target host's public key and manually authenticate it.
The client then stores the host's public key in a ``known_hosts``
file. On subsequent attempts to log in, the client checks its
``known_hosts`` files. If the presented host key does not match the
stored host key, the OpenSSH client refuses to continue.
Based on the last exercise, try to figure out how to upload SSH host
keys to the FreeIPA server.
**Note:** OpenSSH has already been configured to look up known hosts
on the FreeIPA server, so no manual configuration is required for
this section.

View File

@@ -0,0 +1,453 @@
.. _11-kerberos-ticket-policy:
Unit 11: Kerberos ticket policy
=========================================
**Prerequisites:**
- :ref:`Unit 3: User management and Kerberos authentication <3-user-management>`
In this module you will explore how to manage properties of Kerberos
authentication and authorization in FreeIPA.
**Note:** To complete this module, FreeIPA-4.8.4 or later is needed.
Kerberos ticket policies
------------------------
FreeIPA's primary authentication mechanism is based on Kerberos infrastructure.
Each user has an associated Kerberos principal and potential aliases. Each FreeIPA
service has its own Kerberos service and, optionally, alias names as well. Depending
on who initiates a communication flow, in Kerberos terminology there are client
and a target (server) principals. Any Kerberos principal can be used in both
client and server roles, though typically FreeIPA services are used as targets
and users are used as clients.
A client first authenticates to a Key Distribution Center (KDC) and obtains a
ticket granting ticket (TGT). With the ticket granting ticket in possession, the
client then asks a KDC for a service ticket to the target Kerberos principal.
After the service ticket is issued by the KDC, the client can initiate its
application-specific communication to the target application server.
When a KDC issues a ticket, there are few properties that can be controlled with
the help of a Kerberos policy in FreeIPA. Each ticket has its own life time and
a potential renewal age: a ticket can be renewed before its life time has ended
but until the renewal age expired.
The combination of Kerberos ticket life time and renewal age altogether
comprises a **Kerberos ticket policy**. The policy itself is not stored in a single
place because individual parts of it are applied to different objects and at
different stages of authentication and authorization processes. Instead, it is
split into several parts which are associated with the corresponding Kerberos
principals, whether they are used as clients or as targets.
For users, Kerberos ticket life time and renewal age can be managed with
Kerberos ticket policy commands described in ``ipa help krbtpolicy`` manual.
If no specific policy is associated with a user, a default one is applied. To
manage the default policy the same ``ipa krbtpolicy-*`` commands are used,
without an explicit user name.
Display the default Kerberos ticket policy::
[admin@client]$ kinit admin
Password for admin@IPADEMO.LOCAL:
[admin@client]$ ipa krbtpolicy-show
Max life: 86400
Max renew: 604800
Modify the default policy to 8 hours max life, 1-day max renewal::
[admin@client]$ ipa krbtpolicy-mod --maxlife=28800 --maxrenew=86400
Max life: 28800
Max renew: 86640
Display effective Kerberos ticket policy for user ``admin``::
[admin@client]$ ipa krbtpolicy-show admin
Max life: 28800
Max renew: 86640
Modify per-user policy for user 'admin'::
[admin@client]$ ipa krbtpolicy-mod admin --maxlife=3600
Max life: 3600
Reset per-user policy for user ``admin``::
[admin@client]$ ipa krbtpolicy-reset admin
Max life: 28800
Max renew: 86640
Currently (FreeIPA 4.8.4), FreeIPA does not allow a Kerberos service principal
to have a custom Kerberos ticket policy. As result, only default Kerberos ticket
policy is applicable to service principals.
Kerberos authentication indicators
----------------------------------
A Kerberos client may have different means to prove possession of a client
principal credentials to a KDC. There are several so-called 'pre-authentication
mechanisms' that are used for this purpose. FreeIPA KDC is able to record which
pre-authentication method was used when issuing the ticket granting ticket. The
specific label is called an **authentication indicator**.
Authentication indicators are associated with the following pre-authentication mechanisms:
========================= ========================
Authentication indicator Pre-authentication mechanism
========================= ========================
radius RADIUS
otp FreeIPA two factor authentication (password + OTP)
pkinit PKINIT, smart-card or certificate authentication
hardened Hardened Password (by SPAKE or FAST)
idp External Identity Provider
========================= ========================
**Hardened** authentication indicator is set by FreeIPA KDC when a Kerberos
client has used one of two pre-authentication mechanisms that allow protecting
an exchange between the client and the KDC:
- **FAST** is a Kerberos pre-authentication mechanism defined in
`RFC 6113, section 5.4 <https://tools.ietf.org/htlm/rfc6113#section-5.4>`_.
It is used to securely pass so-called **FAST factors** to the KDC. Such
factors might represent a traditional password-based exchange, or two-factor
authentication, or something else. There are multiple types of FAST armors
supported by FreeIPA.
- **SPAKE** is a new pre-authentication mechanism,
`being standardized <https://tools.ietf.org/html/draft-ietf-kitten-krb-spake-preauth>`_
by the IETF Kitten working group. Its purpose is to increase security of
Kerberos pre-authentication exchanges by making offline brute-force attacks
infeasible and to enable use of multi-factor authentication without relying
on FAST. SPAKE implementation in FreeIPA currently only supports a single
factor authentication.
In the context of authentication indicators, FAST and SPAKE pre-authentication
methods give higher level of protection than an exchange using encrypted
timestamp method, traditional for Kerberos 5.
Each authentication indicator conveys the fact that KDC was able to
pre-authenticate the initial ticket granting ticket exchange using chosen
mechanism. This fact can further be used to differentiate the issued ticket life
time and renewal age.
With FreeIPA 4.8.4 or later, Kerberos ticket policy allows an administrator to
set different life time and renewal age for ticket granting tickets obtained
with different pre-authentication methods. Each policy setting may include
authentication indicator to say that the life time or renewal age applies to
TGTs with which include this indicator::
[admin@client]$ ipa krbtpolicy-mod --help
Usage: ipa [global-options] krbtpolicy-mod [USER] [options]
Modify Kerberos ticket policy.
Options:
-h, --help show this help message and exit
--maxlife=INT Maximum ticket life (seconds)
--maxrenew=INT Maximum renewable age (seconds)
--otp-maxlife=INT OTP token maximum ticket life (seconds)
--otp-maxrenew=INT OTP token ticket maximum renewable age (seconds)
--radius-maxlife=INT RADIUS maximum ticket life (seconds)
--radius-maxrenew=INT
RADIUS ticket maximum renewable age (seconds)
--pkinit-maxlife=INT PKINIT maximum ticket life (seconds)
--pkinit-maxrenew=INT
PKINIT ticket maximum renewable age (seconds)
--hardened-maxlife=INT
Hardened ticket maximum ticket life (seconds)
--hardened-maxrenew=INT
Hardened ticket maximum renewable age (seconds)
....
For example, we can allow ``admin`` user to renew its ticket for two days if it
was obtained with ``hardened`` authentication indicator::
[admin@client]$ ipa krbtpolicy-mod admin --hardened-maxrenew=$((2*24*60*60))
Hardened max renew: 172800
[admin@client]$ ipa krbtpolicy-show admin
Max life: 28800
Max renew: 86640
Hardened max renew: 172800
There is no way to see authentication indicators for already issued tickets with
existing Kerberos utilities. However, MIT Kerberos tracing facilities can be
used to see what pre-authentication method was used to obtain a ticket::
[admin@client]$ KRB5_TRACE=/dev/stderr kinit admin
[29708] 1583503381.62516: Getting initial credentials for admin@IPADEMO.LOCAL
[29708] 1583503381.62518: Sending unauthenticated request
[29708] 1583503381.62519: Sending request (176 bytes) to IPADEMO.LOCAL
[29708] 1583503381.62520: Initiating TCP connection to stream AA.BB.CC.DD:88
[29708] 1583503381.62521: Sending TCP request to stream AA.BB.CC.DD:88
[29708] 1583503381.62522: Received answer (515 bytes) from stream AA.BB.CC.DD:88
[29708] 1583503381.62523: Terminating TCP connection to stream AA.BB.CC.DD:88
[29708] 1583503381.62524: Response was from master KDC
[29708] 1583503381.62525: Received error from KDC: -1765328359/Additional pre-authentication required
[29708] 1583503381.62528: Preauthenticating using KDC method data
[29708] 1583503381.62529: Processing preauth types: PA-PK-AS-REQ (16), PA-PK-AS-REP_OLD (15), PA-PK-AS-REQ_OLD (14), PA-FX-FAST (136), PA-ETYPE-INFO2 (19), PA-PKINIT-KX (147), PA-SPAKE (151), PA-ENC-TIMESTAMP (2), PA_AS_FRESHNESS (150), PA-FX-COOKIE (133)
[29708] 1583503381.62530: Selected etype info: etype aes256-cts, salt "SOME-VALUE", params ""
[29708] 1583503381.62531: Received cookie: SOME-VALUE
[29708] 1583503381.62532: PKINIT client has no configured identity; giving up
[29708] 1583503381.62533: Preauth module pkinit (147) (info) returned: 0/Success
[29708] 1583503381.62534: PKINIT client received freshness token from KDC
[29708] 1583503381.62535: Preauth module pkinit (150) (info) returned: 0/Success
[29708] 1583503381.62536: PKINIT client has no configured identity; giving up
[29708] 1583503381.62537: Preauth module pkinit (16) (real) returned: 22/Invalid argument
[29708] 1583503381.62538: PKINIT client ignoring draft 9 offer from RFC 4556 KDC
[29708] 1583503381.62539: Preauth module pkinit (15) (real) returned: -1765328360/Preauthentication failed
[29708] 1583503381.62540: PKINIT client ignoring draft 9 offer from RFC 4556 KDC
[29708] 1583503381.62541: Preauth module pkinit (14) (real) returned: -1765328360/Preauthentication failed
[29708] 1583503381.62542: SPAKE challenge received with group 1, pubkey 327144B7EC68505214E5A3606FD2091A7C47CBB60020D7D94B8C4878456B879E
Password for admin@IPADEMO.LOCAL:
[29708] 1583503386.372820: SPAKE key generated with pubkey F0AD6539C037C28758B692FA38FF8F924D5E52C593E485B3700DBF7FD2856477
[29708] 1583503386.372821: SPAKE algorithm result: B53EC5E8C1A22F36F91FD584915F19B3F06CDF3CE460704E2C900AE83DF53EDC
[29708] 1583503386.372822: SPAKE final transcript hash: AC42F4221481B9C9ED3169568A09BBDA9FAACE46DE13F6DCAFF8261003115A9C
[29708] 1583503386.372823: Sending SPAKE response
[29708] 1583503386.372824: Preauth module spake (151) (real) returned: 0/Success
[29708] 1583503386.372825: Produced preauth for next request: PA-FX-COOKIE (133), PA-SPAKE (151)
[29708] 1583503386.372826: Sending request (435 bytes) to IPADEMO.LOCAL
[29708] 1583503386.372827: Initiating TCP connection to stream AA.BB.CC.DD:88
[29708] 1583503386.372828: Sending TCP request to stream AA.BB.CC.DD:88
[29708] 1583503386.372829: Received answer (1419 bytes) from stream AA.BB.CC.DD:88
[29708] 1583503386.372830: Terminating TCP connection to stream AA.BB.CC.DD:88
[29708] 1583503386.372831: Response was from master KDC
[29708] 1583503386.372832: AS key determined by preauth: aes256-cts/AE1D
[29708] 1583503386.372833: Decrypted AS reply; session key is: aes256-cts/12C3
[29708] 1583503386.372834: FAST negotiation: available
[29708] 1583503386.372835: Initializing KCM:123456 with default princ admin@IPADEMO.LOCAL
[29708] 1583503386.372836: Storing admin@IPADEMO.LOCAL -> krbtgt/IPADEMO.LOCAL@IPADEMO.LOCAL in KCM:123456
[29708] 1583503386.372837: Storing config in KCM:123456 for krbtgt/IPADEMO.LOCAL@IPADEMO.LOCAL: fast_avail: yes
[29708] 1583503386.372838: Storing admin@IPADEMO.LOCAL -> krb5_ccache_conf_data/fast_avail/krbtgt\/IPADEMO.LOCAL\@IPADEMO.LOCAL@X-CACHECONF: in KCM:123456
[29708] 1583503386.372839: Storing config in KCM:123456 for krbtgt/IPADEMO.LOCAL@IPADEMO.LOCAL: pa_type: 151
[29708] 1583503386.372840: Storing admin@IPADEMO.LOCAL -> krb5_ccache_conf_data/pa_type/krbtgt\/IPADEMO.LOCAL\@IPADEMO.LOCAL@X-CACHECONF: in KCM:123456
As can be seen above, pre-authentication type, ``pa_type``, 151 (SPAKE)
was used in for pre-authentication. A look at the credential cache content will
show that the renewal age policy applied corresponds to the ``hardened`` variant::
[admin@client]$ klist -f -d -e
Ticket cache: KCM:123456
Default principal: admin@IPADEMO.LOCAL
Valid starting Expires Service principal
06.03.2020 09.03.06 06.03.2020 17.03.06 krbtgt/IPADEMO.LOCAL@IPADEMO.LOCAL
renew until 07.03.2020 09.03.01, Flags: FRIA
Etype (skey, tkt): aes256-cts-hmac-sha1-96, aes256-cts-hmac-sha1-96 , AD types:
As result, ``admin`` user can now use its ticket up to 8 hours and renew it
until 48 hours since the original ticket was obtained.
Finally, we can reset the default Kerberos ticket policy to the installation
default::
[admin@client]$ ipa krbtpolicy-reset
Max life: 86400
Max renew: 604800
Enforcing authentication indicators
-----------------------------------
Authentication indicators from the ticket granting ticket are copied by the KDC
into service tickets issued with the help of the TGT presented by a Kerberos
client. The indicators can be seen by the applications receiving a communication
encrypted with the service ticket. This allows an application administrator to
permit restricted access to only those clients who used specific
pre-authentication mechanisms to obtain their initial ticket granting ticket.
For example, an application might decide to only allow access to a specialized
resource to people who used smart-card authentication initially, even if the
application itself only supports Kerberos authentication.
At the moment, there is only one known application that implements
authentication indicator-based authorization. Since version 2.6.0, SSSD provides
a PAM module ``pam_sss_gss`` which allows to authenticate users with GSSAPI
(Kerberos ticket) and optionally check authentication indicator that was used to
obtain this ticket. More information can be found in the man page for
``pam_sss_gss` and for ``sssd.conf`` where options starting with ``pam_gssapi_``
prefix are documented. This feature was also backported to SSSD 2.4.2 and 2.5.0.
For example, setting the following in SSSD configuration would allow GSSAPI
authentication to ``sudo`` and ``sudo -i`` only if the Kerberos ticket was
obtained with the use of a smartcard or certificate-based authentcation::
[pam]
pam_gssapi_services = sudo, sudo-i
pam_gssapi_indicators_map = sudo:pkinit, sudo-i:pkinit
The actual enforcement requires use of ``pam_sss_gss`` module in the PAM stack.
Fedora and RHEL distributions provide ``authselect`` tool to handle PAM and NSS
configuration. ``authselect`` was extended to allow use of ``pam_sss_gss`` as
SSSD feature ``with-gssapi``::
[root@client ~]# authselect enable-feature with-gssapi
Make sure that SSSD service is configured and enabled. See SSSD documentation for more information.
- with-gssapi is selected, make sure that GSSAPI authenticaiton is enabled in SSSD
- set pam_gssapi_services to a list of allowed services in /etc/sssd/sssd.conf
- see additional information in pam_sss_gss(8)
Once this change made and SSSD configuration updated to allow PAM services to
use GSSAPI authentication, it will be possible to use Kerberos ticket to
authenticate over a chosen PAM service. A session below demonstrates it::
[root@client ~]# vim /etc/sssd/sssd.conf
[root@client ~]# systemctl restart sssd
[root@client ~]# id testuser
uid=167200003(testuser) gid=167200003(testuser) groups=167200003(testuser)
[root@client ~]# ssh testuser@`hostname`
(testuser@client.ipa.test) password:
Last login: Thu Mar 24 13:54:21 2022 from 192.168.122.141
-sh-5.1$ klist
Ticket cache: KCM:167200003:41683
Default principal: testuser@IPA.TEST
Valid starting Expires Service principal
03/25/22 13:47:55 03/26/22 13:04:47 krbtgt/IPA.TEST@IPA.TEST
-sh-5.1$ sudo -l
Matching Defaults entries for testuser on client:
!visiblepw, always_set_home, match_group_by_gid,
always_query_group_plugin, env_reset, env_keep="COLORS DISPLAY HOSTNAME
HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL QTDIR USERNAME LANG LC_ADDRESS
LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT
LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER
LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET
XAUTHORITY",
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/var/lib/snapd/snap/bin
User testuser may run the following commands on dc:
(ALL) ALL
FreeIPA also provides a check for an authentication indicator at KDC side. This
means that a lack of a specific authentication indicator in TGT can result in
denying an issuance of a requested service ticket. A consequence is that an
application will never see any user with a ticket that does not contain a
specified authentication indicator.
In order to enable the check, add authentication indicator to a service using
``ipa service-mod`` command. We can create a new service and associate
the ``pkinit`` authentication indicator with it::
[admin@client]$ ipa service-add my-service/`hostname`
---------------------------------------------------
Added service "my-service/client.ipademo.local@IPADEMO.LOCAL"
---------------------------------------------------
Principal name: my-service/client.ipademo.local@IPADEMO.LOCAL
Principal alias: my-service/client.ipademo.local@IPADEMO.LOCAL
Managed by: client.ipademo.local
[admin@client]$ ipa-getkeytab -k my-service.keytab -p my-service/`hostname`
Keytab successfully retrieved and stored in: my-service.keytab
A new service, ``my-service/client.ipademo.local``, was created and a set of
random Kerberos keys was associated with it by retrieving a keytab with the
keys. If we want to request a service ticket to the service, the service must
have Kerberos keys.
MIT Kerberos provides a nice tool to request Kerberos service tickets: ``kvno``.
At this point our service has no authentication indicator associated and a
request will succeed::
[admin@client]$ KRB5_TRACE=/dev/stderr kvno -S my-service `hostname`
[29770] 1583505522.60592: Getting credentials admin@IPADEMO.LOCAL -> my-service/client.ipademo.local@IPADEMO.LOCAL using ccache KCM:123456
[29770] 1583505522.60593: Retrieving admin@IPADEMO.LOCAL -> my-service/client.ipademo.local@IPADEMO.LOCAL from KCM:!23456 with result: -1765328243/Matching credential not found
[29770] 1583505522.60594: Retrieving admin@IPADEMO.LOCAL -> krbtgt/IPADEMO.LOCAL@IPADEMO.LOCAL from KCM:!23456 with result: 0/Success
[29770] 1583505522.60595: Starting with TGT for client realm: admin@IPADEMO.LOCAL -> krbtgt/IPADEMO.LOCAL@IPADEMO.LOCAL
[29770] 1583505522.60596: Requesting tickets for my-service/client.ipademo.local@IPADEMO.LOCAL, referrals on
[29770] 1583505522.60597: Generated subkey for TGS request: aes256-cts/8F4D
[29770] 1583505522.60598: etypes requested in TGS request: aes256-cts, aes128-cts, aes256-sha2, aes128-sha2, des3-cbc-sha1, rc4-hmac, camellia128-cts, camellia256-cts
[29770] 1583505522.60600: Encoding request body and padata into FAST request
[29770] 1583505522.60601: Sending request (1655 bytes) to IPADEMO.LOCAL
[29770] 1583505522.60602: Initiating TCP connection to stream AA.BB.CC.DD:88
[29770] 1583505522.60603: Sending TCP request to stream AA.BB.CC.DD:88
[29770] 1583505522.60604: Received answer (1626 bytes) from stream AA.BB.CC.DD:88
[29770] 1583505522.60605: Terminating TCP connection to stream AA.BB.CC.DD:88
[29770] 1583505522.60606: Response was from master KDC
[29770] 1583505522.60607: Decoding FAST response
[29770] 1583505522.60608: FAST reply key: aes256-cts/71CF
[29770] 1583505522.60609: TGS reply is for admin@IPADEMO.LOCAL -> my-service/client.ipademo.local@IPADEMO.LOCAL with session key aes256-cts/8B3E
[29770] 1583505522.60610: TGS request result: 0/Success
[29770] 1583505522.60611: Received creds for desired service my-service/client.ipademo.local@IPADEMO.LOCAL
[29770] 1583505522.60612: Storing admin@IPADEMO.LOCAL -> my-service/client.ipademo.local@IPADEMO.LOCAL in KCM:123456
my-service/client.ipademo.local@IPADEMO.LOCAL: kvno = 1
Let's associate ``pkinit`` authentication indicator with the service::
[admin@client]$ ipa service-mod my-service/`hostname` --auth-ind pkinit
------------------------------------------------------
Modified service "my-service/client.ipademo.local@IPADEMO.LOCAL"
------------------------------------------------------
Principal name: my-service/client.ipademo.local@IPADEMO.LOCAL
Principal alias: my-service/client.ipademo.local@IPADEMO.LOCAL
Authentication Indicators: pkinit
Managed by: client.ipademo.local
Since our credentials cache already contains Kerberos ticket to
``my-service/client.ipademo.local`` from the previous step, ``kvno`` will not
attempt to obtain a new ticket if we just request it again. Instead, we need to
destroy our credentials cache or specify a different one and re-try again::
[admin@client]$ kdestroy
[admin@client]$ kinit admin
Password for admin@IPADEMO.LOCAL:
[admin@client]$ KRB5_TRACE=/dev/stderr kvno -S my-service `hostname`
[29811] 1583506366.899807: Getting credentials admin@IPADEMO.LOCAL -> my-service/client.ipademo.local@IPADEMO.LOCAL using ccache KCM:123456
[29811] 1583506366.899808: Retrieving admin@IPADEMO.LOCAL -> my-service/client.ipademo.local@IPADEMO.LOCAL from KCM:123456 with result: -1765328243/Matching credential not found
[29811] 1583506366.899809: Retrieving admin@IPADEMO.LOCAL -> krbtgt/IPADEMO.LOCAL@IPADEMO.LOCAL from KCM:123456 with result: 0/Success
[29811] 1583506366.899810: Starting with TGT for client realm: admin@IPADEMO.LOCAL -> krbtgt/IPADEMO.LOCAL@IPADEMO.LOCAL
[29811] 1583506366.899811: Requesting tickets for my-service/client.ipademo.local@IPADEMO.LOCAL, referrals on
[29811] 1583506366.899812: Generated subkey for TGS request: aes256-cts/8737
[29811] 1583506366.899813: etypes requested in TGS request: aes256-cts, aes128-cts, aes256-sha2, aes128-sha2, des3-cbc-sha1, rc4-hmac, camellia128-cts, camellia256-cts
[29811] 1583506366.899815: Encoding request body and padata into FAST request
[29811] 1583506366.899816: Sending request (1655 bytes) to IPADEMO.LOCAL
[29811] 1583506366.899817: Initiating TCP connection to stream AA.BB.CC.DD:88
[29811] 1583506366.899818: Sending TCP request to stream AA.BB.CC.DD:88
[29811] 1583506366.899819: Received answer (447 bytes) from stream AA.BB.CC.DD:88
[29811] 1583506366.899820: Terminating TCP connection to stream AA.BB.CC.DD:88
[29811] 1583506366.899821: Response was from master KDC
[29811] 1583506366.899822: Decoding FAST response
[29811] 1583506366.899823: TGS request result: -1765328372/KDC policy rejects request
[29811] 1583506366.899824: Requesting tickets for my-service/client.ipademo.local@IPADEMO.LOCAL, referrals off
[29811] 1583506366.899825: Generated subkey for TGS request: aes256-cts/CC99
[29811] 1583506366.899826: etypes requested in TGS request: aes256-cts, aes128-cts, aes256-sha2, aes128-sha2, des3-cbc-sha1, rc4-hmac, camellia128-cts, camellia256-cts
[29811] 1583506366.899828: Encoding request body and padata into FAST request
[29811] 1583506366.899829: Sending request (1655 bytes) to IPADEMO.LOCAL
[29811] 1583506366.899830: Initiating TCP connection to stream AA.BB.CC.DD:88
[29811] 1583506366.899831: Sending TCP request to stream AA.BB.CC.DD:88
[29811] 1583506366.899832: Received answer (447 bytes) from stream AA.BB.CC.DD:88
[29811] 1583506366.899833: Terminating TCP connection to stream AA.BB.CC.DD:88
[29811] 1583506366.899834: Response was from master KDC
[29811] 1583506366.899835: Decoding FAST response
[29811] 1583506366.899836: TGS request result: -1765328372/KDC policy rejects request
kvno: KDC policy rejects request while getting credentials for my-service/client.ipademo.local@IPADEMO.LOCAL
Finally, we can remove the indicator from ``my-service/client.ipademo.local``::
[admin@client]$ ipa service-mod my-service/`hostname` --auth-ind ''
------------------------------------------------------
Modified service "my-service/client.ipademo.local@IPADEMO.LOCAL"
------------------------------------------------------
Principal name: my-service/client.ipademo.local@IPADEMO.LOCAL
Principal alias: my-service/client.ipademo.local@IPADEMO.LOCAL
Managed by: client.ipademo.local
Authentication indicators and FreeIPA services
----------------------------------------------
Authentication indicators can become an effective way to enforce the use of a
particular pre-authentication method. However, there are caveats. Since
KDC-based enforcement does not allow anyone to obtain a service ticket to a
Kerberos service if they do not possess an authentication indicator in question,
great care has to be used when assigning authentication indicators to internal
FreeIPA services.
Internal FreeIPA services include following Kerberos services on each IPA master
or replica:
- ``HTTP/master.ipademo.local@IPADEMO.LOCAL``
- ``ldap/master.ipademo.local@IPADEMO.LOCAL``
- ``DNS/master.ipademo.local@IPADEMO.LOCAL``
- ``cifs/master.ipademo.local@IPADEMO.LOCAL``
These services are used by automated tools and internally by FreeIPA server
applications themselves. The tools and servers currently cannot perform
interactive authentication steps required by PKINIT and multi-factor
authentication methods.

View File

@@ -0,0 +1,779 @@
.. _12-external-idp-support:
Unit 12: Authentication against external Identity Providers
===========================================================
**Prerequisites:**
- :ref:`Unit 11: Kerberos ticket policy <11-kerberos-ticket-policy>`
In this module you will explore how to manage use external OAuth 2.0 servers to
authorize issuance of Kerberos tickets in FreeIPA.
**Note:** To complete this module, FreeIPA-4.10 or later is needed.
Authentication using external Identity Providers
------------------------------------------------
It is possible to let FreeIPA to delegate authentication and authorization
process of issuing Kerberos tickets to an external entity. FreeIPA has been
supporting RADIUS server proxying for some time. This is exposed over
Kerberos with the help of 'otp' pre-authentication mechanism.
Configuration of the RADIUS proxy authentication is done in two steps: first,
create a RADIUS proxy object in FreeIPA and then associate the user account with
this RADIUS proxy object.
There is no specific requirement as to how RADIUS proxy actually authenticates
the user. It is left outside the FreeIPA scope. The connection to the RADIUS
server becomes critical and is important to protect.
This approach has been extended to allow FreeIPA to contact an OAuth 2.0
Authorization Server instead of RADIUS server. OAuth 2.0 authorization framework
is a modern way to delegate authorization decisions between loosely coupled
parties. It heavily relies on the ability to use HTTP redirects to guide a
user's browser to hop between OAuth 2.0 parties and reach the one that logs user
in and the one that authorizes the access.
Traditionally, it was hard to integrate with OAuth 2.0-enabled systems in POSIX
environment because there is no way to run a browser session from within the
shell or console. Most of OAuth 2.0 identity providers (IdP) heavily rely on
JavaScript and other modern browser features to provide an enhanced user
experience. Emulating the login pages as part of line- and packet-oriented SSH
protocol or console login script is not possible.
OAuth 2.0 Device Authorization Grant is defined in
`RFC 8628 <https://www.rfc-editor.org/rfc/rfc8628>`_ and allows devices that either
lack a browser or input constrained to obtain user authorization to access
protected resources. Instead of performing the authorization flow right at the
device where OAuth authorization grant is requested, a user would perform it at
a separate device that has required rich browsing or input capabilities.
Following figure demonstrates a generic device authorization flow:
.. uml::
participant "End User at Browser"
participant "Device Client"
participant "Authorization Server"
"Device Client" -> "Authorization Server": (A) Client Identifier
"Authorization Server" -> "Device Client": (B) Device Code, User Code & Verification URI
"Device Client" -> "End User at Browser": (C) User Code & Verification URI
"End User at Browser" <-> "Authorization Server": (D) End user reviews authorization request
"Device Client" -> "Authorization Server": (E) Polling with Device Code and Client Identifier
"Authorization Server" -> "Device Client": (F) Access Token (& Optional Refresh Token)
FreeIPA implements a variation of this flow and hides it behind Kerberos KDC. A
special pre-authentication method in MIT Kerberos, ``idp`` is implemented in
SSSD 2.7.0 to facilitate the process outlined above.
Device authorization grant flow decouples the process into several steps:
- the device initiates OAuth 2.0 flow and receives a response from the
Authorization Server that contains a special code and a link to a website user
needs to visit to authorize the device;
- user opens this website somewhere else (mobile, desktop, etc) where a proper
browser is available;
- user is asked to enter the special code;
- if needed, user would be asked login into an OAuth 2.0-based IdP;
- once logged in, IdP would ask user if they authorize this device to access
certain user information;
- once the access request is granted, user comes back to the device's prompt and
confirms it;
- the device at this point would poll OAuth 2.0 Authorization Server on whether
it is allowed to access user information already.
Set up external IdP integration in FreeIPA
------------------------------------------
In order to perform OAuth 2.0 device authorization grant flow against an IdP, an
OAuth 2.0 client has to be registered with the IdP and a capability to allow the
device authorization grant has to be given to it. Not all IdPs support this
feature. Out of the known public ones, following IdPs do support device
authorization grant flow:
* Microsoft Identity Platform, including Azure AD
* Google
* Github
* Keycloak, including Red Hat SSO
* Okta
Many OAuth 2.0 platforms do not support device authorization grant flow and
cannot be directly enabled to operate with FreeIPA. However, one can always
chain (federate) IdPs. It means that, for example, one can deploy Keycloak
locally to allow users to sign in with identities from a different IdP. In that
case the local Keycloak instance would need to be registered as an OAuth 2.0
client with the remote IdP. Local Keycloak instance would then be registered
with IPA.
Setting up IdP references (OAuth 2.0 clients) in IPA can be done with ``ipa
idp-add`` command. The command accepts an option to specify a pre-defined
template for one of the known IdPs. If none of the pre-defined templates is
suitable, individual parameters can also be added::
ipa help idp-add
Usage: ipa [global-options] idp-add NAME [options]
Add a new Identity Provider reference.
Options:
-h, --help show this help message and exit
--auth-uri=STR OAuth 2.0 authorization endpoint
--dev-auth-uri=STR Device authorization endpoint
--token-uri=STR Token endpoint
--userinfo-uri=STR User information endpoint
--keys-uri=STR JWKS endpoint
--issuer-url=STR The Identity Provider OIDC URL
--client-id=STR OAuth 2.0 client identifier
--secret OAuth 2.0 client secret
--scope=STR OAuth 2.0 scope. Multiple scopes separated by space
--idp-user-id=STR Attribute for user identity in OAuth 2.0 userinfo
--setattr=STR Set an attribute to a name/value pair. Format is
attr=value. For multi-valued attributes, the command
replaces the values already present.
--addattr=STR Add an attribute/value pair. Format is attr=value. The
attribute must be part of the schema.
--provider=['google', 'github', 'microsoft', 'okta', 'keycloak']
Choose a pre-defined template to use
--organization=STR Organization ID or Realm name for IdP provider
templates
--base-url=STR Base URL for IdP provider templates
--all Retrieve and print all attributes from the server.
Affects command output.
--raw Print entries as stored on the server. Only affects
output format.
In this part we would use Keycloak IdP to integrate with IPA. Next section shows
how to set up Keycloak on a host enrolled into IPA domain. All shell scripts
below assume execution under ``root`` privileges.
Set up Keycloak IdP on enrolled IPA client
------------------------------------------
In this section, we set up `Keycloak <https://www.keycloak.org>`_ IdP on IPA
client and use it to authenticate IPA users. User database in Keycloak would be
different from the one in IPA, one would need to keep user accounts duplicated
in both places but this would simplify our configuration. We also would use
automation provided by the Keycloak to set up OAuth 2.0 clients and user
accounts.
First, we would download keycloak and unpack it into ``/opt/keycloak-<VERSION>`` as ``root``::
[root@client ~]# dnf -y install java-11-openjdk-headless openssl
#### download keycloak ####
[root@client ~]# export KEYCLOAK_VERSION=18.0.0
[root@client ~]# wget https://github.com/keycloak/keycloak/releases/download/${KEYCLOAK_VERSION}/keycloak-${KEYCLOAK_VERSION}.tar.gz
[root@client ~]# tar zxf keycloak-${KEYCLOAK_VERSION}.tar.gz -C /opt
#### add keycloak system user/group and folder ####
[root@client ~]# groupadd keycloak
[root@client ~]# useradd -r -g keycloak -d /opt/keycloak-${KEYCLOAK_VERSION} keycloak
[root@client ~]# chown -R keycloak:keycloak /opt/keycloak-${KEYCLOAK_VERSION}
[root@client ~]# chmod o+x /opt/keycloak-${KEYCLOAK_VERSION}/bin/
[root@client ~]# restorecon -R /opt/keycloak-${KEYCLOAK_VERSION}
Next step would be to prepare a TLS certificate to be used to protect HTTPS
connections in Keycloak. Since our system is already enrolled into IPA, we can
rely on two features:
* Enrolled IPA client has Kerberos host principal registered with keytab in ``/etc/krb5.keytab``
* Enrolled IPA client host Kerberos principal can manage Kerberos services on the same host
This means we can create ``HTTP/client...`` Kerberos service right from the IPA
client and use ``certmonger`` to issue TLS certificate for it. Certmonger would
automatically renew the certificate. The following sequence of commands
demonstrates how to achieve this, run as root::
########## setup TLS certificate using IPA CA ###############################
[root@client ~]# kinit -k
[root@client ~]# ipa service-add HTTP/$(hostname)
[root@client ~]# ipa-getcert request -K HTTP/$(hostname) -D $(hostname) \
-o keycloak -O keycloak \
-m 0600 -M 0644 \
-k /etc/pki/tls/private/keycloak.key \
-f /etc/pki/tls/certs/keycloak.crt \
-w
[root@client ~]# keytool -import \
-keystore /etc/pki/tls/private/keycloak.store \
-file /etc/ipa/ca.crt \
-alias ipa_ca \
-trustcacerts -storepass Secret123 -noprompt
[root@client ~]# chown keycloak:keycloak /etc/pki/tls/private/keycloak.store
The private key for this certificate is stored in
``/etc/pki/tls/private/keycloak.key``, only accessible to the keycloak user.
Public part of the certificate is stored in ``/etc/pki/tls/certs/keycloak.crt``
and has permissions 0644.
We also import IPA CA's chain to a Java keystore that would be used by Keycloak,
stored at ``/etc/pki/tls/private/keycloak.store``.
Finally, we need to set up ``systemd`` service to run Keycloak::
# Setup keycloak service and config files
[root@client ~]# cat > /etc/sysconfig/keycloak <<EOF
KEYCLOAK_ADMIN=admin
KEYCLOAK_ADMIN_PASSWORD=Secret123
#KC_LOG_LEVEL=debug
KC_HOSTNAME=$(hostname):8443
KC_HTTPS_CERTIFICATE_FILE=/etc/pki/tls/certs/keycloak.crt
KC_HTTPS_CERTIFICATE_KEY_FILE=/etc/pki/tls/private/keycloak.key
KC_HTTPS_TRUST_STORE_FILE=/etc/pki/tls/private/keycloak.store
KC_HTTPS_TRUST_STORE_PASSWORD=Secret123
KC_HTTP_RELATIVE_PATH=/auth
EOF
[root@client ~]# cat > /etc/systemd/system/keycloak.service <<EOF
[Unit]
Description=Keycloak Server
After=network.target
[Service]
Type=idle
EnvironmentFile=/etc/sysconfig/keycloak
User=keycloak
Group=keycloak
ExecStart=/opt/keycloak-${KEYCLOAK_VERSION}/bin/kc.sh start
TimeoutStartSec=600
TimeoutStopSec=600
[Install]
WantedBy=multi-user.target
EOF
[root@client ~]# systemctl daemon-reload
When ``systemd`` service is prepared, Keycloak needs to be initialized::
[root@client ~]# su - keycloak -c '''
export KEYCLOAK_ADMIN=admin
export KEYCLOAK_ADMIN_PASSWORD=Secret123
export KC_HOSTNAME=$(hostname):8443
export KC_HTTPS_CERTIFICATE_FILE=/etc/pki/tls/certs/keycloak.crt
export KC_HTTPS_CERTIFICATE_KEY_FILE=/etc/pki/tls/private/keycloak.key
export KC_HTTPS_TRUST_STORE_FILE=/etc/pki/tls/private/keycloak.store
export KC_HTTPS_TRUST_STORE_PASSWORD=Secret123
export KC_HTTP_RELATIVE_PATH=/auth
/opt/keycloak-${KEYCLOAK_VERSION}/bin/kc.sh --verbose build
'''
and can be started with the standard ``systemctl`` tool::
[root@client ~]# systemctl start keycloak
[root@client ~]# systemctl status --lines 3 --no-pager keycloak
● keycloak.service - Keycloak Server
Loaded: loaded (/etc/systemd/system/keycloak.service; disabled; vendor preset: disabled)
Active: active (running) since Fri 2022-05-06 10:43:06 UTC; 9min ago
Main PID: 27170 (java)
Tasks: 37 (limit: 2318)
Memory: 297.1M
CPU: 25.560s
CGroup: /system.slice/keycloak.service
└─27170 java -Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Djava.net.preferIPv4Stack=true -D…
May 06 10:43:28 client.ipademo.local kc.sh[27170]: 2022-05-06 10:43:28,411 INFO [io.quarkus] (main) Keycloak 18.0.0 on …0.0:8443
May 06 10:43:28 client.ipademo.local kc.sh[27170]: 2022-05-06 10:43:28,412 INFO [io.quarkus] (main) Profile prod activated.
May 06 10:43:28 client.ipademo.local kc.sh[27170]: 2022-05-06 10:43:28,412 INFO [io.quarkus] (main) Installed features: [agroal…
Hint: Some lines were ellipsized, use -l to show in full.
Now we can use it for setting up users and OAuth 2.0 clients. There are two
handy scripts, ``kcadm.sh`` and ``kcreg.sh`` that allow to perform all
operations without visiting the Keycloak Web UI.
With ``kcadm.sh`` we login as admin and create user ``testuser1`` and set a password::
[root@client ~]# /opt/keycloak-18.0.0/bin/kcadm.sh config truststore \
--trustpass Secret123 \
/etc/pki/tls/private/keycloak.store
[root@client ~]# /opt/keycloak-18.0.0/bin/kcadm.sh config credentials \
--server https://$(hostname):8443/auth/ \
--realm master --user admin --password Secret123
Logging into https://client.ipademo.local:8443/auth/ as user admin of realm master
[root@client ~]# /opt/keycloak-18.0.0/bin/kcadm.sh create users \
-r master \
-s username=testuser1 -s enabled=true -s email=testuser1@ipademo.local
Created new user with id 'd319b32a-4cea-43c5-8ef8-19b2b8418d0a'
[root@client ~]# /opt/keycloak-18.0.0/bin/kcadm.sh set-password \
-r master \
--username testuser1 --new-password Secret123
With ``kcreg.sh`` we can create OAuth 2.0 client using a pre-defined template
that will include all parameters we need to allow OAuth 2.0 Device Authorization
Grant flow::
[root@client ~]# /opt/keycloak-18.0.0/bin/kcreg.sh config credentials \
--server https://$(hostname):8443/auth \
--realm master --user admin --password Secret123
[root@client ~]# cat >ipa_client.json <<EOF
{
"enabled" : true,
"redirectUris" : [ "https://ipa-ca.$(hostname -d)/ipa/idp/*" ],
"webOrigins" : [ "https://ipa-ca.$(hostname -d)" ],
"protocol" : "openid-connect",
"publicClient" : true,
"attributes" : {
"oauth2.device.authorization.grant.enabled" : "true",
"oauth2.device.polling.interval": "5"
}
}
EOF
[root@client ~]# /opt/keycloak-18.0.0/bin/kcreg.sh create \
-f ipa_client.json \
-s clientId=ipa_oidc_client
At this point, we have a Keycloak instance with a default ``master`` realm
(organization) and base URL ``https://$(hostname):8443/auth/``. In this realm we
have created ``testuser1`` user with a simple password. We also created OAuth
2.0 client ``ipa_oidc_client`` that is allowed to utilize OAuth 2.0 device
authorization grant flow. This client has no client secret ("public OAuth 2.0
client") associated. Confidential clients can also support device authorization
grant flows.
The client details include information about the redirect URIs. These are required
to specify for public OAuth 2.0 clients, but they aren't used for OAuth 2.0
device authorization grant flow.
Two attributes specified in the OAuth 2.0 client definition for Keycloak:
- ``oauth2.device.authorization.grant.enabled``, set to ``true``, allows OAuth 2.0
device authorization grant processing,
- ``oauth2.device.polling.interval``, set to 5, defines the polling interval for
the client to 5 seconds.
Keycloak 17.0.0 and 18.0.0 releases have a bug that sets default polling
interval to 600 seconds. This makes impossible actual polling process as the
lifespan of the device code is also set to 600 seconds. Keycloak's
[pull request 11893](https://github.com/keycloak/keycloak/pull/11893) needs
to be merged to fix the default settings.
Add IdP reference to IPA
------------------------
The following command adds IdP reference named ``keycloak`` as IPA administrator::
[root@client ~]# kinit admin
..
[root@client ~]# echo -e "Secret123\nSecret123" | \
[root@client ~]# ipa idp-add keycloak --provider keycloak \
--org master \
--base-url https://client.ipademo.local:8443/auth \
--client-id ipa_oidc_client \
--secret
-----------------------------------------
Added Identity Provider reference "keycloak"
-----------------------------------------
Identity Provider reference name: keycloak
Authorization URI: https://client.ipademo.local:8443/auth/realms/master/protocol/openid-connect/auth
Device authorization URI: https://client.ipademo.local:8443/auth/realms/master/protocol/openid-connect/auth/device
Token URI: https://client.ipademo.local:8443/auth/realms/master/protocol/openid-connect/token
User info URI: https://client.ipademo.local:8443/auth/realms/master/protocol/openid-connect/userinfo
Client identifier: ipa_oidc_client
Secret: U2VjcmV0MTIz
Scope: openid email
External IdP user identifier attribute: email
The name for the IdP reference is only used to associate an IdP with users in
IPA. Option ``--provider keycloak`` allows us to fill-in pre-defined template
for Keycloak or Red Hat SSO IdPs. The template expects both Keycloak's realm
(``--org`` option) and a base URL (``--base-url`` option) because Keycloak is
typically deployed as a part of a larger solution. These options may not be
needed for other pre-defined templates like Google or Github.
The `openid` scope is mandatory since
[Keycloak 19.0.2](https://www.keycloak.org/docs/latest/upgrading/index.html#userinfo-endpoint-changes).
Without the `openid` scope, Keycloak refuses userinfo requests with HTTP
response 403: `invalid_scope` `Missing openid scope`.
Associate IdP reference with IPA user
-------------------------------------
While we have added ``testuser1`` to Keycloak instance, this user needs to exist
in IPA to be visible to all enrolled systems. Currently there is no good
solution to integrate between IPA and Keycloak to allow automatically propagate
changes between the two. For the purpose of this workshop we would create users
manually -- we already did that for Keycloak.
Create a user ``testuser1`` in IPA::
[root@client ~]# ipa user-add testuser1 --first Test --last User1
----------------------
Added user "testuser1"
----------------------
User login: testuser1
First name: Test
Last name: User1
Full name: Test User1
Display name: Test User1
Initials: TU
Home directory: /home/testuser1
GECOS: Test User1
Login shell: /bin/sh
Principal name: testuser1@ipademo.local
Principal alias: testuser1@ipademo.local
Email address: testuser1@ipademo.local
UID: 35000003
GID: 35000003
Password: False
Member of groups: ipausers
Kerberos keys available: False
Once user is added, associate it with ``keycloak`` IdP reference we just
created. In order to allow user to login via IdP we need few conditions to be
satisfied:
* IdP reference defined for this IdP in IPA
* IdP reference associated with the user (``--idp`` option to ``ipa user-add``
or ``ipa user-mod``)
* IdP identity for the user is set in the user entry (``--idp-user-id`` option
to ``ipa user-add`` or ``ipa user-mod``)
* finally, user should be allowed to use ``idp`` user authentication method
(``--user-auth-type=idp`` option to ``ipa user-add`` or ``ipa user-mod`` or
``idp`` method set globally)
We can set these options to ``testuser1`` with ``ipa user-mod`` command::
[root@client ~]# ipa user-mod testuser1 --idp keycloak \
--idp-user-id testuser1@ipademo.local \
--user-auth-type=idp
-------------------------
Modified user "testuser1"
-------------------------
User login: testuser1
First name: Test
Last name: User1
Home directory: /home/testuser1
Login shell: /bin/sh
Principal name: testuser1@ipademo.local
Principal alias: testuser1@ipademo.local
Email address: testuser1@ipademo.local
UID: 35000003
GID: 35000003
User authentication types: idp
External IdP configuration: keycloak
External IdP user identifier: testuser1@ipademo.local
Account disabled: False
Password: False
Member of groups: ipausers
Kerberos keys available: False
As can be seen in the output, the account for ``testuser1`` has no password and
no Kerberos keys. It will not be able to authenticate to IPA services without
IdP's help.
Access IPA resources as an IdP user
-----------------------------------
There are two ways to trigger authentication and authorization of ``testuser1``
via our Keycloak IdP instance:
* obtain Kerberos ticket with ``kinit`` tool
* login to the target system via SSH or on the console
In order to obtain initial Kerberos ticket, we need to use ``kinit`` tool. SSSD
2.7.0 provides a special package ``sssd-idp`` which implements Kerberos
pre-authentication method ``idp``. When this package is installed, MIT Kerberos
configuration on the host is updated to automatically allow use of ``idp``
method. However, ``idp`` method requires use of FAST channel in order to provide
a secure connection between the Kerberos client and KDC. This is similar to
``otp`` pre-authentication method FreeIPA already provided for several years.
When IPA is deployed with integrated CA, IPA also provides a way to obtain a
special ticket, called Anonymous PKINIT, to use as a FAST channel factor.
Let's use Anonymous PKINIT to obtain a ticket and store it in the file
``./fast.ccache``. Then we can enable FAST channel with the use of ``-T`` option
for ``kinit`` tool::
[root@client ~]# kinit -n -c ./fast.ccache
[root@client ~]# kinit -T ./fast.ccache testuser1
Authenticate at https://client.ipademo.local:8443/auth/realms/master/device?user_code=YHMQ-XKTL and press ENTER.:
The prompt indicates that ``idp`` method was chosen between the KDC and the
Kerberos client. When KDC received the initial ticket granting ticket request,
IPA database driver (KDB) performed an LDAP lookup of the Kerberos principal and
found out that ``testuser1@IPADEMO.LOCAL`` Kerberos principal has ``idp`` user
authentication type. This, in turn, activated KDC side of the ``idp``
pre-authentication method and led to a request to ``ipa-otpd`` daemon. Finally,
``ipa-otpd`` daemon asked ``oidc_child`` to request a device code authorization
grant from the IdP associated with the ``testuser1@IPADEMO.LOCAL`` principal.
The grant flow resulted in IdP returning a code and a message which was
propagated back to the Kerberos client and displayed by the client side of the
``idp`` pre-authentication method.
At this point we need to visit the page and authorize access to the information.
Once it is done, we complete the process by pressing ``<ENTER>`` key. If
authorization was granted, KDC will issue a Kerberos ticket to and it will be
stored in the credentials cache::
[root@client ~]# klist
Ticket cache: KCM:0:58420
Default principal: testuser1@IPADEMO.LOCAL
Valid starting Expires Service principal
05/09/22 07:48:23 05/10/22 07:03:07 krbtgt/IPADEMO.LOCAL@IPADEMO.LOCAL
Similar process happens when ``pam_sss`` PAM module is used, for example, to
authenticate and authorize access to PAM services. Applications which use PAM to
authenticate and authorize remote access can also benefit from the flow. For
example, SSH daemon can be configured with ``keyboard-interactive`` method which
will allow PAM authentication and authorization. As part of it, PAM messages
will be relayed to the SSH client and SSH client's user input will be sent back
to PAM::
$ ssh testuser1@client.ipademo.local
(testuser1@client.ipademo.local) Authenticate at https://client.ipademo.local:8443/auth/realms/master/device?user_code=XYFL-ROYR and press ENTER.
Last login: Mon May 9 07:48:25 2022 from 10.0.190.227
-sh-5.1$ klist
Ticket cache: KCM:7800003:58420
Default principal: testuser1@IPADEMO.LOCAL
Valid starting Expires Service principal
05/09/22 07:49:38 05/10/22 07:49:24 krbtgt/IPADEMO.LOCAL@IPADEMO.LOCAL
-sh-5.1$
Once initial Kerberos ticket is available, it can be used to perform normal IPA
operations:
- access IPA API with command line tool ``ipa`` or through a Web UI in a browser
- login to other systems with GSSAPI authentication
- access PAM services which use ``pam_sss_gss`` module in their PAM stack definitions
Direct authentication to Web UI with the help of OAuth 2.0 client is not implemented yet.
Troubleshooting IdP integration
-------------------------------
Communication with an IdP server happens on IPA server when KDC calls out to
``ipa-otpd`` daemon and ``ipa-otpd`` daemon launches ``oidc_child`` helper.
Journal logs for ``ipa-otpd`` can be checked with the ``journalctl`` tool.
``ipa-otpd`` processes start on demand and content from all sessions can be
captured with the following command::
[root@master #] journalctl -u 'ipa-otpd@*'
The output would look similar to the following real world example::
May 02 18:51:28 dc.ipa.test systemd[1]: Started ipa-otpd service (PID 1473660/UID 0).
May 02 18:51:28 dc.ipa.test ipa-otpd[1636136]: LDAP: ldapi://%2Frun%2Fslapd-IPA-TEST.socket
May 02 18:51:28 dc.ipa.test ipa-otpd[1636136]: ab@IPA.TEST: request received
May 02 18:51:28 dc.ipa.test ipa-otpd[1636136]: ab@IPA.TEST: user query start
May 02 18:51:28 dc.ipa.test ipa-otpd[1636136]: ab@IPA.TEST: user query end: uid=ab,cn=users,cn=accounts,dc=ipa,dc=test
May 02 18:51:28 dc.ipa.test ipa-otpd[1636136]: ab@IPA.TEST: idp query start: cn=github,cn=idp,dc=ipa,dc=test
May 02 18:51:28 dc.ipa.test ipa-otpd[1636136]: ab@IPA.TEST: idp query end: github
May 02 18:51:28 dc.ipa.test ipa-otpd[1636136]: ab@IPA.TEST: oauth2 start: Get device code
May 02 18:51:29 dc.ipa.test ipa-otpd[1636136]: ab@IPA.TEST: Received: [{"device_code":"f071833afe966eaf596d83646f55250cfdb57418","expires_in":899,"interval":5}
May 02 18:51:29 dc.ipa.test ipa-otpd[1636136]: oauth2 {"verification_uri": "https://github.com/login/device", "user_code": "ECD3-4310"}
May 02 18:51:29 dc.ipa.test ipa-otpd[1636136]: ]
May 02 18:51:29 dc.ipa.test ipa-otpd[1636136]: ab@IPA.TEST: sent: 0 data: 200
May 02 18:51:29 dc.ipa.test ipa-otpd[1636136]: ab@IPA.TEST: ..sent: 200 data: 200
May 02 18:51:29 dc.ipa.test ipa-otpd[1636136]: ab@IPA.TEST: response sent: Access-Challenge
May 02 18:51:29 dc.ipa.test ipa-otpd[1636136]: Socket closed, shutting down...
First part of the output until ``idp query start`` is similar to RADIUS proxy
operation. Unlike RADIUS proxy, in the case of IdP communication, ``ipa-otpd``
first receives an initial state from the ``oidc_child`` process and sends it
back to the KDC within a RADIUS packet with ``Access-Challenge`` message.
The state is then transferred to the Kerberos client and results in a message
that instructs to visit the verification URI and enter the code. Some IdPs also
return a complete message to show, like in the case of Keycloak in our examples
above.
Once the Kerberos client returns, another ``ipa-otpd`` call is performed,
this time to request an access token::
May 02 18:51:50 dc.ipa.test systemd[1]: Started ipa-otpd service (PID 1473661/UID 0).
May 02 18:51:50 dc.ipa.test ipa-otpd[1636149]: LDAP: ldapi://%2Frun%2Fslapd-IPA-TEST.socket
May 02 18:51:50 dc.ipa.test ipa-otpd[1636149]: ab@IPA.TEST: request received
May 02 18:51:50 dc.ipa.test ipa-otpd[1636149]: ab@IPA.TEST: user query start
May 02 18:51:50 dc.ipa.test ipa-otpd[1636149]: ab@IPA.TEST: user query end: uid=ab,cn=users,cn=accounts,dc=ipa,dc=test
May 02 18:51:50 dc.ipa.test ipa-otpd[1636149]: ab@IPA.TEST: idp query start: cn=github,cn=idp,dc=ipa,dc=test
May 02 18:51:50 dc.ipa.test ipa-otpd[1636149]: ab@IPA.TEST: idp query end: github
May 02 18:51:50 dc.ipa.test ipa-otpd[1636149]: ab@IPA.TEST: oauth2 start: Get access token
May 02 18:51:50 dc.ipa.test ipa-otpd[1636149]: ab@IPA.TEST: Received: [abbra]
May 02 18:51:50 dc.ipa.test ipa-otpd[1636149]: ab@IPA.TEST: sent: 0 data: 20
May 02 18:51:50 dc.ipa.test ipa-otpd[1636149]: ab@IPA.TEST: ..sent: 20 data: 20
May 02 18:51:50 dc.ipa.test ipa-otpd[1636149]: ab@IPA.TEST: response sent: Access-Accept
May 02 18:51:50 dc.ipa.test ipa-otpd[1636149]: Socket closed, shutting down...
An access token request followed by the request to obtain a user information.
The resource owner's subject then compared with the value set in the LDAP entry
for this Kerberos principal with the help of ``--idp-user-id`` option. Subject's
field name is chosen through the same option to the IdP reference. If the check
is successful, ``ipa-otpd`` sends a RADIUS packet with ``Access-Accept``
response code.
Communication performed by ``oidc_child`` is not included into the journal logs
by default. If there are issues in accessing IdPs, a special option can be added
to ``/etc/ipa/default.conf`` to increase log level of ``oidc_child`` output. By
default, it is 0 and could be any number between 0 and 10::
[global]
oidc_child_debug_level=10
A value greater than 6 would include debug output from the ``libcurl`` utility::
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: oidc_child started.
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: Running with effective IDs: [0][0].
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: Running with real IDs [0][0].
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: JSON device code: [{"device_code":"f071833afe966eaf596d83646f55250cfdb57418","expires_in":899,"interval":5}].
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: Result does not contain the 'user_code' string.
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: Result does not contain the 'verification_uri' string.
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: Result does not contain the 'verification_url' string.
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: Result does not contain the 'verification_uri_complete' string.
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: Result does not contain the 'message' string.
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: device_code: [f071833afe966eaf596d83646f55250cfdb57418].
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: expires_in: [899].
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: interval: [5].
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: POST data: [grant_type=urn:ietf:params:oauth:grant-type:device_code&client_id=some-client-id&device_code=f071833afe966eaf596d83646f55250cfdb57418].
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Trying 140.82.121.3:443...
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Connected to github.com (140.82.121.3) port 443 (#0)
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * ALPN, offering h2
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * ALPN, offering http/1.1
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * successfully set certificate verify locations:
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * CAfile: /etc/pki/tls/certs/ca-bundle.crt
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * CApath: none
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (OUT), TLS handshake, Client hello (1):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (IN), TLS handshake, Server hello (2):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (IN), TLS handshake, Certificate (11):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (IN), TLS handshake, CERT verify (15):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (IN), TLS handshake, Finished (20):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (OUT), TLS handshake, Finished (20):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * ALPN, server accepted to use h2
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Server certificate:
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * subject: C=US; ST=California; L=San Francisco; O=GitHub, Inc.; CN=github.com
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * start date: Mar 15 00:00:00 2022 GMT
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * expire date: Mar 15 23:59:59 2023 GMT
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * subjectAltName: host "github.com" matched cert's "github.com"
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * issuer: C=US; O=DigiCert Inc; CN=DigiCert TLS Hybrid ECC SHA384 2020 CA1
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * SSL certificate verify ok.
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Using HTTP2, server supports multiplexing
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Connection state changed (HTTP/2 confirmed)
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Using Stream ID: 1 (easy handle 0x562cd1ee96e0)
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: > POST /login/oauth/access_token HTTP/2
Host: github.com
user-agent: SSSD oidc_child/0.0
accept: application/json
content-length: 139
content-type: application/x-www-form-urlencoded
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * We are completely uploaded and fine
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * old SSL session ID is stale, removing
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < HTTP/2 200
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < server: GitHub.com
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < date: Mon, 02 May 2022 18:51:50 GMT
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < content-type: application/json; charset=utf-8
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < vary: X-PJAX, X-PJAX-Container
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < permissions-policy: interest-cohort=()
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < etag: W/"some-e-tag-value"
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < cache-control: max-age=0, private, must-revalidate
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < strict-transport-security: max-age=31536000; includeSubdomains; preload
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-frame-options: deny
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-content-type-options: nosniff
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-xss-protection: 0
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < expect-ct: max-age=2592000, report-uri="https://api.github.com/_private/browser/errors"
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < content-security-policy: default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.git>
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < vary: Accept-Encoding, Accept, X-Requested-With
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-github-request-id: D1EA:541D:48A585:4BF8E5:62702846
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: <
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: {"access_token":"some-access-token","token_type":"bearer","scope":"user"}
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Connection #0 to host github.com left intact
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: Result does not contain the 'id_token' string.
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: access_token: [some-access-token].
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: id_token: [(null)].
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Trying 140.82.121.6:443...
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Connected to api.github.com (140.82.121.6) port 443 (#0)
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * ALPN, offering h2
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * ALPN, offering http/1.1
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * successfully set certificate verify locations:
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * CAfile: /etc/pki/tls/certs/ca-bundle.crt
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * CApath: none
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (OUT), TLS handshake, Client hello (1):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (IN), TLS handshake, Server hello (2):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (IN), TLS handshake, Certificate (11):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (IN), TLS handshake, CERT verify (15):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (IN), TLS handshake, Finished (20):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (OUT), TLS handshake, Finished (20):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * ALPN, server accepted to use h2
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Server certificate:
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * subject: C=US; ST=California; L=San Francisco; O=GitHub, Inc.; CN=*.github.com
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * start date: Mar 16 00:00:00 2022 GMT
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * expire date: Mar 16 23:59:59 2023 GMT
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * subjectAltName: host "api.github.com" matched cert's "*.github.com"
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * issuer: C=US; O=DigiCert Inc; CN=DigiCert TLS Hybrid ECC SHA384 2020 CA1
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * SSL certificate verify ok.
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Using HTTP2, server supports multiplexing
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Connection state changed (HTTP/2 confirmed)
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Server auth using Bearer with user ''
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Using Stream ID: 1 (easy handle 0x562cd1f92ae0)
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: > GET /user HTTP/2
Host: api.github.com
authorization: Bearer some-token-value
user-agent: SSSD oidc_child/0.0
accept: application/json
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * old SSL session ID is stale, removing
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < HTTP/2 200
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < server: GitHub.com
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < date: Mon, 02 May 2022 18:51:50 GMT
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < content-type: application/json; charset=utf-8
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < content-length: 1357
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < cache-control: private, max-age=60, s-maxage=60
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < vary: Accept, Authorization, Cookie, X-GitHub-OTP
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < etag: "some-e-tag-value"
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < last-modified: Mon, 14 Mar 2022 14:05:20 GMT
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-oauth-scopes: user
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-accepted-oauth-scopes:
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-oauth-client-id: some-client-id
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-github-media-type: github.v3
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-ratelimit-limit: 5000
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-ratelimit-remaining: 4996
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-ratelimit-reset: 1651520567
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-ratelimit-used: 4
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-ratelimit-resource: core
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < access-control-expose-headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scop>
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < access-control-allow-origin: *
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < strict-transport-security: max-age=31536000; includeSubdomains; preload
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-frame-options: deny
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-content-type-options: nosniff
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-xss-protection: 0
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < content-security-policy: default-src 'none'
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < vary: Accept-Encoding, Accept, X-Requested-With
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: < x-github-request-id: C5B8:5B48:4C0EB7:4D8AF2:62702846
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: <
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: {"login":"abbra","id":some-id,"node_id":"some-node","avatar_url":"some-avatar-url","gravatar_id":"","url":"some-user-url","html_ur
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: l":"some-url","followers_url":"some-api-url","following_url":"some-following-url","gists_url":"some-gists-url>
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: libcurl: * Connection #0 to host api.github.com left intact
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: userinfo: [{"login": "abbra", "id": some-id, "node_id": "some-node", "avatar_url": "some-avatar-rul", "gravatar_id": "", "url": "some-user-url", ">
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: User identifier: [abbra].
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: User identifier: [abbra].
May 02 18:51:50 dc.ipa.test oidc_child[1636150]: oidc_child finished successful!
Don't forget to remove ``oidc_child_debug_level`` from the
``/etc/ipa/default.conf`` once troubleshooting is done. Information like above
often contains personal details of the user and should probably not stored in
the system journal.

View File

@@ -0,0 +1,62 @@
.. _2-client-install:
Unit 2: Enrolling client machines
===================================
**Prerequisites**:
- :ref:`Unit 1: Installing the FreeIPA server <1-server-install>`
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 --mkhomedir
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
Next, the client's time will be synchronised with the server, then
the installer will prompt you to enter the 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. 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.
You can now move on to
:ref:`Unit 3: User management and Kerberos authentication <3-user-management>`.

View File

@@ -0,0 +1,133 @@
.. _3-user-management:
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 administrative 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 *topic*, or the kind of
object they act upon. Run ``ipa help topics`` to list all topics.
You can read a general overview of a topic by running ``ipa help
<topic>``, and specific information on a particular command by
running ``ipa help <command>``.
Add a user named ``bob`` from the CLI. Use the CLI help to find the
right command (**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: Pre-authentication failed: Invalid argument 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:1000
Default principal: bob@IPADEMO.LOCAL
Valid starting Expires Service principal
06/04/2018 21:45:50 06/05/2018 21:38:24 host/client.ipademo.local@IPADEMO.LOCAL
06/04/2018 21:38:41 06/05/2018 21:38:24 krbtgt/IPADEMO.LOCAL@IPADEMO.LOCAL
Now that you have created some users, it's time to define some
access policies. Proceed to
:ref:`Unit 4: Host-based access control (HBAC) <4-hbac>`.
Alternatively, if you are interested in SSH public key management
for users and hosts, jump ahead to
:ref:`Unit 10: SSH user and host key management <10-ssh-key-management>`.

150
doc/workshop/4-hbac.rst Normal file
View File

@@ -0,0 +1,150 @@
.. _4-hbac:
Unit 4: Host-based access control (HBAC)
==========================================
**Prerequisites:**
- :ref:`Unit 3: User management and Kerberos authentication <3-user-management>`
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
login 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 separate
commands—one to create the host group, then another to add
``client.ipademo.local`` to 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 hostgroups 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 is the result of ``ipa hbactest`` for
``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
Connection closed by UNKNOWN port 65535
The server refused to let ``bob`` in and closed the connection.
Now try ``alice``::
[server]$ kinit alice
Password for alice@IPADEMO.LOCAL:
[server]$ ssh alice@client.ipademo.local
Creating home directory for alice.
[alice@client]$
This was the final mandatory unit in the workshop. From here, there
are several optional units you can choose from. You can proceed
directly to
:ref:`Unit 5: Web application authentication and authorisation <5-web-app-authnz>`.
Otherwise,
:ref:`return to the curriculum overview <curriculum-overview>`
to see all the options.

View File

@@ -0,0 +1,314 @@
.. _5-web-app-authnz:
Unit 5: Web application authentication and authorisation
==========================================================
**Prerequisites**:
- :ref:`Unit 3: User management and Kerberos authentication <3-user-management>`
- :ref:`Unit 4: Host-based access control (HBAC) <4-hbac>`
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
----------------
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!)
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 -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 an authenticated 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: https://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 time=1528050430.867333 sender=:1.147 -> destination=:1.150 serial=5 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 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: alice@IPADEMO.LOCAL
REMOTE_* REQUEST VARIABLES:
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?
This unit is now concluded. Now that you have mastered web app
authentication, you'll want to configure TLS for your site. Proceed
to
:ref:`Unit 6: Service certificates <6-cert-management>`.

View File

@@ -0,0 +1,136 @@
.. _6-cert-management:
Unit 6: Service certificates
================================
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 certificate requests, track certificates, and
renew tracked certificates when the expiration time approaches.
Will also use ``mod_ssl`` with Apache.
Issue the service certificate
-----------------------------
Let's start by confirming that the HTTP service does not yet have a
certificate::
[client]$ ipa service-show HTTP/client.ipademo.local
Principal name: HTTP/client.ipademo.local@IPADEMO.LOCAL
Principal alias: HTTP/client.ipademo.local@IPADEMO.LOCAL
Keytab: True
Managed by: client.ipademo.local
Enable and start Certmonger::
[client]$ sudo systemctl enable --now certmonger
Created symlink /etc/systemd/system/multi-user.target.wants/certmonger.service → /usr/lib/systemd/system/certmonger.service.
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 \
-f /etc/pki/tls/certs/app.crt \
-k /etc/pki/tls/private/app.key \
-K HTTP/client.ipademo.local \
-D client.ipademo.local
New signing request "20180603185400" added.
Let's break down some of those command arguments.
``-k <path>``
Path to private key (Certmonger will generate it)
``-f <path>``
Path to certificate (where it will be saved after being issued)
``-K <principal>``
Kerberos service principal; because different kinds of services
may be accessed at one hostname, this argument tells Certmonger
which service principal is the subject
``-D <dnsname>``
Requests the given domain name to appear in the *Subject
Alternative Name (SAN)* extension; today the *Common Name (CN)*
field is no longer used by browsers so the SAN value is essential
Another important option is ``-N <subject-name>``. It 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 20180603185400
Number of certificates and requests being tracked: 1.
Request ID '20180603185400':
status: MONITORING
stuck: no
key pair storage: type=FILE,location='/etc/pki/tls/private/app.key'
certificate: type=FILE,location='/etc/pki/tls/certs/app.crt'
CA: IPA
issuer: CN=Certificate Authority,O=IPADEMO.LOCAL
subject: CN=client.ipademo.local,O=IPADEMO.LOCAL
expires: 2020-06-03 18:54: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?
Set up TLS for Apache
---------------------
Now we can reconfigure Apache to serve our app over TLS. Update
``app.conf`` to listen on port 443 and add the SSL directives::
...
Listen 443
<VirtualHost *:443>
SSLEngine on
SSLCertificateFile "/etc/pki/tls/certs/app.crt"
SSLCertificateKeyFile "/etc/pki/tls/private/app.key"
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: alice@IPADEMO.LOCAL
REMOTE_USER_GROUP_1: ipausers
REMOTE_USER_GROUP_2: sysadmin
REMOTE_USER_GROUP_N: 2
REMOTE_USER_FIRSTNAME: Alice
REMOTE_USER_LASTNAME: Alice
REMOTE_USER_MAIL: alice@ipademo.local
REMOTE_ADDR: 192.168.33.20
REMOTE_PORT: 51876
You can now proceed to
:ref:`Unit 7: Replica installation <7-replica-install>`
or
:ref:`Unit 8: Sudo rule management <8-sudorule>`.
Otherwise,
:ref:`return to the curriculum overview <curriculum-overview>`
to see all the options.

View File

@@ -0,0 +1,64 @@
.. _7-replica-install:
Unit 7: Replica installation
==============================
**Prerequisites**:
- :ref:`Unit 1: Installing the FreeIPA server <1-server-install>`
FreeIPA is designed to be run in a replicated multi-master
environment. In this unit, we will install a replica of the
existing master. For recommended production topologies, see
https://www.freeipa.org/page/Deployment_Recommendations#Servers.2FReplicas.
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**.
Client installation
-------------------
The first step of replica creation is to enrol the machine that will
become the replica. SSH to the ``replica`` VM and enrol it per
:ref:`Unit 2: Enrolling client machines <2-client-install>`
Replica promotion
-----------------
Now promote the client to server. We will set up the replica
*without* the CA or DNS role. In a production deployment there
should be at least one instance of these services in each data
centre. These roles can be configured later via
``ipa-ca-install(1)`` and ``ipa-dns-install(1)``.
::
[replica]$ sudo ipa-replica-install
Password for admin@IPADEMO.LOCAL:
ipaserver.install.server.replicainstall: ERROR Reverse DNS resolution of address 192.168.33.10 (server.ipademo.local) failed. Clients may not function properly. Please check your DNS setup. (Note that this check queries IPA DNS directly and ignores /etc/hosts.)
Continue? [no]: yes
Run connection check to master
Connection check OK
Configuring directory server (dirsrv). Estimated time: 30 seconds
[1/41]: creating directory server instance
[2/41]: enabling ldapi
...
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/41]: setting up initial replication
Starting replication, please wait until this has completed.
Update in progress, 4 seconds elapsed
Update succeeded
After ``ipa-replica-install`` finishes, the replica is operational.
LDAP changes on any server will be replicated to all other servers.
You can proceed to
:ref:`Unit 8: Sudo rule management <8-sudorule>`
or
:ref:`return to the curriculum overview <curriculum-overview>`
to see all the available topics.

246
doc/workshop/8-sudorule.rst Normal file
View File

@@ -0,0 +1,246 @@
.. _8-sudorule:
Unit 8: Sudo rule management
============================
**Prerequisites**:
- :ref:`Unit 3: User management and Kerberos authentication <3-user-management>`
- :ref:`Unit 4: Host-based access control (HBAC) <4-hbac>`
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.
Older versions of sudo did not require pam access for passwordless
rules (e.g. rules with the NOPASSWD keyword).
sudo-1.8.23 and newer require pam access for all rules.
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``.
As of FreeIPA 4.6.90.pre2, you should enable SSSD's sudo responder by running::
[client]$ sudo authselect enable-feature with-sudo
Restart SSSD::
[client]$ sudo systemctl restart sssd
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``.
**Note:** if the command is prevented there may be some stale cache
entries. Move on with the workshop and try again in 5 minutes.
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, create 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 using the ``sshd``
service.
Once this is done you should be able to login, but not use ``su -l``::
[client]$ su -l bob
Password:
[bob@client]$ su -l bob
Password:
su: Permission denied
Then, let's observe that ``bob`` currently cannot restart Apache::
[bob@client]$ sudo systemctl restart httpd
[sudo] password for bob:
sudo: PAM account management error: Permission denied
Take note that the error is different from the one alice got, which was::
alice is not allowed to run sudo on client. This incident will be reported.
While the HBAC rule alice uses (sysadmin_webservers) was created with
"--servicecat=all", the HBAC rule for bob was created with sshd in mind,
like this::
[server]$ ipa hbacrule-add-service webadmin_webservers --hbacsvcs=sshd
As bob needs to run both ``su -l`` and ``sudo``, add both commands to
the list of allowed services in your access control rule, for instance::
[server]$ ipa hbacrule-add-service webadmin_webservers \
--hbacsvcs=sudo --hbacsvcs=su-l
Now login and logout as bob. Not only bob should now be able to use
``su -l``, but the error message from ``sudo`` should change::
[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.
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
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.
This concludes the unit. Now that you have Sudo rules working,
proceed to :ref:`Unit 9: SELinux User Maps <9-selinux-user-map>`.

View File

@@ -0,0 +1,143 @@
.. _9-selinux-user-map:
Unit 9: SELinux User Maps
=========================
**Prerequisites**:
- :ref:`Unit 3: User management and Kerberos authentication <3-user-management>`
- :ref:`Unit 4: Host-based access control (HBAC) <4-hbac>`
- :ref:`Unit 8: Sudo rule management <8-sudorule>`
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*. In this unit, you will 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. You will also learn how to change a
user's SELinux context when they execute commands via Sudo.
**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).
Confining users
---------------
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 :ref:`Unit 4: Host-based access control (HBAC)<4-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.4# id
uid=0(root) gid=0(root) groups=0(root) context=staff_u:staff_r:staff_t:s0-s0:c0.c1023
sh-4.4# echo "Hello, world!" > /etc/motd
sh: /etc/motd: Permission denied
As you can see, ``alice`` became ``root``, but the SELinux
confinement prevents her from writing ``/etc/motd`` (and many other
things). 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.4# id -Z
staff_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
sh-4.4# echo "Hello, world!" > /etc/motd
sh-4.4# cat /etc/motd
Hello, world!
This concludes the unit. You can now proceed to
:ref:`Unit 10: SSH user and host key management <10-ssh-key-management>`
or
:ref:`return to the curriculum overview <curriculum-overview>`
to see all the available topics.

286
doc/workshop/README.rst Normal file
View File

@@ -0,0 +1,286 @@
.. _workshop:
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:
Curriculum overview
-------------------
Mandatory:
- :ref:`Unit 1: Installing the FreeIPA server <1-server-install>`
- :ref:`Unit 2: Enrolling client machines <2-client-install>`
- :ref:`Unit 3: User management and Kerberos authentication <3-user-management>`
- :ref:`Unit 4: Host-based access control (HBAC) <4-hbac>`
Optional units—choose the topics that are relevant to you:
- :ref:`Unit 5: Web application authentication and authorisation <5-web-app-authnz>`
- :ref:`Unit 6: Service certificates <6-cert-management>`
- :ref:`Unit 7: Replica installation <7-replica-install>`
- :ref:`Unit 8: Sudo rule management <8-sudorule>`
- :ref:`Unit 9: SELinux User Maps <9-selinux-user-map>`
- :ref:`Unit 10: SSH user and host key management <10-ssh-key-management>`
- :ref:`Unit 11: Kerberos ticket policy <11-kerberos-ticket-policy>`
- :ref:`Unit 12: External IdP support <12-external-idp-support>`
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 networked virtual machines (VMs) with all software needed for
the workshop. **The goal of this preparation** is to ``vagrant up``
the VMs. After this preparation is completed you are ready to begin
the workshop.
.. _Vagrant: https://www.vagrantup.com/
Requirements
------------
For the FreeIPA workshop you will need to:
- Install **Vagrant** and **VirtualBox**. (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 using ``libvirt``.
Add your user to ``libvirt`` group so you don't need to enter your administrator
password everytime::
$ sudo gpasswd -a ${USER} libvirt
$ newgrp libvirt
Finally restart the services::
$ systemctl restart libvirtd
More information: https://docs.fedoraproject.org/en-US/quick-docs/getting-started-with-virtualization/
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-6.1
Finally, load the kernel modules (you may need to restart your system for this to work)::
$ sudo modprobe vboxdrv vboxnetadp
Mac OS X
^^^^^^^^
Install Vagrant for Mac OS X from
https://www.vagrantup.com/downloads.html.
Install VirtualBox 6.1 for **OS X hosts** from
https://www.virtualbox.org/wiki/Downloads.
Install Git from https://git-scm.com/download/mac or via your
preferred package manager.
Debian / Ubuntu
^^^^^^^^^^^^^^^
Install Vagrant, Git and VirtualBox::
$ sudo apt-get install -y vagrant git
$ sudo apt-get install -y virtualbox-6.1
If VirtualBox 6.1 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 for **Windows hosts** from
https://www.virtualbox.org/wiki/Downloads.
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.git
$ cd freeipa/doc/workshop
Fetch Vagrant box
-----------------
Please fetch the Vagrant box prior to the workshop. It is > 700MB
so it may not be feasible to download it during the workshop.
::
$ vagrant box add freeipa/freeipa-workshop
Add hosts file entries
----------------------
*This step is optional. All units can be completed using the CLI
only. But if you want to access the FreeIPA Web UI or other web
servers on the VMs from your browser, follow these instructions.*
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*.
Next step
---------
You are ready to begin the workshop. Continue to
:ref:`Unit 1: Installing the FreeIPA server <1-server-install>`.
After the workshop
------------------
Here are some contact details and resources that may help you after
the workshop is over:
- IRC: ``#freeipa`` and ``#sssd`` (Libera.chat)
- ``freeipa-users@lists.fedorahosted.org`` `mailing list
<https://lists.fedoraproject.org/archives/list/freeipa-users@lists.fedorahosted.org/>`_
- `How To guides <https://www.freeipa.org/page/HowTos>`_: large
index of articles about specialised tasks and integrations
- `Troubleshooting guide
<https://www.freeipa.org/page/Troubleshooting>`_: how to debug
common problems; how to report bugs
- `Bug tracker <https://pagure.io/freeipa>`_
- Information about the `FreeIPA public demo
<https://www.freeipa.org/page/Demo>`_ instance
- `Deployment Recommendations
<https://www.freeipa.org/page/Deployment_Recommendations>`_:
things to consider when going into production
- `Documentation index
<https://www.freeipa.org/page/Documentation>`_
- `FreeIPA Planet <http://planet.freeipa.org/>`_: aggregate of
several FreeIPA and identity-management related blogs
- `GitHub organisation <https://github.com/freeipa>`_. In addition
to the `main repository <https://github.com/freeipa/freeipa>`_
there are various tools, CI-related projects and documentation.
- `Development roadmap <https://www.freeipa.org/page/Roadmap>`_

82
doc/workshop/Vagrantfile vendored Normal file
View File

@@ -0,0 +1,82 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
# Replace this with "fedora/34-cloud-base" (or latest) for a fresh box without
# pre-installed freeipa packages, you must also uncomment shell provisioning step
# at the bottom of this file.
# config.vm.box = "fedora/34-cloud-base"
config.vm.box = "freeipa/freeipa-workshop"
config.vm.synced_folder ".", "/vagrant", disabled: true
config.vm.provider :libvirt do |libvirt|
libvirt.qemu_use_session = false
libvirt.memory = 1024
end
config.vm.provider :virtualbox do |virtualbox|
virtualbox.memory = 1536
end
config.vm.define "server" do |server|
server.vm.network "private_network", ip: "192.168.33.10"
server.vm.hostname = "server.ipademo.local"
config.vm.provider "virtualbox" do |v|
v.memory = 1536
end
config.vm.provider "libvirt" do |v|
v.memory = 1536
end
end
config.vm.define "replica" do |replica|
replica.vm.network "private_network", ip: "192.168.33.11"
replica.vm.hostname = "replica.ipademo.local"
replica.vm.provision "shell",
inline: 'echo "PEERDNS=no" >> /etc/sysconfig/network-scripts/ifcfg-eth0'
replica.vm.provision "shell",
inline: 'echo "DNS1=192.168.33.10" >> /etc/sysconfig/network-scripts/ifcfg-eth1'
replica.vm.provision "shell",
inline: 'printf "DNS=192.168.33.10\nDomains=~." >> /etc/systemd/resolved.conf'
replica.vm.provision "shell",
inline: 'systemctl restart systemd-resolved'
config.vm.provider "virtualbox" do |v|
v.memory = 1536
end
config.vm.provider "libvirt" do |v|
v.memory = 1536
end
end
config.vm.define "client" do |client|
client.vm.network "private_network", ip: "192.168.33.20"
client.vm.hostname = "client.ipademo.local"
client.vm.provision "shell",
inline: 'echo "PEERDNS=no" >> /etc/sysconfig/network-scripts/ifcfg-eth0'
client.vm.provision "shell",
inline: 'echo "DNS1=192.168.33.10" >> /etc/sysconfig/network-scripts/ifcfg-eth1'
client.vm.provision "shell",
inline: 'printf "DNS=192.168.33.10\nDomains=~." >> /etc/systemd/resolved.conf'
client.vm.provision "shell",
inline: 'systemctl restart systemd-resolved'
client.vm.provision "shell",
inline: 'sudo sed -i "s/^/#/g" /etc/httpd/conf.d/ssl.conf'
client.vm.provision "shell",
inline: 'systemctl -q enable httpd && systemctl start httpd'
client.vm.provision "shell",
inline: 'systemctl -q enable oddjobd && systemctl start oddjobd'
end
# Uncomment line below when using Fedora's cloud base box.
# config.vm.provision "shell", path: "workshop-install-packages.sh"
config.vm.provision "shell", path: "workshop-ipa-customizations.sh"
end

71
doc/workshop/building.rst Normal file
View File

@@ -0,0 +1,71 @@
.. _building:
Building Vagrant box images
===========================
This document describes how to build vagrant box images for the
FreeIPA workshop.
Requirements
------------
- Install packer (http://packer.io/)
- Install Vagrant, libvirt and VirtualBox
- Clone the Fedora kickstarts repo (https://pagure.io/fedora-kickstarts)
Packer template
---------------
Packer template ``packer-template-fedora.json`` requires Fedora 34 kickstart file
used by Fedora to build vagrant images:
- Clone the repo and checkout latest Fedora release branch::
$ git clone https://pagure.io/fedora-kickstarts.git
$ cd fedora-kickstarts
$ git checkout f34
- Install ``pykickstart`` package which provides ``ksflatten`` tool::
$ sudo dnf install pykickstart
- Generate the ``anaconda-ks.cfg`` file needed by flattening vagrant kickstart files
and putting it onto the same folder as the packer template file::
$ ksflatten -c $FEDORA_KICKSTARTS_REPO/fedora-cloud-base-vagrant.ks > $FREEIPA_REPO/doc/workshop/anaconda-ks.cfg
Building the vagrant images
-----------------------------
Build the images::
$ cd $FREEIPA_REPO/doc/workshop
$ BIN_PACKER build packer-template-fedora.json
Uploading boxes to Vagrant Cloud
----------------------------------
Vagrant by default looks for boxes in a directory called *Vagrant Cloud*.
Therefore is is good to make images available there, so that people
can easily download them as part of workshop preparation.
1. Log into https://app.vagrantup.com/.
2. Create or edit the *freeipa-workshop* box.
3. Create a new *version* of the box (left-hand menu). Each version
can include images for multiple *providers*.
4. *Create new provider* for ***virtualbox*** and upload the
corresponding ``.box`` file.
5. *Create new provider* for ***libvirt*** and upload the
corresponding ``.box`` file. *libvirt* may not appear as an
autocomplete option but type it in anyway.
6. *Release* the new version (this makes it available for
Vagrant to download). *Edit* the version, then click *Release
version*.

View File

@@ -0,0 +1,35 @@
Notes for workshop facilitators
===============================
Orientation presentation
------------------------
It is suggested to begin the workshop with a short "orientation"
presentation, which should cover:
- Goals of the workshop
- Curriculum overview
- High-level IdM concepts
- High-level FreeIPA architecture
- Further resources (this can be covered at end of workshop)
Here is an example presentation you are welcome to use:
https://github.com/frasertweedale/talks/raw/master/2016-02-03-lca-freeipa-workshop/presentation.odp
Feedback
--------
Please offer participants the opportunity to provide feedback about
their workshop. It should include questions about their technical
background and prior general IdM knowledge, as well as whether the
workshop helped them learn FreeIPA, how difficult it was, etc.
Example: https://goo.gl/forms/UOkcsVROqV
Vagrant boxes
-------------
See :ref:`building` for instructions on building Vagrant boxes.
At time of writing, the ``freeipa/freeipa-workshop`` box is
FreeIPA 4.9.3 / Fedora 34, for the VirtualBox and libvirt providers.

View File

@@ -0,0 +1,77 @@
{
"builders": [{
"type": "qemu",
"iso_url": "{{user `iso_url`}}",
"iso_checksum": "{{user `iso_checksum`}}",
"output_directory": "output-{{user `box_name`}}-x86_64-{{build_type}}",
"vm_name": "packer-{{user `box_name`}}-x86_64",
"disk_size": "{{user `disk_size`}}",
"headless": "{{user `headless`}}",
"http_directory": ".",
"boot_wait": "5s",
"boot_command": [
"<tab> ",
"inst.ks=http://{{.HTTPIP}}:{{.HTTPPort}}/anaconda-ks.cfg ",
"biosdevname=0 ",
"net.ifnames=0 ",
"<enter>"
],
"ssh_timeout": "{{user `ssh_timeout`}}",
"ssh_username": "vagrant",
"ssh_password": "vagrant",
"shutdown_command": "sudo systemctl poweroff",
"qemuargs": [
["-m", "{{user `memory`}}"],
["-smp", "{{user `cpus`}}"]
]
}, {
"type": "virtualbox-iso",
"guest_os_type": "Fedora_64",
"iso_url": "{{user `iso_url`}}",
"iso_checksum": "{{user `iso_checksum`}}",
"output_directory": "output-{{user `box_name`}}-x86_64-{{build_type}}",
"vm_name": "packer-{{user `box_name`}}-x86_64",
"disk_size": "{{user `disk_size`}}",
"headless": "{{user `headless`}}",
"http_directory": ".",
"boot_wait": "5s",
"boot_command": [
"<tab> ",
"inst.ks=http://{{.HTTPIP}}:{{.HTTPPort}}/anaconda-ks.cfg ",
"biosdevname=0 ",
"net.ifnames=0 ",
"<enter>"
],
"ssh_timeout": "{{user `ssh_timeout`}}",
"ssh_username": "vagrant",
"ssh_password": "vagrant",
"shutdown_command": "sudo systemctl poweroff",
"vboxmanage": [
["modifyvm", "{{.Name}}", "--memory", "{{user `memory`}}"],
["modifyvm", "{{.Name}}", "--cpus", "{{user `cpus`}}"]
]
}],
"provisioners": [{
"type": "shell",
"scripts": [
"workshop-install-packages.sh"
]
}],
"post-processors": [{
"type": "vagrant",
"compression_level": "{{user `compression_level`}}",
"output": "{{user `box_name`}}-x86_64-{{.Provider}}.box"
}],
"variables": {
"box_name": "fedora-34",
"iso_url": "{{user `mirror`}}/releases/34/Server/x86_64/iso/Fedora-Server-netinst-x86_64-34-1.2.iso",
"iso_checksum": "file:{{user `mirror`}}/releases/34/Server/x86_64/iso/Fedora-Server-34-1.2-x86_64-CHECKSUM",
"compression_level": "9",
"cpus": "1",
"disk_size": "40000",
"headless": "false",
"memory": "1024",
"mirror": "http://download.fedoraproject.org/pub/fedora/linux",
"ssh_timeout": "60m"
}
}

View File

@@ -0,0 +1,57 @@
Troubleshooting
===============
Local webserver
---------------
Drop firewall::
sudo firewall-cmd --add-service=http
DNS / hosts file issues
-----------------------
Flush cache
^^^^^^^^^^^
Note: some resolvers cache NX.
Max OS X::
dscacheutil -flushcache
Windows::
ipconfig /flush -- or is it /flushdns ?
Virtual network
---------------
If ``Vagrant::Errors::NetworkCollision`` occurs, try deleting host
network device, e.g.::
sudo ifconfig virbr2 down
*vagrant-libvirt* might have problems if the ``default`` network is
up::
sudo virsh net-destroy default
Vagrant
-------
If ``vagrant up`` fails to SSH into VM, delete
``~/.vagrant.d/insecure_private_key``. See
https://stackoverflow.com/questions/28284112/.
mod_lookup_identity
-------------------
To flush cache::
$ sudo sss_cache -E

View File

@@ -0,0 +1,3 @@
#!/bin/bash
sudo dnf install -y freeipa-server freeipa-server-dns sssd-dbus mod_lookup_identity mod_authnz_pam haveged nmap-ncat nano pamtester bash-completion
sudo dnf clean all

View File

@@ -0,0 +1,47 @@
#!/bin/bash
sudo systemctl enable haveged
sudo sh -c "echo 'PS1=\"[\u@\h]\\\\$ \"' >> /etc/profile"
sudo sh -c "echo 'PS1=\"[\h]\\\\$ \"' >> /etc/bashrc"
sudo sh -c "echo '192.168.33.10 server.ipademo.local' >> /etc/hosts"
sudo sh -c "echo '192.168.33.11 replica.ipademo.local' >> /etc/hosts"
sudo sh -c "echo '192.168.33.20 client.ipademo.local' >> /etc/hosts"
sudo rm -f /etc/httpd/conf.d/welcome.conf
sudo sh -c "cat >/usr/share/httpd/app.py" <<EOF
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
remote_user = environ.get('REMOTE_USER')
if remote_user is not None:
yield "LOGGED IN AS: {}\n".format(remote_user).encode('utf8')
else:
yield b"NOT LOGGED IN\n"
yield b"\nREMOTE_* REQUEST VARIABLES:\n\n"
for k, v in environ.items():
if k.startswith('REMOTE_'):
yield " {}: {}\n".format(k, v).encode('utf8')
EOF
sudo sh -c "cat >/etc/httpd/conf.d/app.conf" <<EOF
<VirtualHost *:80>
ServerName client.ipademo.local
WSGIScriptAlias / /usr/share/httpd/app.py
<Directory /usr/share/httpd>
<Files "app.py">
Require all granted
</Files>
</Directory>
</VirtualHost>
EOF
# Vagrant's "change host name" sets the short host name. Before
# we repair /etc/hosts (see below) let's reset /etc/hostname to
# the *full* host name
hostname --fqdn > /etc/hostname && hostname -F /etc/hostname
# Vagrant's "change host name" capability for Fedora maps hostname
# to loopback. We must repair /etc/hosts
sed -ri 's/127\.0\.0\.1\s.*/127.0.0.1 localhost localhost.localdomain/' /etc/hosts

286
doc/workshop/workshop.rst Normal file
View File

@@ -0,0 +1,286 @@
.. _workshop:
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:
Curriculum overview
-------------------
Mandatory:
- :ref:`Unit 1: Installing the FreeIPA server <1-server-install>`
- :ref:`Unit 2: Enrolling client machines <2-client-install>`
- :ref:`Unit 3: User management and Kerberos authentication <3-user-management>`
- :ref:`Unit 4: Host-based access control (HBAC) <4-hbac>`
Optional units—choose the topics that are relevant to you:
- :ref:`Unit 5: Web application authentication and authorisation <5-web-app-authnz>`
- :ref:`Unit 6: Service certificates <6-cert-management>`
- :ref:`Unit 7: Replica installation <7-replica-install>`
- :ref:`Unit 8: Sudo rule management <8-sudorule>`
- :ref:`Unit 9: SELinux User Maps <9-selinux-user-map>`
- :ref:`Unit 10: SSH user and host key management <10-ssh-key-management>`
- :ref:`Unit 11: Kerberos ticket policy <11-kerberos-ticket-policy>`
- :ref:`Unit 12: External IdP support <12-external-idp-support>`
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 networked virtual machines (VMs) with all software needed for
the workshop. **The goal of this preparation** is to ``vagrant up``
the VMs. After this preparation is completed you are ready to begin
the workshop.
.. _Vagrant: https://www.vagrantup.com/
Requirements
------------
For the FreeIPA workshop you will need to:
- Install **Vagrant** and **VirtualBox**. (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 using ``libvirt``.
Add your user to ``libvirt`` group so you don't need to enter your administrator
password everytime::
$ sudo gpasswd -a ${USER} libvirt
$ newgrp libvirt
Finally restart the services::
$ systemctl restart libvirtd
More information: https://docs.fedoraproject.org/en-US/quick-docs/getting-started-with-virtualization/
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-6.1
Finally, load the kernel modules (you may need to restart your system for this to work)::
$ sudo modprobe vboxdrv vboxnetadp
Mac OS X
^^^^^^^^
Install Vagrant for Mac OS X from
https://www.vagrantup.com/downloads.html.
Install VirtualBox 6.1 for **OS X hosts** from
https://www.virtualbox.org/wiki/Downloads.
Install Git from https://git-scm.com/download/mac or via your
preferred package manager.
Debian / Ubuntu
^^^^^^^^^^^^^^^
Install Vagrant, Git and VirtualBox::
$ sudo apt-get install -y vagrant git
$ sudo apt-get install -y virtualbox-6.1
If VirtualBox 6.1 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 for **Windows hosts** from
https://www.virtualbox.org/wiki/Downloads.
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.git
$ cd freeipa/doc/workshop
Fetch Vagrant box
-----------------
Please fetch the Vagrant box prior to the workshop. It is > 700MB
so it may not be feasible to download it during the workshop.
::
$ vagrant box add freeipa/freeipa-workshop
Add hosts file entries
----------------------
*This step is optional. All units can be completed using the CLI
only. But if you want to access the FreeIPA Web UI or other web
servers on the VMs from your browser, follow these instructions.*
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*.
Next step
---------
You are ready to begin the workshop. Continue to
:ref:`Unit 1: Installing the FreeIPA server <1-server-install>`.
After the workshop
------------------
Here are some contact details and resources that may help you after
the workshop is over:
- IRC: ``#freeipa`` and ``#sssd`` (Libera.chat)
- ``freeipa-users@lists.fedorahosted.org`` `mailing list
<https://lists.fedoraproject.org/archives/list/freeipa-users@lists.fedorahosted.org/>`_
- `How To guides <https://www.freeipa.org/page/HowTos>`_: large
index of articles about specialised tasks and integrations
- `Troubleshooting guide
<https://www.freeipa.org/page/Troubleshooting>`_: how to debug
common problems; how to report bugs
- `Bug tracker <https://pagure.io/freeipa>`_
- Information about the `FreeIPA public demo
<https://www.freeipa.org/page/Demo>`_ instance
- `Deployment Recommendations
<https://www.freeipa.org/page/Deployment_Recommendations>`_:
things to consider when going into production
- `Documentation index
<https://www.freeipa.org/page/Documentation>`_
- `FreeIPA Planet <http://planet.freeipa.org/>`_: aggregate of
several FreeIPA and identity-management related blogs
- `GitHub organisation <https://github.com/freeipa>`_. In addition
to the `main repository <https://github.com/freeipa/freeipa>`_
there are various tools, CI-related projects and documentation.
- `Development roadmap <https://www.freeipa.org/page/Roadmap>`_