diff --git a/ansible/roles/portail/tasks/03-code.yml b/ansible/roles/portail/tasks/03-code.yml index 69a4acc..99e60be 100644 --- a/ansible/roles/portail/tasks/03-code.yml +++ b/ansible/roles/portail/tasks/03-code.yml @@ -122,6 +122,9 @@ - { cle: "LABS_DOSSIER", valeur: "/opt/labs" } no_log: true register: portail_env_mis_a_jour + # queue:work charge la configuration une seule fois au démarrage : sans + # redémarrage, il garderait l'ancien mot de passe après une rotation. + notify: redémarrer le worker de file - name: installer les dépendances JS (npm) ansible.builtin.command: diff --git a/docs/runbooks/compte-service-openstack.md b/docs/runbooks/compte-service-openstack.md new file mode 100644 index 0000000..7b34d0a --- /dev/null +++ b/docs/runbooks/compte-service-openstack.md @@ -0,0 +1,92 @@ +# Runbook — Compte de service OpenStack `paillasse-service` + +Compte utilisé par le portail pour tout ce qu'il demande à OpenStack (consoles +Nova, stacks Heat). Authentification par mot de passe, pas par application +credential : voir [ADR 0002](../adr/0002-mot-de-passe-pour-heat.md). + +## État attendu (à vérifier après toute intervention) + +| Point | Attendu | Vérification | +|---|---|---| +| Rôles | `member` sur le projet `paillasse`, rien d'autre (`reader` apparaît en effectif : rôle impliqué par `member`) | `openstack role assignment list --user paillasse-service --user-domain Default --names` (cloud `kolla-admin`) | +| Mot de passe | 32 octets aléatoires (`openssl rand -base64 32`, 44 caractères) | longueur seulement, jamais la valeur | +| Copie 1 (référence) | `/etc/kolla/clouds-paillasse.yaml`, `600 root:root` | `stat -c "%a %U:%G" ...` | +| Copie 2 (lue par PHP) | `/var/www/portail/.env` (`OS_PASSWORD`), `640 adam:www-data` | idem | + +Le mot de passe n'existe nulle part ailleurs : ni dans Git, ni sur le Mac, ni +dans un gestionnaire de mots de passe. Personne n'a besoin de le connaître. + +## Rotation + +Quand : si le secret a pu être exposé (fichier copié, sauvegarde mal chiffrée, +affichage accidentel), au départ d'une personne ayant eu un accès root, et +sinon une fois par an. + +Durée d'interruption : quelques secondes pour les nouvelles authentifications ; +aucune perte de données. Éviter un créneau de séance en cours. + +### 1. Sur le serveur : nouveau mot de passe dans Keystone et dans la référence + +``` +ssh paillasse +sudo -i +export PATH=/opt/kolla-venv/bin:$PATH +export OS_CLIENT_CONFIG_FILE=/etc/kolla/clouds.yaml OS_CLOUD=kolla-admin + +NOUVEAU=$(openssl rand -base64 32) +openstack user set --password "$NOUVEAU" paillasse-service +sed -i "s|^\(\s*password:\s*\).*|\1\"$NOUVEAU\"|" /etc/kolla/clouds-paillasse.yaml +unset NOUVEAU +chmod 600 /etc/kolla/clouds-paillasse.yaml +``` + +Ne pas exporter `OS_PROJECT_NAME=paillasse` ici : le compte `admin` n'a pas +de rôle sur ce projet (`401`). Le mot de passe passe brièvement en argument +de commande (visible par `ps` pendant l'appel) : risque accepté, le serveur n'a +pas d'autre utilisateur interactif. + +Vérifier que la référence fonctionne : + +``` +OS_CLIENT_CONFIG_FILE=/etc/kolla/clouds-paillasse.yaml OS_CLOUD=paillasse-service \ + openstack token issue -f value -c project_id +``` + +### 2. Depuis le Mac : reporter dans le portail + +``` +cd ansible && script -q /dev/null ansible-playbook portail.yml -i inventory.ini +``` + +Le rôle relit `clouds-paillasse.yaml`, met à jour `OS_PASSWORD` dans `.env`, +régénère le cache de configuration et redémarre le worker de file. + +### 3. Sur le serveur : oublier le jeton Keystone en cache + +Le portail garde son jeton Keystone en cache 50 minutes. Que Keystone révoque +ou non les jetons existants au changement de mot de passe (non vérifié sur ce +serveur), le forcer à se réauthentifier tout de suite permet de constater +une erreur maintenant plutôt que 50 minutes plus tard : + +``` +cd /var/www/portail +sudo -u www-data HOME=/tmp php8.3 artisan cache:forget openstack.authentification +``` + +### 4. Vérifier + +``` +sudo -u www-data HOME=/tmp php8.3 artisan tinker \ + --execute="echo strlen(app(App\Services\OpenStack\KeystoneAuth::class)->jeton()) > 0 ? 'ok' : 'echec';" +``` + +Puis ouvrir une console de lab ou admettre un élève de test. + +## En cas d'échec à mi-chemin + +Si Keystone a le nouveau mot de passe mais pas le portail (étape 2 ratée) : les +consoles et créations de stack échouent avec `Authentification OpenStack +refusée`. Relancer l'étape 2 ; `clouds-paillasse.yaml` fait foi. + +Si `clouds-paillasse.yaml` n'a pas été mis à jour (étape 1 interrompue après +`user set`) : refaire toute l'étape 1 avec un nouveau mot de passe.