Aller au contenu principal

Installation le gestionnaire d'identité FreeIPA

· 6 minutes de lecture
Stéphane ROBERT
Consultant DevOps

Je vais poursuivre mes billets sur la sécurisation de la supply chain. Dans ce billet, je vous propose de monter un IDP pour pouvoir mettre en place le principe de moindre privilège sur notre futur serveur Gitlab.

Démarche d'automatisation de l'installation de FreeIPA

Toujours le même principe. Je pars d’une feuille vierge avec comme objectifs :

  • L'installation du serveur gitlab
  • Génération de la configuration via un template.

Pour écrire le playbook Ansible, j’ai tout simplement transposé la procédure d’installation disponible sur le site de documentation de FreeIPA.

Ecriture du Vagrantfile

Le vagrantfile :

# -*- mode: ruby -*-
# vi: set ft=ruby :

ENV['VAGRANT_NO_PARALLEL'] = 'yes'

Vagrant.configure("2") do |config|
  config.vm.synced_folder '.', '/vagrant', disabled: true
  config.hostmanager.enabled = true
  config.hostmanager.manage_host = true
  # First machine is ipa
  config.vm.define "ipa" do |machine|
    machine.vm.box = "generic/rocky9"
    machine.vm.hostname = "ipa.robert.local"
    machine.vm.provider "libvirt" do |lv|
      lv.memory = 3072
      lv.cpus = 2
      lv.management_network_name = 'my_network'
      lv.management_network_address = '192.168.3.0/24'
    end
    machine.vm.provision "ansible" do |a|
      a.verbose = "v"
      a.playbook = "deploy_freeipa.yml"
      a.host_vars = {
        "ipa" => {
          "ipaserver_domain"=>"robert.local",
          "ipaserver_realm"=>"ROBERT.LOCAL",
          "ipaserver_setup_dns"=>"no",
          "ipaadmin_password"=>"MySecretPassword123",
          "ipadm_password"=>"MySecretPassword234",
        }
      }
    end
  end
end

Je pense que vous avez remarqué que sur le provisionnement du serveur FreeIPA, j'ai ajouté des variables permettant de le configurer.

Ecriture du playbook pour installer FreeIPA

En cherchant dans la documentation de FreeIPA, j'ai remarqué que Red Hat, a comme à son habitude écrit une collection permettant d'installer et d'exploiter FreeIPA. La seule contrainte, il faut utiliser un linux de la famille Red Hat, ici une Rocky Linux 9.

Avant d'écrire le playbook, je vous propose de cloner le projet de cette collection :

git clone https://github.com/freeipa/ansible-freeipa.git

Pour que vagrant puisse trouver les rôles de cette collection, créons un simple fichier ansible.cfg :

[defaults]
roles_path = ansible-freeipa/roles

Voilà le code du playbook, qui transpose ce que j'ai trouvé dans la documentation :

---
- name: Install Freeipa
  hosts: ipa
  gather_facts: true
  become: true
  vars:
  pre_tasks:
    - name: Disable ipv6
      ansible.posix.sysctl:
        name: net.ipv6.conf.all.disable_ipv6
        value: 1
        sysctl_file: /etc/sysctl.conf
    - name: Enable ipv6 on lo
      ansible.posix.sysctl:
        name: net.ipv6.conf.lo.disable_ipv6
        value: 0
        sysctl_file: /etc/sysctl.conf
        reload: true
    - name: Set TimeZone to Paris
      community.general.timezone:
        name: Europe/Paris
  roles:
  - role: ipaserver
    state: present

On peut lancer le provisionnement de la machine FreeIPA :

vagrant up ipa

Au bout de quelques minutes votre serveur FreeIPA est up. Une petite vérification :

vagrant ssh ipa

Last login: Sun Sep 17 16:49:49 2023 from 192.168.3.1
[vagrant@ipa ~]$ netstat -tlnp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:464             0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:88              0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:749             0.0.0.0:*               LISTEN      -
tcp6       0      0 :::389                  :::*                    LISTEN      -
tcp6       0      0 :::464                  :::*                    LISTEN      -
tcp6       0      0 :::8443                 :::*                    LISTEN      -
tcp6       0      0 :::22                   :::*                    LISTEN      -
tcp6       0      0 :::88                   :::*                    LISTEN      -
tcp6       0      0 :::111                  :::*                    LISTEN      -
tcp6       0      0 :::749                  :::*                    LISTEN      -
tcp6       0      0 :::636                  :::*                    LISTEN      -
tcp6       0      0 127.0.0.1:8009          :::*                    LISTEN      -
tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      -
tcp6       0      0 ::1:8009                :::*                    LISTEN      -
tcp6       0      0 :::8080                 :::*                    LISTEN      -

Vérifions que nous pouvons consulter les utilisateurs présents dans le serveur. Avant, il faut obtenir un token Kerberos avec la commande kinit :

[vagrant@ipa ~]$ kinit admin
Password for admin@ROBERT.LOCAL:
[vagrant@ipa ~]$ ipa user-find --all
--------------
1 user matched
--------------
  dn: uid=admin,cn=users,cn=accounts,dc=robert,dc=local
  User login: admin
  Last name: Administrator
  Full name: Administrator
  Home directory: /home/admin
  GECOS: Administrator
  Login shell: /bin/bash
  Principal alias: admin@ROBERT.LOCAL, root@ROBERT.LOCAL
  User password expiration: 20231216144606Z
  UID: 1251800000
  GID: 1251800000
  Account disabled: False
  Preserved user: False
  Member of groups: admins, trust admins
  ipantsecurityidentifier: S-1-5-21-150280649-1004467653-323320090-500
  ipauniqueid: 0026acac-5568-11ee-a911-525400c0a1d3
  krbextradata: AAIuEQdlcm9vdC9hZG1pbkBST0JFUlQuTE9DQUwA
  krblastadminunlock: 20230917144606Z
  krblastpwdchange: 20230917144606Z
  objectclass: top, person, posixaccount, krbprincipalaux, krbticketpolicyaux, inetuser, ipaobject, ipasshuser,
               ipaSshGroupOfPubKeys, ipaNTUserAttrs
----------------------------
Number of entries returned 1
----------------------------

Pas mal, nous avons un utilisateur présent, le compte admin bien sûr. Je vais utiliser la CLI ipa pour créer les utilisateurs dans un premier temps. Ajoutons un utilisateur :

ipa user-add steph --first=Stéphane --last=ROBERT --email=steph@robert.local
------------------
Added user "steph"
------------------
  User login: steph
  First name: Stéphane
  Last name: ROBERT
  Full name: Stéphane ROBERT
  Display name: Stéphane ROBERT
  Initials: SR
  Home directory: /home/steph
  GECOS: Stéphane ROBERT
  Login shell: /bin/sh
  Principal name: steph@ROBERT.LOCAL
  Principal alias: steph@ROBERT.LOCAL
  Email address: steph@robert.local
  UID: 1251800003
  GID: 1251800003
  Password: False
  Member of groups: ipausers
  Kerberos keys available: False

Définissons le mot de passe :

ipa user-mod steph --password

Entrez deux fois le même mot de passe. Vérifions que nous pouvons retrouver les utilisateurs via les commandes ldap :

ldapsearch -H ldaps://ipa.robert.local -D 'uid=admin,cn=users,cn=accounts,dc=robert,dc=local' -w MySecretPassword123 -b 'uid=steph,cn=users,cn=accounts,dc=robert,dc=local'
# extended LDIF
#
# LDAPv3
# base <uid=steph,cn=users,cn=accounts,dc=robert,dc=local> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# steph, users, accounts, robert.local
dn: uid=steph,cn=users,cn=accounts,dc=robert,dc=local
givenName:: U3TDqXBoYW5l
sn: ROBERT
uid: steph
cn:: U3TDqXBoYW5lIFJPQkVSVA==
displayName:: U3TDqXBoYW5lIFJPQkVSVA==
initials: SR
gecos:: U3TDqXBoYW5lIFJPQkVSVA==
krbPrincipalName: steph@ROBERT.LOCAL
mail: steph@robert.local
objectClass: top
objectClass: person
objectClass: organizationalperson
objectClass: inetorgperson
objectClass: inetuser
objectClass: posixaccount
objectClass: krbprincipalaux
objectClass: krbticketpolicyaux
objectClass: ipaobject
objectClass: ipasshuser
objectClass: ipaSshGroupOfPubKeys
objectClass: mepOriginEntry
objectClass: ipantuserattrs
loginShell: /bin/sh
homeDirectory: /home/steph
krbCanonicalName: steph@ROBERT.LOCAL
ipaUniqueID: 3c0bbe66-5571-11ee-8e38-525400c0a1d3
uidNumber: 1251800003
gidNumber: 1251800003
mepManagedEntry: cn=steph,cn=groups,cn=accounts,dc=robert,dc=local
ipaNTSecurityIdentifier: S-1-5-21-150280649-1004467653-323320090-1003
memberOf: cn=ipausers,cn=groups,cn=accounts,dc=robert,dc=local
krbPasswordExpiration: 20230917155005Z
krbLastPwdChange: 20230917155005Z
krbExtraData:: AAItIAdlcm9vdC9hZG1pbkBST0JFUlQuTE9DQUwA

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

Bon notre serveur ldap fonctionne comme attendu ! Pour créer les utilisateurs et les groupes, nous allons utiliser les modules ipa.

- name: Install Freeipa
  hosts: ipa
  gather_facts: true
  become: true
  vars:
  tasks:
    - name: Ensure steph is present and always reset password
      community.general.ipa_user:
        name: Steph
        state: present
        password: steph123
        givenname: Stéphane
        ipa_host: ipa.robert.local
        ipa_user: admin
        ipa_pass: MySecretPassword123

On va pouvoir, configurer notre serveur IPA avec les modules Ansible.

Plus loin

Dans le prochain billet, nous provisionnerons le serveur Gitlab et nous utiliserons le serveur IPA comme source d'authentification. PAr contre, je mettrais à jour ce billet avec du code Terraform pour le déployer sur mon homelab dans les prochains jours. Je vais aussi étudier la partie exploitation de FreeIPA. Et oui, il faut maintenir ce genre d'outil : mise à jour, sauvegarde, reprise sur incident, ...