start
This commit is contained in:
1 parent
4b8bb1427a
commit
975d3e9d1d
84 files changed
+2507
-351
No files matched your search
@@ -1,75 +1,125 @@
|
||||
# ${REPO_NAME}
|
||||
# ansible-hardening-linux
|
||||
|
||||
${REPO_DESCRIPTION}
|
||||
Configuration et durcissement de serveurs Linux — Debian 12/13, Ubuntu 22.04/24.04,
|
||||
RHEL / Rocky / AlmaLinux 8 et 9 — par Ansible. Reprise du dépôt de scripts
|
||||
`prerequis-install-deb` (Debian uniquement, copie de fichiers à la main) sous
|
||||
forme de rôles idempotents, multi-distributions, avec CI/CD Gitea.
|
||||
|
||||
# A propos de
|
||||
Objectif : à la fin d'un passage, tout serveur est configuré, à jour, supervisé,
|
||||
et **n'est joignable à distance qu'en SSH par clé publique** ; l'accès local
|
||||
(console, `su -`) continue de fonctionner comme avant.
|
||||
|
||||
# Prérequis
|
||||
## Correspondance avec les scripts d'origine
|
||||
|
||||
Vous avez besoin d'une installation Ansible fonctionnelle sur votre machine.
|
||||
| Script d'origine | Rôle | Ce qui change |
|
||||
|---|---|---|
|
||||
| `01-ssh` (sshd_config, ssh_config, banner, authorized_keys, 00-basic) | `ssh` | Drop-in `sshd_config.d/00-durcissement.conf` au lieu d'écraser tout le fichier ; clé publique obligatoire (`AuthenticationMethods publickey`) ; `AllowUsers` calculé depuis la liste des comptes ; clés centralisées dans `/etc/ssh/authorized_keys/<user>` (le lien symbolique de l'ancien script est remplacé par des fichiers appartenant à root) ; bannière dans `/etc/issue.net` et `/etc/issue` ; MOTD `00-basic` conservé, rendu portable, et équivalent `profile.d` sous Red Hat ; vérification d'une **nouvelle** connexion SSH avant de rendre la main |
|
||||
| `02-apt` (proxy + full-upgrade) | `proxy`, `updates` | Proxy APT **et** DNF, plus `profile.d` ; mises à jour de sécurité automatiques (`unattended-upgrades` / `dnf-automatic`) ; signalement du besoin de redémarrage |
|
||||
| `04-agent-glpi` | `glpi_agent` (+ `common` pour le certificat) | Installateur perl officiel, version pilotée par variable, configuration dans `conf.d/10-ansible.cfg` ; le certificat racine va dans le magasin système (`update-ca-certificates` / `update-ca-trust`) et sert à tout le monde, pas seulement à l'agent |
|
||||
| `06-snmp` | `snmp` | Communautés v2c par source de supervision, lues depuis le vault ; SNMPv3 disponible ; vue en lecture seule |
|
||||
| `07-DNS` | `dns` | Respecte le gestionnaire réel : `systemd-resolved` (drop-in), NetworkManager (`dns=none` puis `resolv.conf`), ou `resolv.conf` direct |
|
||||
| `08-NRPE` | `nrpe` | Installation **et** configuration : `allowed_hosts`, `dont_blame_nrpe=0`, commandes de base |
|
||||
| `03-cortex`, `05-manageengine` | — | Ignorés à la demande |
|
||||
| *(absent)* | `firewall` | nftables (Debian/Ubuntu) ou firewalld (Red Hat), politique `drop` : SSH depuis les réseaux d'administration, ICMP, SNMP/NRPE depuis la supervision |
|
||||
| *(absent)* | `fail2ban` | Bannissement des sources en échec sur SSH, backend `systemd` |
|
||||
| *(absent)* | `os_hardening` | sysctl, core dumps, `login.defs`, auditd, services et paquets inutiles |
|
||||
| *(absent)* | `common` | Contrôle de la distribution, paquets de base, fuseau, certificats racine |
|
||||
|
||||
~~~bash
|
||||
./install-ansible.sh
|
||||
~~~
|
||||
## Ce qui garantit que l'accès local reste possible
|
||||
|
||||
## Edition du fichier Hosts
|
||||
~~~bash
|
||||
sudo nano /etc/ansible/hosts
|
||||
~~~
|
||||
- Aucun mot de passe n'est verrouillé, aucun compte n'est désactivé, PAM n'est pas modifié.
|
||||
- `PermitRootLogin prohibit-password` : root n'est joignable à distance que par clé,
|
||||
mais son mot de passe reste valable sur la console (Proxmox, KVM, iLO…) et pour `su -`.
|
||||
- Le pare-feu ne filtre que le réseau ; la console n'est pas concernée.
|
||||
- fail2ban ne bannit que des adresses IP distantes ; les réseaux d'administration sont
|
||||
dans `ignoreip`.
|
||||
- Deux garde-fous contre l'auto-verrouillage : le rôle `ssh` refuse une configuration
|
||||
où le compte utilisé par Ansible n'aurait pas de clé ou ne serait pas dans `AllowUsers`,
|
||||
et le rôle `firewall` refuse une liste `firewall_ssh_sources` qui exclurait l'adresse
|
||||
depuis laquelle Ansible est connecté. Après chaque redémarrage de sshd et après
|
||||
chaque application du pare-feu, une **nouvelle** session SSH est ouverte depuis le
|
||||
contrôleur ; si elle échoue, le playbook s'arrête sans fermer la session courante.
|
||||
|
||||
## Creation clé SSH
|
||||
~~~bash
|
||||
ssh-keygen -t ed25519 -C "ansible"
|
||||
~~~
|
||||
## Arborescence
|
||||
|
||||
## Permissions clé SSH
|
||||
~~~bash
|
||||
chmod 600 ~/.ssh/ansible
|
||||
~~~
|
||||
Même organisation qu'`ansible-centreon` : playbook et `group_vars` à la racine,
|
||||
inventaire et vault versionnés, collections déclarées dans `collections/`.
|
||||
|
||||
## Ping Command Ansible
|
||||
~~~bash
|
||||
ansible all -m ping
|
||||
~~~
|
||||
```
|
||||
.
|
||||
├── ansible.cfg
|
||||
├── site.yml # point d'entrée
|
||||
├── collections/requirements.yml # ansible.posix, community.general (installées par Semaphore)
|
||||
├── inventory/hosts.yml # inventaire versionné
|
||||
├── group_vars/all/
|
||||
│ ├── 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)
|
||||
│ └── ca/*.crt # certificats racine internes (versionnés)
|
||||
├── roles/ # common, proxy, dns, updates, ssh, firewall, fail2ban,
|
||||
│ # os_hardening, snmp, nrpe, glpi_agent
|
||||
├── .gitea/workflows/ansible-lint.yml
|
||||
└── CICD.md # chaîne Gitea (contrôle) -> Semaphore (exécution)
|
||||
```
|
||||
|
||||
## Copier clé SSH
|
||||
~~~bash
|
||||
ssh-copy-id -i ~/.ssh/ansible.pub 10.0.4.150
|
||||
~~~
|
||||
## Mise en route
|
||||
|
||||
## Ping Command Ansible avec nouvelle clé SSH
|
||||
~~~bash
|
||||
ansible all -m ping --key-file ~/.ssh/ansible
|
||||
~~~
|
||||
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é.
|
||||
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`.
|
||||
5. **Variables** : relire `group_vars/all/main.yml` — en particulier
|
||||
`firewall_ssh_sources` (réseaux d'administration), `supervision_sources`,
|
||||
`dns_nameservers`, `proxy_url`, `ssh_users`, `glpi_agent_server`.
|
||||
6. **Simulation** : `ansible-playbook site.yml --check --diff --ask-vault-pass`
|
||||
7. **Application** : `ansible-playbook site.yml --ask-vault-pass`
|
||||
|
||||
# Démarrage
|
||||
Un seul rôle : `--tags ssh`, `--tags firewall`, etc. Un rôle peut aussi être
|
||||
désactivé par variable (`enable_<rôle>: false`) au niveau global, d'un groupe ou d'un hôte.
|
||||
|
||||
~~~bash
|
||||
git clone https://gitea.tips-of-mine.com${REPO_LINK}.git
|
||||
cd ${REPO_NAME}
|
||||
~~~
|
||||
## Ordre d'exécution et raison
|
||||
|
||||
## Personnalisation
|
||||
`common` → `proxy` → `dns` → `updates` → `ssh` → `firewall` → `fail2ban` →
|
||||
`os_hardening` → `snmp` → `nrpe` → `glpi_agent`.
|
||||
|
||||
Le fichier .env pour les variable d'environnement
|
||||
~~~bash
|
||||
nano .env
|
||||
~~~
|
||||
Le proxy et le DNS viennent d'abord (sans eux, aucun paquet ne se télécharge) ; le SSH
|
||||
est durci avant le pare-feu (la règle SSH doit exister avant que la politique passe à
|
||||
`drop`) ; la supervision et l'agent GLPI viennent en dernier, une fois le système stable.
|
||||
|
||||
Modification des labels pour traefik
|
||||
~~~bash
|
||||
nano docker-compose.yml
|
||||
~~~
|
||||
## Points d'attention par distribution
|
||||
|
||||
## Lancement
|
||||
- **Ubuntu 22.10+** : sshd est activé par socket (`ssh.socket`). Le rôle bascule sur
|
||||
`ssh.service` pour que `Port` soit pris en compte depuis `sshd_config`.
|
||||
- **Red Hat / Rocky / Alma** : les algorithmes SSH ne sont pas définis dans `sshd_config`
|
||||
(ils viennent de `crypto-policies`) ; fail2ban, NRPE et les greffons Nagios viennent
|
||||
d'EPEL, installé par `common`. SELinux : le port SSH est déclaré si différent de 22.
|
||||
- **Red Hat 8 (OpenSSH 8.0)** : pas de directive `Include` ; le durcissement est inséré
|
||||
en tête de `sshd_config` entre des marqueurs, et les directives contradictoires du
|
||||
fichier d'origine sont commentées.
|
||||
- **VM issues de `terraform-proxmox-serveur-debian-12`** : le jeu nftables et le drop-in
|
||||
sshd sont compatibles avec ceux posés par cloud-init (même structure, même
|
||||
répertoire `/etc/nftables.d/`). Le drop-in Ansible `00-durcissement.conf` passe avant
|
||||
`99-durcissement.conf` de cloud-init : c'est Ansible qui a le dernier mot.
|
||||
|
||||
~~~bash
|
||||
docker compose up -d
|
||||
~~~
|
||||
## CI/CD
|
||||
|
||||
~~~bash
|
||||
docker compose logs -f
|
||||
~~~
|
||||
Voir `CICD.md` : Gitea contrôle le code, Semaphore l'exécute depuis la branche `valide`.
|
||||
|
||||
# Buy me a coffe
|
||||
<a href='https://ko-fi.com/R5R2KNI3N' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi4.png?v=3' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
|
||||
## Vérifications après un premier passage
|
||||
|
||||
```bash
|
||||
# Depuis le contrôleur : nouvelle session, clé uniquement
|
||||
ssh -o BatchMode=yes -o ControlPath=none ansible@<hôte> 'sudo sshd -T | grep -Ei "^(permitrootlogin|passwordauthentication|authenticationmethods|allowusers)"'
|
||||
|
||||
# Pare-feu : seuls SSH, ICMP et les ports de supervision sont ouverts
|
||||
ssh ansible@<hôte> 'sudo nft list chain inet filter input' # Debian/Ubuntu
|
||||
ssh ansible@<hôte> 'sudo firewall-cmd --list-all' # Red Hat
|
||||
|
||||
# fail2ban actif sur sshd
|
||||
ssh ansible@<hôte> 'sudo fail2ban-client status sshd'
|
||||
```
|
||||
Reference in new issue
Block a user