Installation et configuration de Semaphore UI l'interface web pour Ansible

Open source ansible semaphore automatisation

Si vous n'avez pas de centrale nucléaire dédiée pour faire tourner Ansible AWX, Semaphore UI devrait alors vous plaire. Voici un article sur son installation et la configuration d'un playbook.

Dans cet article, je vais installer Semaphore UI avec comme objectif une mise à jour programmée de mes serveurs Debian et un dépôt Git comme référentiel.

spaces_-MjiAzQOIMcQuH4zX4KI_uploads_git-blob-22f6a68332c47aef1de55c7ee28199f7b35899af_image

Il existe 3 façons d'installer Semaphore :

  • Snap : pratique pour une première prise en main mais peut s'avérer vite limitée notamment lors de l'utilisation de librairies Python. J'avais démarré avec ce mode d'installation, mais j'ai eu un blocage avec la librairie Python Kerberos utilisé avec mes hôtes cibles Windows.
  • Docker : Je n'ai pas testé.
  • Paquet : C'est sur ce modèle que j'ai choisi d'installer Semaphore UI.

Au fait, pourquoi ? En effet, on pourrait se contenter d'une usage CLI d'Ansible et faire la même chose. Oui mais dans le cadre d'un usage au sein d'une équipe, c'est clairement plus facile d'organiser cela à travers une application.

Pour cet article, j'utilise une VM sous Proxmox VE avec un OS Debian 12.

Nous nous servirons de Postgresql comme backend de configuration.

Sur notre serveur dédié à Semaphore :

su - postgres
psql

postgres=# ALTER USER postgres WITH password 'unmotdepasse';
postgres=# create database semaphoredb;
postgres=# create user semaphore with encrypted password 'unautremotdepasse';
postgres=# grant all privileges on database semaphoredb to semaphore;
postgres=# ALTER DATABASE semaphoredb OWNER TO semaphore;
postgres=# GRANT USAGE, CREATE ON SCHEMA PUBLIC TO semaphore;

apt install gpg

UBUNTU_CODENAME=jammy

wget -O- "https://keyserver.ubuntu.com/pks/lookup?fingerprint=on&op=get&search=0x6125E2A8C77F2818FB7BD15B93C4A3FD7BB9C367" | sudo gpg --dearmour -o /usr/share/keyrings/ansible-archive-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/ansible-archive-keyring.gpg] http://ppa.launchpad.net/ansible/ansible/ubuntu $UBUNTU_CODENAME main" | sudo tee /etc/apt/sources.list.d/ansible.list

sudo apt update && sudo apt install ansible

Sur le serveur créez un utilisateur standard qui nous servira pour le service Semaphore. Le mien sera "semuser01" avec comme groupe "semuser01"

apt install curl git -y
vim /root/semaphore_latest.sh

#!/bin/bash
VER=$(curl -s https://api.github.com/repos/ansible-semaphore/semaphore/releases/latest|grep tag_name | cut -d '"' -f 4|sed 's/v//g')
wget -q https://github.com/ansible-semaphore/semaphore/releases/download/v${VER}/semaphore_${VER}_linux_amd64.deb
dpkg -i semaphore_${VER}_linux_amd64.deb

./semaphore_latest.sh

mkdir /etc/semaphore/
chown -R semuser01:semuser01 /etc/semaphore/

root@srv-semaphore:~# semaphore setup

Hello! You will now be guided through a setup to:

1. Set up configuration for a MySQL/MariaDB database
2. Set up a path for your playbooks (auto-created)
3. Run database Migrations
4. Set up initial semaphore user & password

What database to use:
   1 - MySQL
   2 - BoltDB
   3 - PostgreSQL
 (default 1): 3

db Hostname (default 127.0.0.1:5432): 

db User (default root): semaphore

db Password: LEPASSWORD

db Name (default semaphore): semaphoredb

Playbook path (default /tmp/semaphore): 

Public URL (optional, example: https://example.com/semaphore): 

Enable email alerts? (yes/no) (default no): 

Enable telegram alerts? (yes/no) (default no): 

Enable slack alerts? (yes/no) (default no): 

Enable LDAP authentication? (yes/no) (default no): 

Config output directory (default /root): /etc/semaphore/

Running: mkdir -p /etc/semaphore/..
Configuration written to /etc/semaphore/config.json..
 Pinging db..
Running db Migrations..
Executing migration v0.0.0 (at 2024-01-06 13:46:12.504720912 +0100 CET m=+60.655151485)...
Creating migrations table
(...)

Migrations Finished

 > Username: semuser01         
 > Email: semuser01@domain.tld
 > Your name: semuser01
 > Password: UNPASSWORD

 You are all setup semuser01
 Re-launch this program pointing to the configuration file

./semaphore server --config /etc/semaphore/config.json

 To run as daemon:

nohup ./semaphore server --config /etc/semaphore/config.json &

 You can login with semuser01@domain.tld or semuser01.

Ici j'ai de nouveau créé un utilisateur semuser01 mais il n'est pas lié au compte créé précédemment sur le serveur.

Configuration système

# Configuration du service
vim /etc/systemd/system/semaphore.service

[Unit]
Description=Semaphore Ansible
Documentation=https://github.com/ansible-semaphore/semaphore
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
User=semuser01
Group=semuser01
ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/usr/bin/semaphore service --config=/etc/semaphore/config.json
SyslogIdentifier=semaphore
Restart=always

[Install]
WantedBy=multi-user.target

root@srv-semaphore:~# systemctl daemon-reload
root@srv-semaphore:~# systemctl enable semaphore.service
Created symlink /etc/systemd/system/multi-user.target.wants/semaphore.service → /etc/systemd/system/semaphore.service.
root@srv-semaphore:~# systemctl start semaphore.service

Connectez sur http://IP:3000 et authentifiez vous avec votre user.

Note : Les données sensibles sont stockées et chiffrées dans la base de données. Vous devez définir l'option de configuration access_key_encryption dans le fichier de configuration /etc/semaphore/config.json pour activer le chiffrement des clés d'accès. Cette clé est générée automatiquement lors du setup.

Façon de se connecter de manière sécurisée à Semaphore, j'ai utilisé ma PKI locale pour créer un certificat serveur puis j'ai configuré mon reverse-proxy Nginx :

upstream srvsem {
        server IPSEMAPHORESRV:3000;
        keepalive 64;
}

server {
        listen 80;
        server_name sem.domain.tld;
        return 301 https://$host$request_uri;
}

server {
        server_name sem.domain.tld;
        listen 443 ssl http2;

        # Other SSL stuff goes here
        ssl_certificate /etc/nginx/ssl/sem.crt;
        ssl_certificate_key /etc/nginx/ssl/sem.key;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        add_header X-XSS-Protection "1; mode=block";
        add_header X-Frame-Options "DENY";
        add_header X-Content-Type-Options "nosniff";
        more_set_headers "Server: My server";
        add_header X-Powered-By "Love";
        add_header Referrer-Policy "no-referrer";

    location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host;
        proxy_set_header X-NginX-Proxy true;
        proxy_buffering off;
        proxy_request_buffering off;
        proxy_pass http://srvsem/;

    }

    location /api/ws {
        proxy_pass http://srvsem/api/ws;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Origin "";
  }

        access_log /var/log/nginx/sem.access.log;
        error_log  /var/log/nginx/sem.error.log;
}

Testez la connexion en vous rendant maintenant sur https://sem.domain.tld

Un projet est un lieu pour séparer les activités de gestion. Toutes les activités de Sémaphore se déroulent dans le contexte d'un projet.

Les projets sont indépendants les uns des autres, vous pouvez donc les utiliser pour organiser des systèmes non liés au sein d'une seule installation Semaphore. Cela peut être utile pour gérer différentes équipes, infrastructures, environnements ou applications.

projet

Une fois le projet créé, vous avez accès à différents paramètres à configurer :

projet01

Dans le cadre du travail, on peut ajouter ses collègues et leur adjoindre un rôle :

  • Guest : ne peut rien faire à par lister les modèles de tâches, les inventaires... sans pouvoir les visualiser.
  • Task runner : peut lancer des modèles de tâches sans pouvoir visulaiser le contenu et éditer ceux-ci, de mêmes pour les autres paramètres (Dépôts...).
  • Manager : peut tout éditer ou créer, lancer les modèles de tâches mais ne peut pas éditer les paramètres du projet.
  • Owner : peut tout faire.

Voici l'ordre de configuration :

  1. Magasin de clés : sert à renseigner les mots de passe (Git, Ansible...) et clés SSH.
  2. Dépôts : pour renseigner les dépôts comme le dépôt Git dans cet article.
  3. Inventaire : pour renseigner les hôtes cibles.
  4. Environnement : pour passer des variables.
  5. Modèles de tâches : pour créer des tâches.

Git

Ces creds seront utilisés lors de la configuration du dépôt Git.

Cliquez sur Nouvelle clé puis :

  • Renseignez le nom,
  • Choisissez le type : ici "Connectez-vous avec mot de passe"
  • Connexion : renseignez votre login
  • Mot de passe : le mot de passe correspondant à votre login.

magkey

Une fois les informations saisies et validées, vous ne pouvez plus les récupérer. Si vous avez commis une erreur de saisie, il vous faudra de nouveau renseigner les informations et choisir l'option "remplacer". Seul le nom de la clé est modifiable sans cocher l'option "remplacer".

SSH

Ces creds seront utilisés lors de la création des inventaires, la finalité étant de pouvoir se connecter aux hôtes présents dans celui-ci. Il faudra que votre clé publique SSH ait été au préalable copiée sur les hôtes cibles (ssh-copy-id).

Cliquez sur Nouvelle clé puis :

  • Renseignez le nom.
  • Type : Clé SSH
  • Nom d'utilisateur : vous pouvez renseigner ici le nom de l'utilisateur qui va se connecter en SSH, c'est le "ansible_user". Semaphore vous laisse l'option de renseigner cette variable ailleurs.
  • Clé privée : renseignez la clé privée SSH.

sshkey

Comme pour la clé précédente, une fois les informations saisies et validées, vous ne pouvez plus les récupérer pour les afficher.

Sudo

Dans le cas où vous utilisez une escalade des privilèges avec sudo et un mot de passe.

Ici je renseigne le mot de passe de l'utilisateur ansibleuser01 sans préciser la case Connexion.

sudo

Vault Password

Il se peut que vous ayez besoin de renseigner des mots de passe dans vos playbooks. Bien évidemment vous les aurez chiffrés avec ansible vault avant.

Afin de les déchiffrer, il vous faudra le mot de passe utilisé. Dans Semaphore ce mot de passe sera appelé depuis un modèle de tâche.

Créez une clé du type "Connectez-vous avec mot de passe"

vault

Mot de passe vide

Il peut être utile de créer une clé du type "Aucune" dans le cas où l'on souhaite par exemple utiliser plus tard un dépôt local situé sur le serveur Semaphore sachant que l'utilisation d'une clé (même vide) est obligatoire lors de la création d'un dépôt.

vide

Rendez-vous dans Dépôts puis cliquez sur "Nouveau référentiel".

gitdepot

Rendez-vous sur Inventaire, cliquez sur Nouvel Inventaire puis renseignez les informations :

  • Le nom de votre inventaire qui sera appelé plus tard par le "modèle de base".
  • L'identifiant utilisateur : ici ce sera la clé SSH pour se connecter sur les hôtes de notre inventaire.
  • l'identifiant Sudo : ici nous sélectionnons la clé Sudo. Si vous utilisez sudo sans mot de passe, ne renseignez rien.
  • Type : ici j'ai choisi le Static YAML.

L'édition d'un inventaire dans Semaphore n'étant pas super pratique, je vous conseille d'utiliser votre éditeur préféré puis de copier/coller ce dernier dans l'éditeur de Semaphore.

L'inventaire en lui-même est le même que celui utilisé de manière classique avec Ansible. Exemple :

all:
  vars:
    unmotdepasse: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          31..................................................
          ....................................................
          ....................................................
          ..................................................33
debian:
  hosts:
    srv-deb01:
    srv-deb02:
    srv-de03:
      ansible_port: 12003
    srv-deb04:
      ansible_port: 11004

Notez qu'ici j'ai précisé :

  • la variable "unmotdepasse" contenant un mot de passe chiffré avec Ansible Vault.
  • les ports SSH de connexion pour certains hôtes cibles n'utilisant pas le port 22.

Vous devez renseignez un environnement même si celui-ci est vide.

env01

Exemple avec la variable permettant d'éviter le "host key checking" :

env02

Création des vues

Façon de ne pas mélanger tous mes modèles, je vais créer trois vues :

  • Test : pour tester des modèles non finalisés
  • Maintenance : pour contenir mes modèles permettant de mettre à jour mes hôtes cibles (màj sys, applicative...)
  • Déploiement : pour le déploiement de configurations, d'applications, d'utilisateurs....

Cliquez sur le crayon situé à côté de "Tous" puis créez les vues. Validez chaque vue en cliquant du l'icône check puis fermez ensuite en cliquant sur la croix à côté de "Modifier les vues".

modeles

Création d'un modèle

Cliquez sur "Nouveau modèle" puis renseignez comme ci-dessous :

modele

Notez ici que j'appelle le playbook debian-update.yml qui doit exister sur le dépôt Git.

Une fois cela fait, cliquez sur "Run" et cochez l'option "Simulation". Si vous avez des erreurs, celles-ci apparaîtront comme avec l'utilisation d'Ansible en mode CLI. Vous pouvez également activer l'option Debug si besoin de plus de précisions.

Si votre test est réussi, vous pouvez modifier le modèle en modifiant la vue en "Maintenance" puis planifier la tâche. Dans mon exemple à 3h00 du matin tous les jours, juste après les sauvegardes.

modele02

Conseil : ce n'est pas à lié à Semaphore mais pensez à faire plusieurs lots de serveurs avec des updates programmés de manière espacé. Ainsi en cas de mise à jour foireuse, cela permet de limiter la casse.

Les alertes mails ne vous sont adressées uniquement en cas d'un échec partiel (par exemple un hôte qui n'a pas répondu) ou total.

Vous devez configurer le compte mail dans /etc/semaphore/config.json. Exemple :

(...)
    "email_alert": true,
    "email_sender": "semaphore@domain.tld",
    "email_host": "smtp.domain.tld",
    "email_port": "587",
    "email_username": "semaphore@domain.tld",
    "email_password": "MOTDEPASSE",
    "email_secure": true,
(...)

Autorisez les alertes dans la paramètres du projet :

alerts

Enfin, cochez la case pour les utilisateurs concernés en cliquant en bas sur votre login puis "Utilisateurs".

Personnellement, j'ai adopté cette solution au travail après l'avoir testé quelques temps à la maison. Si je trouve le temps, je ferai d'autres articles avec cette fois-ci Windows et OPNSense comme hôtes cibles et voire un troisième article sur la configuration du SSO avec le protocole OpenID Connect. À noter que vous pouvez également faire du CI/CD avec Semaphore UI.

Article précédent