Aller au contenu

FreeIPA un gestionnaire d'identité pour Gitlab

logo

Nous poursuivons notre démarche de sécurisation du serveur GitLab. Après avoir mis en place notre Identity Provider (IDP), à savoir FreeIPA et vérifié son bon fonctionnement, il est temps de passer à la prochaine étape : l’installation de GitLab et son intégration avec FreeIPA pour centraliser l’authentification des utilisateurs. Dans cet article, nous verrons comment configurer GitLab pour qu’il utilise FreeIPA en tant que source d’authentification, renforçant ainsi la sécurité et simplifiant la gestion des accès.

Installation de Gitlab

Modification du Vagrantfile

Je vais poursuivre le travail sur le fichier Vagrantfile du serveur IDP FreeIPA en y ajoutant un serveur dédié à l’hébergement de GitLab. D’après la documentation disponible sur le site de GitLab, l’installation est simplifiée grâce à un unique package. Une fois le dépôt de packages GitLab ajouté au serveur, l’installation se fait automatiquement. Il ne nous reste donc plus qu’à nous concentrer sur la gestion et la personnalisation de la configuration de GitLab.

Le Vagrantfile modifié :

# -*- 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
config.vm.define "gitlab" do |machine|
machine.vm.box = "generic/rocky9"
machine.vm.hostname = "gitlab.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_gitlab.yml"
end
end
end

Écriture du playbook

Voici le contenu du Playbbok deploy_gitlab.yml :

---
- name: Install Gitlab
hosts: gitlab
gather_facts: true
become: true
tasks:
- name: Read vaulted file
ansible.builtin.include_vars:
file: gitlab_password.yml
- name: Read vars
ansible.builtin.include_vars:
file: vars.yml
- name: Install prerequisites
ansible.builtin.apt:
name: "{{ gitlab_dependencies }}"
state: present
update_cache: true
notify: Start services
- name: Create folder
ansible.builtin.file:
path: /etc/gitlab/ssl
owner: root
group: root
mode: "0644"
state: directory
- name: Copy GitLab configuration file.
ansible.builtin.template:
src: gitlab.rb.j2
dest: /etc/gitlab/gitlab.rb
owner: root
group: root
mode: "0600"
- name: Copy certificats
ansible.builtin.copy:
dest: /etc/gitlab/ssl
src: "{{ item }}"
owner: root
group: root
mode: "0600"
with_items:
- gitlab.key
- gitlab.crt
- name: Test repo file exist
ansible.builtin.stat:
path: "/etc/apt/sources.list.d/gitlab_{{ gitlab_version }}.list"
register: file_exist
- name: Install gitlab if repo not exist
when: not file_exist.stat.exists
block:
- name: Download gitlab file
ansible.builtin.get_url:
mode: "0755"
url: "https://packages.gitlab.com/install/repositories/gitlab/{{ gitlab_version }}/script.deb.sh"
dest: /tmp/gitlab_install_repository.sh
- name: Create repo files
ansible.builtin.command:
cmd: bash /tmp/gitlab_install_repository.sh
creates: "/etc/apt/sources.list.d/gitlab_{{ gitlab_version }}.list"
- name: Install gitlab
ansible.builtin.apt:
name: "{{ gitlab_version }}"
environment:
EXTERNAL_URL: "https://{{ gitlab_host }}.gitlab_domain"
GITLAB_ROOT_PASSWORD: "{{ vault_gitlab_root_password }}"

Ce playbook ne gère pas le cas où le fichier de configuration est simplement modifié. Pour appliquer les modifications :

Terminal window
vagrant ssh gitlab
Last login: Thu Sep 21 13:40:56 2023 from 192.168.3.1
-bash: warning: setlocale: LC_ALL: cannot change locale (fr_FR.UTF-8)
vagrant@gitlab:~$ sudo gitlab-ctl reconfigure

Comme d’habitude le certificat a été généré avec mkcert.

Voici le template de la config de gitlab :

# The URL through which GitLab will be accessed.
external_url "{{ gitlab_external_url }}"
# gitlab.yml configuration
gitlab_rails['time_zone'] = "{{ gitlab_time_zone }}"
gitlab_rails['backup_keep_time'] = {{ gitlab_backup_keep_time }}
gitlab_rails['gitlab_email_enabled'] = {{ gitlab_email_enabled | lower }}
{% if gitlab_email_enabled %}
gitlab_rails['gitlab_email_from'] = "{{ gitlab_email_from }}"
gitlab_rails['gitlab_email_display_name'] = "{{ gitlab_email_display_name }}"
gitlab_rails['gitlab_email_reply_to'] = "{{ gitlab_email_reply_to }}"
{% endif %}
# Default Theme
gitlab_rails['gitlab_default_theme'] = "{{ gitlab_default_theme }}"
# Whether to redirect http to https.
nginx['redirect_http_to_https'] = {{ gitlab_redirect_http_to_https | lower }}
nginx['ssl_certificate'] = "{{ gitlab_ssl_certificate }}"
nginx['ssl_certificate_key'] = "{{ gitlab_ssl_certificate_key }}"
letsencrypt['enable'] = {{ gitlab_letsencrypt_enable | lower }}
{% if gitlab_letsencrypt_enable %}
letsencrypt['contact_emails'] = {{ gitlab_letsencrypt_contact_emails | to_json }}
letsencrypt['auto_renew_hour'] = "{{ gitlab_letsencrypt_auto_renew_hour }}"
letsencrypt['auto_renew_minute'] = "{{ gitlab_letsencrypt_auto_renew_minute }}"
letsencrypt['auto_renew_day_of_month'] = "{{ gitlab_letsencrypt_auto_renew_day_of_month }}"
letsencrypt['auto_renew'] = {{ gitlab_letsencrypt_auto_renew | lower }}
{% endif %}
# The directory where Git repositories will be stored.
git_data_dirs({"default" => {"path" => "{{ gitlab_git_data_dir }}"} })
# The directory where Gitlab backups will be stored
gitlab_rails['backup_path'] = "{{ gitlab_backup_path }}"
# These settings are documented in more detail at
# https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/gitlab.yml.example#L118
gitlab_rails['ldap_enabled'] = {{ gitlab_ldap_enabled | lower }}
{% if gitlab_ldap_enabled %}
gitlab_rails['prevent_ldap_sign_in'] = false
# LDAP Configuration
gitlab_rails['ldap_servers'] = {
'main' => {
'label' => 'LDAP',
'host' => '{{ gitlab_ldap_host }}',
'port' => {{ gitlab_ldap_port }},
'uid' => '{{ gitlab_ldap_uid }}',
'bind_dn' => '{{ gitlab_ldap_bind_dn }}',
'password' => '{{ gitlab_ldap_password }}',
'encryption' => '{{ gitlab_ldap_method}}',
'verify_certificates' => false,
'smartcard_auth' => false,
'active_directory' => false,
'allow_username_or_email_login' => false,
'base' => '{{ gitlab_ldap_base }}',
'user_filter' => '',
'lowercase_usernames' => 'false',
'allow_username_or_email_login' => false,
'block_auto_created_users' => false,
'group_base' => 'cn=groups,cn=accounts,dc={{ sld }},dc={{ tld }}',
'admin_group' => 'admin',
}
}
gitlab_rails['ldap_host'] = '{{ gitlab_ldap_host }}'
gitlab_rails['ldap_port'] = {{ gitlab_ldap_port }}
gitlab_rails['ldap_uid'] = '{{ gitlab_ldap_uid }}'
gitlab_rails['ldap_method'] = '{{ gitlab_ldap_method}}' # 'ssl' or 'plain'
gitlab_rails['ldap_bind_dn'] = '{{ gitlab_ldap_bind_dn }}'
gitlab_rails['ldap_password'] = '{{ gitlab_ldap_password }}'
gitlab_rails['ldap_allow_username_or_email_login'] = true
gitlab_rails['ldap_base'] = '{{ gitlab_ldap_base }}'
{% endif %}
# GitLab Nginx
## See https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/nginx.md
{% if gitlab_nginx_listen_port is defined %}
nginx['listen_port'] = "{{ gitlab_nginx_listen_port }}"
{% endif %}
{% if gitlab_nginx_listen_https is defined %}
nginx['listen_https'] = {{ gitlab_nginx_listen_https | lower }}
{% endif %}
# Use smtp instead of sendmail/postfix
# More details and example configuration at
# https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/smtp.md
gitlab_rails['smtp_enable'] = {{ gitlab_smtp_enable | lower }}
{% if gitlab_smtp_enable %}
gitlab_rails['smtp_address'] = '{{ gitlab_smtp_address }}'
gitlab_rails['smtp_port'] = {{ gitlab_smtp_port }}
{% if gitlab_smtp_user_name %}
gitlab_rails['smtp_user_name'] = '{{ gitlab_smtp_user_name }}'
{% endif %}
{% if gitlab_smtp_password %}
gitlab_rails['smtp_password'] = '{{ gitlab_smtp_password }}'
{% endif %}
gitlab_rails['smtp_domain'] = '{{ gitlab_smtp_domain }}'
{% if gitlab_smtp_authentication %}
gitlab_rails['smtp_authentication'] = '{{ gitlab_smtp_authentication }}'
{% endif %}
gitlab_rails['smtp_enable_starttls_auto'] = {{ gitlab_smtp_enable_starttls_auto | lower }}
gitlab_rails['smtp_tls'] = {{ gitlab_smtp_tls | lower }}
gitlab_rails['smtp_openssl_verify_mode'] = '{{ gitlab_smtp_openssl_verify_mode }}'
gitlab_rails['smtp_ca_path'] = '{{ gitlab_smtp_ca_path }}'
gitlab_rails['smtp_ca_file'] = '{{ gitlab_smtp_ca_file }}'
{% endif %}
# 2-way SSL Client Authentication.
{% if gitlab_nginx_ssl_verify_client %}
nginx['ssl_verify_client'] = "{{ gitlab_nginx_ssl_verify_client }}"
{% endif %}
{% if gitlab_nginx_ssl_client_certificate %}
nginx['ssl_client_certificate'] = "{{ gitlab_nginx_ssl_client_certificate }}"
{% endif %}
# GitLab registry.
registry['enable'] = {{ gitlab_registry_enable | lower }}
{% if gitlab_registry_enable %}
registry_external_url "{{ gitlab_registry_external_url }}"
registry_nginx['ssl_certificate'] = "{{ gitlab_registry_nginx_ssl_certificate }}"
registry_nginx['ssl_certificate_key'] = "{{ gitlab_registry_nginx_ssl_certificate_key }}"
{% endif %}
{% if gitlab_extra_settings is defined %}
# Extra configuration
{% for extra in gitlab_extra_settings %}
{% for setting in extra %}
{% for kv in extra[setting] %}
{% if (kv.type is defined and kv.type == 'plain') or (kv.value is not string) %}
{{ setting }}['{{ kv.key }}'] = {{ kv.value }}
{% else %}
{{ setting }}['{{ kv.key }}'] = '{{ kv.value }}'
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endif %}
# To change other settings, see:
# https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#changing-gitlab-yml-settings

Le fichier de variables :

---
# General config.
gitlab_domain: gitlab
gitlab_version: gitlab-ee
gitlab_external_url: "https://{{ gitlab_domain }}.robert.local/"
gitlab_git_data_dir: "/var/opt/gitlab/git-data"
gitlab_backup_path: "/var/opt/gitlab/backups"
# SSL Configuration.
gitlab_redirect_http_to_https: true
gitlab_ssl_certificate: "/etc/gitlab/ssl/{{ gitlab_domain }}.crt"
gitlab_ssl_certificate_key: "/etc/gitlab/ssl/{{ gitlab_domain }}.key"
# SSL Self-signed Certificate Configuration.
gitlab_create_self_signed_cert: true
gitlab_self_signed_cert_subj: "/C=US/ST=Missouri/L=Saint Louis/O=IT/CN={{ gitlab_domain }}"
# LDAP Configuration.
gitlab_ldap_enabled: true
gitlab_ldap_host: "ipa.robert.local"
gitlab_ldap_port: "636"
gitlab_ldap_uid: "uid"
gitlab_ldap_method: "simple_tls"
gitlab_ldap_bind_dn: "uid=admin,cn=users,cn=accounts,dc=robert,dc=local"
gitlab_ldap_password: "MySecretPassword123"
gitlab_ldap_base: "cn=users,cn=accounts,dc=robert,dc=local"
# SMTP Configuration
gitlab_smtp_enable: false
gitlab_smtp_address: "smtp.server"
gitlab_smtp_port: "465"
gitlab_smtp_user_name: "smtp user"
gitlab_smtp_password: "smtp password"
gitlab_smtp_domain: "robert.local"
gitlab_smtp_authentication: "login"
gitlab_smtp_enable_starttls_auto: true
gitlab_smtp_tls: false
gitlab_smtp_openssl_verify_mode: "none"
gitlab_smtp_ca_path: "/etc/ssl/certs"
gitlab_smtp_ca_file: "/etc/ssl/certs/ca-certificates.crt"
# 2-way SSL Client Authentication support.
gitlab_nginx_ssl_verify_client: ""
gitlab_nginx_ssl_client_certificate: ""
# Probably best to leave this as the default, unless doing testing.
gitlab_restart_handler_failed_when: 'gitlab_restart.rc != 0'
# Dependencies.
gitlab_dependencies:
- openssh-server
- postfix
- curl
- openssl
- tzdata
# Optional settings.
gitlab_time_zone: "UTC"
gitlab_backup_keep_time: "604800"
gitlab_download_validate_certs: true
gitlab_default_theme: '2'
# Email configuration.
gitlab_email_enabled: false
gitlab_email_from: "gitlab@robert.local"
gitlab_email_display_name: "Gitlab"
gitlab_email_reply_to: "gitlab@robert.local"
# Registry configuration.
gitlab_registry_enable: false
gitlab_registry_external_url: "https://gitlab.robert.local:4567"
gitlab_registry_nginx_ssl_certificate: "/etc/gitlab/ssl/gitlab.crt"
gitlab_registry_nginx_ssl_certificate_key: "/etc/gitlab/ssl/gitlab.key"
# LetsEncrypt configuration.
gitlab_letsencrypt_enable: false
gitlab_letsencrypt_contact_emails: ["gitlab@robert.local"]
gitlab_letsencrypt_auto_renew_hour: 1
gitlab_letsencrypt_auto_renew_minute: 30
gitlab_letsencrypt_auto_renew_day_of_month: "*/7"
gitlab_letsencrypt_auto_renew: true

La partie qui permet de définir la connexion à FreeIPA se trouve dans la section # LDAP Configuration du template et du fichier de valeurs. Les valeurs fonctionnent avec ce que j’ai défini dans le précédent billet.

Ah oui le mot de passe est stocké dans un vault ansible:

Terminal window
echo -n 'vault_gitlab_root_password: "n3xux#R8DUkGWG8M"' > gitlab_password.yml
ansible-vault encrypt gitlab_password.yml

On crée un fichier contenant le mot de passe vault :

Terminal window
echo 'passwd123' > ./vault_pass

On ajoute à la configuration d’ansible le chemin du fichier contenant le password :

[defaults]
roles_path = ansible-freeipa/roles
vault_password_file = .vault_pass

On peut passer au déploiement. Attention la taille du package gitlab dépasse les 1Gb, donc cela prend du temps.

Terminal window
vagrant up

Test de la connexion à gitlab avec le compte créé

Au bout de quelques minutes, gitlab devrait être disponible.

gitlab freeipa login

Et super cela fonctionne, j’ai pu m’authentifier !

gitlab freeipa user authentified

Content du boulot.

Plus loin

Cet épisode sur l’installation de GitLab avec une connexion à l’IDP FreeIPA arrive à sa conclusion. Dans le prochain article, nous explorerons différentes mesures de sécurité que nous pouvons mettre en place pour protéger davantage notre instance de GitLab.