# FreeIPA

- [FreeIPA](#freeipa)
  - [Notes](#notes)
  - [Quickstart Debugging Setup](#quickstart-debugging-setup)
  - [Quickstart Production Setup](#quickstart-production-setup)
  - [NFS](#nfs)
  - [Tips](#tips)
  - [Adding a user](#adding-a-user)
    - [Adding a Smart Card Certificate](#adding-a-smart-card-certificate)
  - [PIV](#piv)
    - [Sources](#sources)
    - [Set up PIV Auth on the Host where you Installed FreeIPA](#set-up-piv-auth-on-the-host-where-you-installed-freeipa)
      - [Note for VMs](#note-for-vms)
      - [Set up PIV](#set-up-piv)
    - [Set up PIV on Another Host](#set-up-piv-on-another-host)
    - [PIV Smart Card (Yubikey Manual) WIP](#piv-smart-card-yubikey-manual-wip)
    - [PIV Smart Card (Taglio) WIP](#piv-smart-card-taglio-wip)
    - [Finding devices in sysfs WIP](#finding-devices-in-sysfs-wip)
    - [Finding p11 devices WIP](#finding-p11-devices-wip)
  - [Arch Client WIP](#arch-client-wip)
  - [Troubleshooting](#troubleshooting)
    - [Changing IP address](#changing-ip-address)

An AD Server.

This guide assumes Fedora 40+.

## Notes

For yubikey manager appimage extend app not responding timeout to 60 seconds

```bash
gsettings set org.gnome.mutter check-alive-timeout 0
```

## Quickstart Debugging Setup

This sets up a freeipa server on RHEL 9 for debugging purposes. No DNS records required
and mostly for local use.

```bash
# Don't forget to install tmux
dnf install -y tmux
```

Install FreeIPA:

```bash
# Hostname needs to be an address that isn't managed by DNS (FreeIPA will check)
# We can get away with *.name.reeselink.com because "name.reeselink.com" doesn't resolve.
export HNAME="freeipa.reese.reeselink.com"
export IPS=$(hostname -I)
# Add "<ip address> freeipa.<unique_name>.reeselink.com" to the /etc/hosts
# Example: "10.3.128.130 freeipa.reese.reeselink.com" <- note, this address *cannot* already exist.
# This will allow us to access our AD server without DNS complication 
for item in $IPS; do echo "$item $HNAME" >> /etc/hosts; done

# FreeIPA checks for this
hostnamectl set-hostname $HNAME --static
hostname $HNAME

# Turning off selinux isn't required, but is nice for debugging.
setenforce 0
sed -i 's/^SELINUX=.*/SELINUX=permissive/g' /etc/selinux/config

# Install FreeIPA with the dns packages. We *could* use this server our DNS server if
# we wanted. This will prevent DCV from talking to our auth endpoint, however, so isn't
# recommended.
dnf install ipa-server-dns bind-dyndb-ldap -y

# IPA Server install
# Note - select defaults for almost everything except:
# 1. We want DNS, so say yes to that
# 2. We don't need to scan for additional zones
ipa-server-install --setup-dns

# Setup firewall
firewall-cmd --add-service=freeipa-ldap --add-service=freeipa-ldaps --add-service=dns --permanent
firewall-cmd --reload

# Install flatpak
dnf install flatpak
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
flatpak install it.mijorus.gearlever
```

1. Download the yubikey manager at <https://www.yubico.com/support/download/yubikey-manager/>
2. Open it in Gear Lever and add to app menu

```bash
# Install pcscd
dnf install pcsc-lite opensc
# Start the pcscd server
systemctl enable --now pcscd
```

Now skip to [Get PIV Working](#piv)

## Quickstart Production Setup

<https://www.freeipa.org/page/Quick_Start_Guide>

1. Set your hostname to your server's fqdn with `hostnamectl hostname freeipa.reeselink.com`
2. If you want freeipa to manage your DNS, make sure you don't have a DNS address pointing to your domain
3. Open freeipa ports

    ```bash
    firewall-cmd --add-service=freeipa-4
    firewall-cmd --add-service=freeipa-4 --permanent
    firewall-cmd --reload
    ```

4. Set a permanent DNS resolver

    ```bash
    rm /etc/resolv.conf
    echo "nameserver 1.1.1.1" > /etc/resolv.conf
    ```

5. Disable NetworkManager DNS management

    ```bash
    vim /etc/NetworkManager/NetworkManager.conf

    [main]
    dns=none
    ```

6.  Reboot
7.  Ensure resolv.conf hasn't been repopulated: `cat /etc/resolv.conf`
8.  Install freeipa: `dnf install -y freeipa-server freeipa-server-dns`
9.  Install the server (mostly choose defaults and sane options): `ipa-server-install`
10. Authenticate as admin: `kinit admin`

Now skip to [Get PIV Working](#piv)

## NFS

<https://www.techrepublic.com/article/kerberos-authentication-with-nfsv4/>

```bash
mkdir /exports
chmod 1777 /exports
mount --bind /srv /exports/srv
```

What this does is remounts /srv to /exports/srv. Effectively, this means that
/srv can be accessed directly, or via /exports/srv and changes in one location
reflect in the other.

To make this persistent, add the mount command above to /etc/rc.d/rc.local or
some similar executed-at-boot script.

Next, edit `/etc/sysconfig/nfs` and enable the SECURE_NFS option:

```conf
SECURE_NFS="yes"
```

Then edit `/etc/exports`. The “/exports” entry has the “fsid=0” option, which
tells NFS that this is the “root” export.

```fstab
/exports     gss/krb5(rw,sync,fsid=0,insecure,no_subtree_check)

/exports/srv gss/krb5(rw,sync,nohide,insecure,no_subtree_check)
```

Create the server principal for the NFS server and add it to the keytab file on
the server using kadmin (usually /etc/krb5.keytab):

```bash
kadmin.local

kadmin.local: addprinc -randkey nfs/nfsserver.domain.com
kadmin.local: ktadd -e des-cbc-crc:normal -k /etc/krb5.keytab nfs/nfsserver.domain.com
kadmin.local: quit
```

Edit `/etc/idmapd.conf` and make sure the Nobody-User and Nobody-Group options
are correct (i.e. on Red Hat Enterprise Linux and Fedora, use the “nfsnobody”
user and group, other distributions may just use “nobody”)

```bash
systemctl restart nfs rpcidmapd
```

open TCP port 2049 for use with NFsv4

```bash
firewall-cmd --add-service=nfs
firewall-cmd --add-service=nfs --permanent
firewall-cmd --reload
```

## Tips

```bash
# Install gnome desktop on Fedora server
dnf group install gnome-desktop
systemctl enable gdm
reboot

# Install spice tools for clipboard sync
sudo dnf install spice-vdagent
reboot
```

## Adding a user

- `ipa user-add`
- `ipa passwd <user>`
- `kinit <user>`

### Adding a Smart Card Certificate

1. Login to the UI as admin
2. Navigate to your user
3. Actions -> New Certificate
4. Generate a self-signed CSR with your yubikey
5. Paste the CSR into the CSR field
6. Generate
7. Download the certificate from the user page
8. Import the certificate into slot 9a for your yubikey
9. `kinit -X X509_user_identity='PKCS11:opensc-pkcs11.so' idm_user`

## PIV

### Sources

Self signed piv cert generation
<https://developers.yubico.com/yubico-piv-tool/Actions/key_generation.html>

Explaing Yubikey key slots
<https://developers.yubico.com/PIV/Introduction/Certificate_slots.html>

Ultimate guide to creating a CA
<https://checkmk.com/linux-knowledge/creating-server-certificate>

CA Public directory
<https://nextcloud.reeseapps.com/s/twRAFeWJZKJ3Qw5>

Convert pem to der
<https://knowledge.digicert.com/solution/how-to-convert-a-certificate-into-the-appropriate-format>

Add smart card login to extended key use
<https://docs.openssl.org/master/man5/x509v3_config/#key-usage>

This should set up a CA and a signed cert for your yubikey.
<https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/8/html/managing_smart_card_authentication/configuring-idm-for-smart-card-auth_managing-smart-card-authentication#conf-idm-server-for-smart-card-auth_configuring-idm-for-smart-card-auth>

### Set up PIV Auth on the Host where you Installed FreeIPA

#### Note for VMs

"virt-manager USB redirection error: Device is in use by another application"

You won't be able to pass through a smart card without stopping pcscd on the host.

```bash
systemctl stop pcscd.socket && systemctl stop pcscd
```

#### Set up PIV

```bash
# copy the CA and run the ipa-advise script that sets up smartcard auth
cp /etc/ipa/ca.crt ca.crt
sudo -i
kinit admin
ipa-advise config-server-for-smart-card-auth > config-server-for-smart-card-auth.sh
chmod +x config-server-for-smart-card-auth.sh
./config-server-for-smart-card-auth.sh ca.crt
```

Allow smart card auth in browser with these changes `/etc/httpd/conf.d/ssl.conf`

```conf
...
SSLOCSPEnable off
...
SSLProtocol all -TLSv1 -TLSv1.1 -TLSv1.3
...
```

And restart httpd:

```bash
systemctl restart httpd
```

Then user -> actions -> new certificate. Paste in the yubikey CSR. Download then upload cert to the yubikey.

Auth with smart card

```bash
kinit -X X509_user_identity='PKCS11:opensc-pkcs11.so' idm_user
```

Or with pam

```bash
cp /etc/ipa/ca.crt /etc/sssd/pki/sssd_auth_ca_db.pem
dnf install -y sssd-tools
authselect enable-feature with-smartcard
# required: authselect enable-feature with-smartcard-required
# lock on remove: authselect enable-feature with-smartcard-lock-on-removal
# set "pam_cert_auth = True" in [pam] section of /etc/sssd/sssd.conf
systemctl restart sssd
sssctl user-checks -s gdm-smartcard "ducoterra" -a auth
```

### Set up PIV on Another Host

**NOTE**: Make sure, if you're joining with a host that already has a user with a username that
exists in your freeipa server, that **you set the UID in freeipa to match the UID on
the system**. Otherwise joining will cause all sorts of problems.

```bash
# This package is required to join a FreeIPA realm
# I think it helps collect and save the relevant data from the FreeIPA
# server when joining (server CA, NTP sync, SSH keys, etc.)
dnf install -y freeipa-client

hostnamectl set-hostname client.reese.reeselink.com

# OPTIONAL: You need to leave any existing AD realm before joining a new one
# realm leave <some-realm>

# Install pcscd
dnf install pcsc-lite opensc
# Start the pcscd server
systemctl enable --now pcscd

# Update client's dns server to use freeipa
vim /etc/resolv.conf
nameserver 192.168.122.130

# This should populate /etc/krb5.conf and /etc/sssd/sssd.conf
realm join -U admin freeipa.reese.reeselink.com -v

# With kinit
kinit -X X509_user_identity='PKCS11:opensc-pkcs11.so' idm_user

# With sssctl
dnf install -y sssd-tools
cp /etc/ipa/ca.crt /etc/sssd/pki/sssd_auth_ca_db.pem
chmod 600 /etc/ipa/ca.crt /etc/sssd/pki/sssd_auth_ca_db.pem
authselect enable-feature with-smartcard
# required: authselect enable-feature with-smartcard-required
# lock on remove: authselect enable-feature with-smartcard-lock-on-removal
```

IMPORTANT: set `pam_cert_auth = True` in `[pam]` section of `/etc/sssd/sssd.conf`.

```bash
systemctl restart sssd
sssctl user-checks -s gdm-smartcard "ducoterra" -a auth
```

### PIV Smart Card (Yubikey Manual) WIP

```bash
openssl req -x509 -config openssl-ca.cnf -days 3650 -newkey rsa:4096 -sha256 -nodes -out cacert.pem -outform PEM
touch index.txt
echo '01' > serial.txt

# Sign the csr generated in slot 9a on your yubikey
openssl ca -config openssl-ca.cnf -policy signing_policy -extensions signing_req -out reese-crt.pem -infiles reese-csr.pem

# Inspect
openssl x509 -in reese-crt.pem -text -noout

# Convert to microsoft format
openssl x509 -outform der -in reese-crt.pem -out reese-crt-der.cer
```

OCSP Server

<https://bhashineen.medium.com/create-your-own-ocsp-server-ffb212df8e63>

```bash
openssl req -new -nodes -out ocspSigning.csr -keyout ocspSigning.key
openssl ca -keyfile rootCA.key -cert rootCA.crt -in ocspSigning.csr -out ocspSigning.crt -config validation.conf
```

### PIV Smart Card (Taglio) WIP

<https://github.com/OpenSC/OpenSC/wiki/Using-pkcs11-tool-and-OpenSSL>

```bash
openssl genrsa -aes256 -out testkey.key 2048
openssl rsa -in testkey.key -pubout -out testkey-public.key
openssl req -new -key testkey.key -out testkey.csr

# Sign with CA
```

### Finding devices in sysfs WIP

```bash
# Try this
ls /dev/input/by-id
udevadm info --query=all --name='/dev/input/by-id/usb-Yubico_YubiKey_OTP+FIDO+CCID-event-kbd'
# Look for E: DEVPATH and put /sys in front of it
# For example:
cd /sys/devices/pci0000:00/0000:00:02.1/0000:02:00.0/usb1/1-3/1-3:1.0/0003:1050:0407.0004/input/input10/event6

# Or alternatively
find /sys -name 'removable'
cd /sys/devices/pci0000:00/0000:00:02.1/0000:02:00.0/usb1/1-3
```

### Finding p11 devices WIP

```bash
dnf install python3-pip python3-devel gcc
python3 -m venv venv
source venv/bin/activate
pip install -U pip
pip install python-pkcs11
export PKCS11_MODULE=/usr/lib64/p11-kit-proxy.so
```

## Arch Client WIP

- Install krb5: `pacman -S krb5`
- Edit /etc/krb5.conf to match your server

```conf
vim /etc/krb5.conf

[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = REESELINK.COM
 dns_lookup_realm = false
 dns_lookup_kdc = true
 rdns = false
 ticket_lifetime = 24h
 forwardable = true
 udp_preference_limit = 0
 default_ccache_name = KEYRING:persistent:%{uid}

[realms]
 REESELINK.COM = {
  kdc = freeipa.reeselink.com:88
  master_kdc = freeipa.reeselink.com:88
  kpasswd_server = freeipa.reeselink.com:464
  admin_server = freeipa.reeselink.com:749
  default_domain = reeselink.com
  pkinit_anchors = FILE:/var/lib/ipa-client/pki/kdc-ca-bundle.pem
  pkinit_pool = FILE:/var/lib/ipa-client/pki/ca-bundle.pem
}

[domain_realm]
 .reeselink.com = REESELINK.COM
 reeselink.com = REESELINK.COM
 freeipa.reeselink.com = REESELINK.COM
```

- Log in with your user: `kinit <user>`
- List your tickets: `klist`

## Troubleshooting

### Changing IP address

Changing the IP address of a freeipa server can break dnssec. You'll get
"servfail" looking things up. The quick way to fix this is to edit
`/etc/named/ipa-options-ext.conf` and to set `dnssec-validation no;`.
