chore: update and add playbook haproxy
This commit is contained in:
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
# Les ports 80/443 sont publiés par Docker (docker-compose du conteneur waf), donc
|
||||||
|
# UFW seul ne suffit pas : Docker insère ses propres règles NAT/FORWARD directement
|
||||||
|
# dans iptables et les contourne. On filtre donc dans la chaîne DOCKER-USER, seul
|
||||||
|
# point garanti d'être évalué avant les règles de Docker.
|
||||||
|
#
|
||||||
|
# Résultat : seul le load-balancer (IP VPN) peut atteindre 80/443 sur ces hôtes,
|
||||||
|
# tout le reste d'internet est bloqué. SSH et le reste du trafic ne sont pas touchés.
|
||||||
|
|
||||||
|
- name: Restreindre l'accès HTTP/HTTPS des serveurs applicatifs au load-balancer
|
||||||
|
hosts: prod:replica-prod
|
||||||
|
become: true
|
||||||
|
gather_facts: false
|
||||||
|
|
||||||
|
vars:
|
||||||
|
lb_vpn_ip: "{{ hostvars['load-balancer']['vpn_ip'] }}"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Installer iptables-persistent
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: iptables-persistent
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: Bloquer les connexions 80/443 non issues du load-balancer
|
||||||
|
ansible.builtin.iptables:
|
||||||
|
chain: DOCKER-USER
|
||||||
|
protocol: tcp
|
||||||
|
match: multiport
|
||||||
|
destination_ports: "80,443"
|
||||||
|
jump: DROP
|
||||||
|
action: insert
|
||||||
|
comment: "app-firewall: bloque 80/443 hors load-balancer"
|
||||||
|
|
||||||
|
- name: Autoriser les connexions 80/443 depuis le load-balancer (VPN)
|
||||||
|
ansible.builtin.iptables:
|
||||||
|
chain: DOCKER-USER
|
||||||
|
protocol: tcp
|
||||||
|
source: "{{ lb_vpn_ip }}/32"
|
||||||
|
match: multiport
|
||||||
|
destination_ports: "80,443"
|
||||||
|
jump: RETURN
|
||||||
|
action: insert
|
||||||
|
comment: "app-firewall: autorise 80/443 depuis le load-balancer"
|
||||||
|
|
||||||
|
- name: Sauvegarder les règles iptables (persistance au reboot)
|
||||||
|
ansible.builtin.command: netfilter-persistent save
|
||||||
|
changed_when: false
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
---
|
||||||
|
# Le certificat mln-uber.club n'est pas généré ici : il existe déjà sur prod-uber
|
||||||
|
# (utilisé par le conteneur waf du docker-compose). On le récupère et on le copie
|
||||||
|
# vers le load-balancer. Relancer ce playbook après chaque renouvellement du cert
|
||||||
|
# sur prod-uber pour resynchroniser HAProxy.
|
||||||
|
|
||||||
|
- name: Récupérer le certificat mln-uber.club depuis prod-uber
|
||||||
|
hosts: prod-uber
|
||||||
|
become: true
|
||||||
|
gather_facts: false
|
||||||
|
|
||||||
|
vars:
|
||||||
|
# À CONFIRMER : chemin réel du cert sur prod-uber (aucun playbook ne le dépose
|
||||||
|
# actuellement à cet endroit — à ajuster si différent).
|
||||||
|
app_cert_dir: "{{ docker_dir }}/certs"
|
||||||
|
local_cert_sync_dir: /tmp/mln-uber-cert-sync
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Créer le dossier temporaire local de synchronisation
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ local_cert_sync_dir }}"
|
||||||
|
state: directory
|
||||||
|
mode: "0700"
|
||||||
|
delegate_to: localhost
|
||||||
|
become: false
|
||||||
|
|
||||||
|
- name: Rapatrier fullchain.pem et privkey.pem
|
||||||
|
ansible.builtin.fetch:
|
||||||
|
src: "{{ app_cert_dir }}/{{ item }}"
|
||||||
|
dest: "{{ local_cert_sync_dir }}/{{ item }}"
|
||||||
|
flat: true
|
||||||
|
loop:
|
||||||
|
- fullchain.pem
|
||||||
|
- privkey.pem
|
||||||
|
|
||||||
|
- name: Restreindre les permissions locales de la clé privée
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ local_cert_sync_dir }}/privkey.pem"
|
||||||
|
mode: "0600"
|
||||||
|
delegate_to: localhost
|
||||||
|
become: false
|
||||||
|
|
||||||
|
- name: Déploiement HAProxy (load-balancer)
|
||||||
|
hosts: load-balancer
|
||||||
|
become: true
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
vars:
|
||||||
|
haproxy_cert_dir: /etc/haproxy/certs
|
||||||
|
haproxy_cert_path: "{{ haproxy_cert_dir }}/{{ domain_name }}.pem"
|
||||||
|
local_cert_sync_dir: /tmp/mln-uber-cert-sync
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Installer HAProxy
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: haproxy
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: Créer le dossier des certificats HAProxy
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ haproxy_cert_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0750"
|
||||||
|
|
||||||
|
- name: Copier fullchain.pem et privkey.pem sur le load-balancer
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ local_cert_sync_dir }}/{{ item }}"
|
||||||
|
dest: "{{ haproxy_cert_dir }}/{{ item }}"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0640"
|
||||||
|
loop:
|
||||||
|
- fullchain.pem
|
||||||
|
- privkey.pem
|
||||||
|
notify: reload haproxy
|
||||||
|
|
||||||
|
- name: Construire le certificat combiné pour HAProxy (fullchain + privkey)
|
||||||
|
ansible.builtin.shell: >
|
||||||
|
cat {{ haproxy_cert_dir }}/fullchain.pem
|
||||||
|
{{ haproxy_cert_dir }}/privkey.pem
|
||||||
|
> {{ haproxy_cert_path }}
|
||||||
|
notify: reload haproxy
|
||||||
|
|
||||||
|
- name: Restreindre les permissions du certificat combiné
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ haproxy_cert_path }}"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0640"
|
||||||
|
|
||||||
|
- name: Ouvrir le port HTTPS dans UFW
|
||||||
|
ansible.builtin.ufw:
|
||||||
|
rule: allow
|
||||||
|
port: "443"
|
||||||
|
proto: tcp
|
||||||
|
|
||||||
|
- name: Déployer la configuration HAProxy
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/haproxy.cfg.j2
|
||||||
|
dest: /etc/haproxy/haproxy.cfg
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
validate: haproxy -c -f %s
|
||||||
|
notify: reload haproxy
|
||||||
|
|
||||||
|
- name: Démarrer et activer HAProxy
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: haproxy
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
|
||||||
|
- name: Nettoyer les fichiers temporaires locaux
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ local_cert_sync_dir }}"
|
||||||
|
state: absent
|
||||||
|
delegate_to: localhost
|
||||||
|
become: false
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- name: reload haproxy
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: haproxy
|
||||||
|
state: reloaded
|
||||||
+1
-1
@@ -23,7 +23,7 @@ s3-uber ansible_host=80.96.58.164 ansible_user=omnex ansible_ssh_private_key_fil
|
|||||||
vpn-uber ansible_host=131.123.42.158 ansible_user=omnex ansible_ssh_private_key_file=../.ssh/omnex vpn_ip=10.0.0.1
|
vpn-uber ansible_host=131.123.42.158 ansible_user=omnex ansible_ssh_private_key_file=../.ssh/omnex vpn_ip=10.0.0.1
|
||||||
|
|
||||||
[load-balancer]
|
[load-balancer]
|
||||||
load-balancer ansible_host=93.185.166.221 ansible_user=omnex ansible_ssh_private_key_file=../.ssh/omnex
|
load-balancer ansible_host=93.185.166.221 ansible_user=omnex ansible_ssh_private_key_file=../.ssh/omnex vpn_ip=10.0.0.12
|
||||||
|
|
||||||
[infra]
|
[infra]
|
||||||
monitoring-uber ansible_host=185.103.167.138 ansible_user=omnex ansible_ssh_private_key_file=../.ssh/omnex vpn_ip=10.0.0.2
|
monitoring-uber ansible_host=185.103.167.138 ansible_user=omnex ansible_ssh_private_key_file=../.ssh/omnex vpn_ip=10.0.0.2
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Domaine servi par le load-balancer HAProxy — utilisé par infra/playbook-haproxy.yml
|
||||||
|
# pour nommer le certificat combiné. Doit correspondre au nom codé en dur dans
|
||||||
|
# templates/haproxy.cfg.j2 (bind *:443 ssl crt /etc/haproxy/certs/mln-uber.club.pem).
|
||||||
|
# Le certificat lui-même n'est pas généré ici : il est copié depuis prod-uber
|
||||||
|
# (voir infra/playbook-haproxy.yml, play "Récupérer le certificat...").
|
||||||
|
domain_name: "mln-uber.club"
|
||||||
Reference in New Issue
Block a user