fix 004
This commit is contained in:
1 parent
05141e6ec2
commit
b307a35eb4
9 files changed
+46
-32
No files matched your search
@@ -39,17 +39,14 @@ jobs:
|
||||
- name: Passer ansible-lint
|
||||
run: ansible-lint
|
||||
|
||||
- name: Vérifier que chaque compte SSH a au moins une clé
|
||||
- name: Vérifier que les clés déclarées dans ssh_users existent
|
||||
run: |
|
||||
set -euo pipefail
|
||||
manquants=0
|
||||
for d in files/keys/*/; do
|
||||
[ -d "$d" ] || continue
|
||||
n=$(find "$d" -name '*.pub' | wc -l)
|
||||
echo "$(basename "$d") : $n clé(s)"
|
||||
[ "$n" -gt 0 ] || manquants=1
|
||||
for f in $(grep -oE 'keys: \[[^]]*\]' group_vars/all/main.yml | tr -d '[]' | sed 's/keys: //; s/,/ /g'); do
|
||||
if [ -f "files/keys/$f" ]; then echo "files/keys/$f : ok"; else echo "files/keys/$f : ABSENT"; manquants=1; fi
|
||||
done
|
||||
[ "$manquants" -eq 0 ] || { echo "Un répertoire de files/keys/ est vide"; exit 1; }
|
||||
[ "$manquants" -eq 0 ]
|
||||
|
||||
promouvoir:
|
||||
# Semaphore suit la branche « valide » : elle n'avance que depuis « main », après contrôle réussi.
|
||||
|
||||
@@ -55,7 +55,7 @@ inventaire et vault versionnés, collections déclarées dans `collections/`.
|
||||
│ ├── main.yml # réseaux, DNS, proxy, comptes, supervision, activation des rôles
|
||||
│ └── vault.yml.example # à copier vers vault.yml, chiffrer, puis versionner
|
||||
├── files/
|
||||
│ ├── keys/<utilisateur>/*.pub # clés publiques SSH (versionnées)
|
||||
│ ├── keys/*.pub # clés publiques SSH, attribuées par ssh_users[].keys
|
||||
│ └── ca/*.crt # certificats racine internes (versionnés)
|
||||
├── roles/ # common, proxy, dns, updates, ssh, firewall, fail2ban,
|
||||
│ # os_hardening, snmp, nrpe, glpi_agent
|
||||
@@ -68,8 +68,9 @@ inventaire et vault versionnés, collections déclarées dans `collections/`.
|
||||
1. **Inventaire** : renseigner `inventory/hosts.yml`. Deux modes de connexion :
|
||||
- compte de service `ansible` + sudo (`become` est activé dans `ansible.cfg`) ;
|
||||
- root par clé, comme sur les VM Terraform : `ansible_user: root`, `become` est alors sans effet.
|
||||
2. **Clés publiques** : un répertoire par compte dans `files/keys/`, un ou plusieurs
|
||||
fichiers `*.pub` dedans. Le compte utilisé par Ansible **doit** y avoir une clé.
|
||||
2. **Clés publiques** : fichiers `*.pub` à plat dans `files/keys/`, attribués aux comptes
|
||||
par `ssh_users[].keys` dans `group_vars/all/main.yml`. Le compte utilisé par Ansible
|
||||
(root) **doit** y avoir la clé de Semaphore.
|
||||
3. **Certificat racine** (facultatif) : `files/ca/root-ca.crt` au format PEM.
|
||||
4. **Secrets** : `cp group_vars/all/vault.yml.example group_vars/all/vault.yml`,
|
||||
renseigner, puis `ansible-vault encrypt group_vars/all/vault.yml`.
|
||||
|
||||
+11
-9
@@ -1,16 +1,18 @@
|
||||
# Clés publiques SSH
|
||||
|
||||
Un sous-répertoire par utilisateur, contenant une ou plusieurs clés au format
|
||||
OpenSSH (`*.pub`) :
|
||||
Fichiers `*.pub` au format OpenSSH, déposés à plat (comme `cles/` du dépôt Terraform) :
|
||||
|
||||
files/keys/root/hcornet.pub
|
||||
files/keys/root/ansible.pub
|
||||
files/keys/ansible/ansible.pub
|
||||
files/keys/hcornet/hcornet.pub
|
||||
files/keys/hcornet.pub
|
||||
files/keys/ansible.pub # clé de Semaphore
|
||||
|
||||
Le rôle `ssh` concatène les fichiers `*.pub` du répertoire portant le nom de
|
||||
l'utilisateur et remplace intégralement le fichier de clés autorisées : une clé
|
||||
retirée d'ici est retirée du serveur au passage suivant.
|
||||
L'attribution aux comptes se fait dans `group_vars/all/main.yml` :
|
||||
|
||||
ssh_users:
|
||||
- name: root
|
||||
keys: [hcornet.pub, ansible.pub]
|
||||
|
||||
Le rôle `ssh` remplace intégralement le fichier de clés autorisées :
|
||||
une clé retirée d'ici est retirée du serveur au passage suivant.
|
||||
|
||||
Les clés publiques sont versionnées : Semaphore clone le dépôt et doit les trouver.
|
||||
Une clé publique n'est pas un secret ; ne jamais déposer de clé privée ici.
|
||||
@@ -0,0 +1 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINrHwV6BNYMsMBfNCEk23pIAx2FFLCA7f5lbhpEYT7/c semaphore@tips-of-mine
|
||||
@@ -0,0 +1 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFDIXkfS5dM3po9Jz7NKgd3t1H4vqh0/cVoxrAP42ivd thedj@ZEU
|
||||
@@ -24,16 +24,16 @@ dns_nameservers:
|
||||
- 10.78.56.8
|
||||
- 10.78.56.9
|
||||
dns_search_domains:
|
||||
- fr.dgs.group
|
||||
- tips-of-mine.local
|
||||
|
||||
# ----------------------------------------------------------------- proxy ----
|
||||
# Laisser vide pour ne configurer aucun proxy.
|
||||
proxy_url: ""
|
||||
# proxy_url: "http://serv-proxy.fr.dgs.group:3128"
|
||||
# proxy_url: "http://serv-proxy.tips-of-mine.local:3128"
|
||||
proxy_no_proxy:
|
||||
- localhost
|
||||
- 127.0.0.1
|
||||
- .fr.dgs.group
|
||||
- .tips-of-mine.local
|
||||
|
||||
# ------------------------------------------------------------------- SSH ----
|
||||
# Les clés publiques sont lues dans files/keys/<utilisateur>/*.pub.
|
||||
@@ -46,7 +46,7 @@ ssh_users:
|
||||
- name: hcornet
|
||||
groups: [sudo_or_wheel]
|
||||
|
||||
ssh_banner_organisation: "Tapis-Saint-Maclou"
|
||||
ssh_banner_organisation: "Tips-Of-Mine"
|
||||
# Logo ASCII repris de 01-ssh/banner, dans un fichier pour éviter tout souci d'indentation YAML.
|
||||
ssh_banner_logo: "{{ lookup('ansible.builtin.file', playbook_dir ~ '/files/banner-logo.txt') }}"
|
||||
|
||||
@@ -57,7 +57,7 @@ snmp_communities:
|
||||
|
||||
nrpe_allowed_hosts: "{{ supervision_sources }}"
|
||||
|
||||
glpi_agent_server: "https://glpi.fr.dgs.group/marketplace/glpiinventory/"
|
||||
glpi_agent_server: "https://glpi.tips-of-mine.fr/marketplace/glpiinventory/"
|
||||
glpi_agent_tag: "ServeurProd"
|
||||
|
||||
# ------------------------------------------------------------- activation ----
|
||||
|
||||
@@ -12,10 +12,10 @@ ssh_port: 22
|
||||
# connecte en root) ; le mot de passe root reste utilisable sur la console.
|
||||
ssh_permit_root_login: prohibit-password
|
||||
|
||||
# Comptes autorisés en SSH. Chaque entrée : name (obligatoire), groups (liste,
|
||||
# « sudo_or_wheel » est traduit selon l'OS), sudo_nopasswd (bool), shell,
|
||||
# password_hash (optionnel, pour un mot de passe local — jamais en clair).
|
||||
# Les clés publiques sont lues dans files/keys/<name>/*.pub.
|
||||
# Comptes autorisés en SSH. Chaque entrée : name (obligatoire), keys (liste de
|
||||
# fichiers .pub pris dans files/keys/), groups (liste, « sudo_or_wheel » est
|
||||
# traduit selon l'OS), sudo_nopasswd (bool), shell, password_hash (optionnel,
|
||||
# pour un mot de passe local — jamais en clair).
|
||||
ssh_users:
|
||||
- name: root
|
||||
|
||||
|
||||
@@ -1,14 +1,26 @@
|
||||
---
|
||||
- name: Recenser les clés publiques disponibles par compte
|
||||
- name: Recenser les clés publiques de chaque compte
|
||||
# Fichiers listés dans « keys », à plat dans files/keys/ (comme cles/ du dépôt Terraform).
|
||||
ansible.builtin.set_fact:
|
||||
ssh_users_keys: >-
|
||||
{{ ssh_users_keys | default({}) | combine({
|
||||
item.name: lookup('ansible.builtin.fileglob', ssh_keys_dir ~ '/' ~ item.name ~ '/*.pub', wantlist=True)
|
||||
item.name: item['keys'] | default([]) | map('regex_replace', '^', ssh_keys_dir ~ '/') | list
|
||||
}) }}
|
||||
loop: "{{ ssh_users }}"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
|
||||
- name: Vérifier que les fichiers de clés déclarés existent
|
||||
ansible.builtin.stat:
|
||||
path: "{{ item }}"
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
loop: "{{ ssh_users_keys.values() | flatten | unique }}"
|
||||
loop_control:
|
||||
label: "{{ item | basename }}"
|
||||
register: ssh_keys_stat
|
||||
failed_when: not ssh_keys_stat.stat.exists
|
||||
|
||||
- name: Calculer la liste AllowUsers
|
||||
ansible.builtin.set_fact:
|
||||
ssh_allow_users_effective: "{{ ssh_users | map(attribute='name') | list }}"
|
||||
@@ -23,7 +35,7 @@
|
||||
- not (ssh_ansible_login == 'root' and ssh_permit_root_login == 'no')
|
||||
fail_msg: >-
|
||||
Le compte de connexion Ansible « {{ ssh_ansible_login }} » doit figurer dans ssh_users
|
||||
avec au moins une clé dans {{ ssh_keys_dir }}/{{ ssh_ansible_login }}/*.pub,
|
||||
avec au moins un fichier dans sa liste « keys » (présent dans {{ ssh_keys_dir }}/),
|
||||
et ssh_permit_root_login ne peut pas valoir « no » si Ansible se connecte en root.
|
||||
vars:
|
||||
ssh_ansible_login: "{{ ansible_user | default('root') }}"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# {{ ansible_managed }}
|
||||
# Source : files/keys/{{ item.name }}/*.pub
|
||||
# Source : {{ ssh_users_keys[item.name] | map("basename") | sort | join(", ") }}
|
||||
{% for key_file in ssh_users_keys[item.name] | sort %}
|
||||
{{ lookup('ansible.builtin.file', key_file) | trim }}
|
||||
{% endfor %}
|
||||
Reference in new issue
Block a user