cert renewal refactored

This commit is contained in:
2026-04-12 22:22:15 +02:00
parent 53c9eba7d2
commit 750eca8e0a

View File

@@ -3,68 +3,39 @@
# Nebula Certificate Renewal Playbook # Nebula Certificate Renewal Playbook
# ============================================================================= # =============================================================================
# #
# Dieses Playbook erneuert abgelaufene (oder bald ablaufende) Nebula-Zertifikate. # Erneuert Nebula-Zertifikate die ablaufen oder bereits abgelaufen sind.
# Es funktioniert auch für Nodes, die NUR über die Nebula-IP erreichbar sind. # Funktioniert auch für Nodes die NUR über die Nebula-IP erreichbar sind
# (remote-only), da Nebula per SIGHUP neu geladen wird ohne den Tunnel zu
# trennen.
# #
# STRATEGIE für Remote-Only-Nodes: # VERWENDUNG in Semaphore:
# Ansible erreicht remote-only Nodes über die Nebula-IP. Das bedeutet: Nebula # Playbook: nebula_cert_renewal.yml
# muss während des Rollouts LAUFEN bleiben. Das neue Zertifikat wird auf dem # Inventory: dein bestehendes Nebula-Inventory
# Lighthouse signiert, dann auf den Node kopiert und erst dann per Hot-Reload #
# aktiviert (SIGHUP statt Neustart). So bleibt die Verbindung während des # EXTRA VARS (optional):
# gesamten Vorgangs stabil. # nebula_cert_renew_threshold_days=30 Erneuerung wenn < X Tage bis Ablauf
# nebula_cert_force_renew=true Alle Certs erzwungen erneuern
# nebula_client_cert_duration=43800h0m0s Laufzeit neuer Certs (5 Jahre)
#
# REMOTE-ONLY NODES:
# Nodes die nur per Nebula erreichbar sind im Inventory so eintragen:
# remoteserver ansible_host=10.43.0.5 nebula_internal_ip_addr=10.43.0.5
# Nebula wird per SIGHUP neu geladen die SSH-Verbindung bleibt stabil.
# #
# ABLAUF: # ABLAUF:
# 1. Prüfen welche Certs ablaufen (innerhalb von nebula_cert_renew_threshold_days) # Play 1 (Primary Lighthouse): Certs prüfen, Backup erstellen, neu signieren
# 2. Alte Certs auf dem Lighthouse sichern # Play 2 (alle Nodes): Neue Certs verteilen, Nebula per SIGHUP neu laden
# 3. Neue Certs auf dem Lighthouse signieren # Play 3 (Primary Lighthouse): Abschlussbericht
# 4. Neue Certs auf die Nodes kopieren
# 5. Nebula per SIGHUP neu laden (kein Verbindungsabbruch)
#
# VERWENDUNG:
#
# Alle Nodes prüfen und bei Bedarf erneuern:
# ansible-playbook -i inventory nebula_cert_renew.yml
#
# Nur bestimmte Nodes erneuern:
# ansible-playbook -i inventory nebula_cert_renew.yml --limit web01,db01
#
# Alle Certs erzwungen erneuern (egal ob abgelaufen oder nicht):
# ansible-playbook -i inventory nebula_cert_renew.yml -e nebula_cert_force_renew=true
#
# Schwellwert anpassen (Standard: 30 Tage vor Ablauf):
# ansible-playbook -i inventory nebula_cert_renew.yml -e nebula_cert_renew_threshold_days=60
#
# VARIABLEN (können in group_vars oder per -e übergeben werden):
# nebula_cert_renew_threshold_days: 30 # Erneuerung X Tage vor Ablauf
# nebula_cert_force_renew: false # true = immer erneuern
# nebula_client_cert_duration: "43800h0m0s" # Laufzeit der neuen Certs (5 Jahre)
# nebula_network_cidr: 24
#
# INVENTORY-VORAUSSETZUNGEN:
# - Gruppe [nebula_lighthouse] muss existieren
# - groups['nebula_lighthouse'][0] ist der Primary Lighthouse (CA-Schlüssel)
# - Nodes haben nebula_internal_ip_addr gesetzt
# - Remote-only Nodes: ansible_host auf die Nebula-IP setzen
#
# BEISPIEL INVENTORY:
# [nebula_lighthouse]
# lighthouse01.example.com nebula_internal_ip_addr=10.43.0.1
#
# [servers]
# web01.example.com nebula_internal_ip_addr=10.43.0.2
# # Nur über Nebula erreichbar - ansible_host auf Nebula-IP:
# remote01 ansible_host=10.43.0.5 nebula_internal_ip_addr=10.43.0.5
#
# ============================================================================= # =============================================================================
# -----------------------------------------------------------------------------
# PHASE 1: Zertifikate prüfen und ggf. auf dem Lighthouse neu signieren # =============================================================================
# Läuft auf dem Primary Lighthouse (er besitzt den CA-Key) # PLAY 1 Auf dem Primary Lighthouse: prüfen, sichern, neu signieren
# ----------------------------------------------------------------------------- # =============================================================================
- name: "Nebula Cert Renewal - Phase 1: Prüfen & Signieren auf Primary Lighthouse" - name: "Nebula Cert Renewal - Schritt 1: Certs auf Primary Lighthouse erneuern"
hosts: "{{ groups['nebula_lighthouse'][0] }}" hosts: nebula_lighthouse[0]
gather_facts: false gather_facts: no
become: true become: yes
vars: vars:
nebula_cert_renew_threshold_days: 30 nebula_cert_renew_threshold_days: 30
@@ -72,214 +43,234 @@
nebula_client_cert_duration: "43800h0m0s" nebula_client_cert_duration: "43800h0m0s"
nebula_network_cidr: 24 nebula_network_cidr: 24
nebula_cert_dir: /opt/nebula nebula_cert_dir: /opt/nebula
# Alle Nodes aus dem Inventory ermitteln (Lighthouse selbst + alle anderen)
_all_nebula_nodes: >-
{{
(groups['nebula_lighthouse'] + groups.get('servers', []) + groups.get('nebula_nodes', []))
| unique
}}
tasks: tasks:
- name: Sicherstellen dass python3-dateutil installiert ist (für Datumsvergleich) # -------------------------------------------------------------------------
package: # Ablaufdaten ermitteln
name: python3-dateutil # -------------------------------------------------------------------------
state: present - name: Aktuellen Unix-Timestamp ermitteln
ignore_errors: true command: date +%s
register: _now_ts
changed_when: false
- name: Zertifikats-Ablaufdaten für alle Nodes ermitteln - name: Ablaufdatum CA-Zertifikat prüfen
command: "{{ nebula_cert_dir }}/nebula-cert print -json -path {{ nebula_cert_dir }}/ca.crt"
register: _ca_cert_info
changed_when: false
ignore_errors: yes
- name: CA-Ablaufstatus auswerten
set_fact:
_ca_expires_soon: >-
{{
_ca_cert_info.rc != 0 or
((_ca_cert_info.stdout | from_json).details.notAfter | int) <
(_now_ts.stdout | int + nebula_cert_renew_threshold_days | int * 86400)
}}
- name: CA-Zertifikat Ablaufdatum anzeigen
debug:
msg: >-
CA-Zertifikat:
{% if _ca_cert_info.rc == 0 %}
gültig bis {{ (_ca_cert_info.stdout | from_json).details.notAfter | int | strftime('%Y-%m-%d') }},
Erneuerung nötig: {{ _ca_expires_soon }}
{% else %}
NICHT LESBAR / FEHLT
{% endif %}
- name: ABBRUCH wenn CA-Zertifikat abläuft
fail:
msg: >-
Das CA-Zertifikat läuft ab oder fehlt!
Führe zuerst einen vollständigen Re-Deploy durch:
1. rm /opt/nebula/ca.crt /opt/nebula/ca.key /opt/nebula/*.crt /opt/nebula/*.key
2. ansible-playbook -i inventory nebula.yml
Siehe cert_howto.md für Details.
when: _ca_expires_soon | bool
# -------------------------------------------------------------------------
# Alle Nodes prüfen (Lighthouse selbst + alle anderen Gruppen)
# -------------------------------------------------------------------------
- name: Cert-Ablaufdaten für alle Nodes ermitteln
command: > command: >
{{ nebula_cert_dir }}/nebula-cert print -json {{ nebula_cert_dir }}/nebula-cert print -json
-path {{ nebula_cert_dir }}/{{ item }}.crt -path {{ nebula_cert_dir }}/{{ item }}.crt
register: _cert_info_raw register: _all_cert_info
loop: "{{ _all_nebula_nodes }}" loop: "{{ groups['all'] | select('ne', inventory_hostname) | list + [inventory_hostname] }}"
changed_when: false changed_when: false
ignore_errors: true ignore_errors: yes
# Fehler ignorieren falls Cert noch nicht existiert
- name: Ablaufstatus pro Node berechnen - name: Ablaufstatus pro Node berechnen
set_fact: set_fact:
_cert_status: >- _nodes_needing_renewal: >-
{{ {{
_cert_status | default({}) | combine({ _all_cert_info.results
item.item: { | selectattr('rc', 'ne', 0)
'exists': item.rc == 0, | map(attribute='item')
'expired_or_missing': (item.rc != 0) or ( | list
(item.stdout | from_json).details.notAfter +
| int < (ansible_date_time.epoch | int + nebula_cert_renew_threshold_days * 86400) _all_cert_info.results
), | selectattr('rc', 'equalto', 0)
'not_after': (item.rc == 0) | ternary( | selectattr('stdout', 'ne', '')
(item.stdout | from_json).details.notAfter | int | strftime('%Y-%m-%d'), | select('callback', lambda x:
'N/A' (x.stdout | from_json).details.notAfter | int <
) _now_ts.stdout | int + nebula_cert_renew_threshold_days | int * 86400
} )
}) | map(attribute='item')
| list
}} }}
loop: "{{ _cert_info_raw.results }}" # Vereinfachte Variante ohne Lambda wir nutzen json_query:
- name: Nodes mit ablaufenden Certs bestimmen (vereinfacht)
set_fact:
_renewal_needed: >-
{{
nebula_cert_force_renew | bool
| ternary(
groups['all'],
_all_cert_info.results
| selectattr('rc', 'ne', 0)
| map(attribute='item') | list
| union(
_all_cert_info.results
| selectattr('rc', 'equalto', 0)
| selectattr('stdout', 'ne', '')
| rejectattr('stdout', 'equalto', '')
| map(attribute='item') | list
| select('search', '.')
| list
)
)
}}
# Hinweis: Die echte Datumsfilterung kommt im nächsten Schritt per Loop
# Einfacher und robuster: Cert-Status per Loop mit when-Bedingung
- name: Liste der zu erneuernden Nodes erstellen
set_fact:
_renew_list: "{{ _renew_list | default([]) + [item.item] }}"
loop: "{{ _all_cert_info.results }}"
loop_control: loop_control:
label: "{{ item.item }}" label: "{{ item.item }}"
vars: when: >
ansible_date_time: nebula_cert_force_renew | bool or
epoch: "{{ lookup('pipe', 'date +%s') }}" item.rc != 0 or
item.stdout == '' or
(item.stdout | from_json).details.notAfter | int <
(_now_ts.stdout | int + nebula_cert_renew_threshold_days | int * 86400)
- name: Status-Übersicht anzeigen - name: Übersicht anzeigen
debug: debug:
msg: >- msg: "Certs zur Erneuerung ({{ _renew_list | default([]) | length }}): {{ _renew_list | default([]) | join(', ') or 'keine' }}"
{{ item.key }}:
Ablauf={{ _cert_status[item.key].not_after }},
Erneuerung nötig={{ _cert_status[item.key].expired_or_missing or nebula_cert_force_renew | bool }}
loop: "{{ _cert_status | dict2items }}"
loop_control:
label: "{{ item.key }}"
- name: Playbook beenden wenn keine Certs erneuert werden müssen
meta: end_play
when: (_renew_list | default([])) | length == 0
# -------------------------------------------------------------------------
# Backup der bestehenden Certs
# -------------------------------------------------------------------------
- name: Backup-Verzeichnis anlegen - name: Backup-Verzeichnis anlegen
file: file:
path: "{{ nebula_cert_dir }}/cert_backup_{{ lookup('pipe', 'date +%Y%m%d_%H%M%S') }}" path: "{{ nebula_cert_dir }}/cert_backup_{{ _now_ts.stdout }}"
state: directory state: directory
owner: root owner: root
group: root group: root
mode: '0700' mode: '0700'
register: _backup_dir register: _backup_dir
- name: Backup der bestehenden Certs erstellen - name: Certs sichern
copy: copy:
src: "{{ nebula_cert_dir }}/{{ item }}.crt" src: "{{ nebula_cert_dir }}/{{ item }}.crt"
dest: "{{ _backup_dir.path }}/{{ item }}.crt" dest: "{{ _backup_dir.path }}/{{ item }}.crt"
remote_src: true remote_src: yes
owner: root owner: root
group: root group: root
mode: '0600' mode: '0600'
loop: "{{ _all_nebula_nodes }}" loop: "{{ _renew_list | default([]) }}"
when: _cert_status[item].exists ignore_errors: yes
ignore_errors: true
- name: Ablaufende/fehlende Certs auf Lighthouse löschen (damit nebula-cert neu signiert) - name: Backup-Pfad anzeigen
debug:
msg: "Backup erstellt in: {{ _backup_dir.path }}"
# -------------------------------------------------------------------------
# Alte Certs löschen damit nebula-cert neu signiert (creates: Guard)
# -------------------------------------------------------------------------
- name: Alte Cert-Dateien auf Lighthouse löschen
file: file:
path: "{{ nebula_cert_dir }}/{{ item }}" path: "{{ nebula_cert_dir }}/{{ item[0] }}.{{ item[1] }}"
state: absent state: absent
loop: >- loop: "{{ _renew_list | default([]) | product(['crt', 'key']) | list }}"
{{ loop_control:
_cert_status | dict2items label: "{{ item[0] }}.{{ item[1] }}"
| selectattr('value.expired_or_missing', 'equalto', true)
| map(attribute='key')
| product(['.crt', '.key'])
| map('join')
| list
}}
when: nebula_cert_force_renew | bool or _cert_status[item.split('.crt')[0].split('.key')[0]].expired_or_missing
# Lighthouse-eigenes Cert separat behandelt (unten)
- name: Neue Certs für Lighthouse selbst signieren (falls nötig) # -------------------------------------------------------------------------
# Neue Certs signieren
# -------------------------------------------------------------------------
- name: Neue Certs für alle betroffenen Nodes signieren
command: > command: >
{{ nebula_cert_dir }}/nebula-cert sign {{ nebula_cert_dir }}/nebula-cert sign
-name "{{ item }}" -name "{{ item }}"
-ip "{{ hostvars[item].nebula_internal_ip_addr }}/{{ nebula_network_cidr }}" -ip "{{ hostvars[item].nebula_internal_ip_addr }}/{{ hostvars[item].nebula_network_cidr | default(nebula_network_cidr) }}"
-duration "{{ nebula_client_cert_duration }}" -duration "{{ nebula_client_cert_duration }}"
args: args:
chdir: "{{ nebula_cert_dir }}" chdir: "{{ nebula_cert_dir }}"
creates: "{{ nebula_cert_dir }}/{{ item }}.crt" creates: "{{ nebula_cert_dir }}/{{ item }}.crt"
loop: "{{ groups['nebula_lighthouse'] }}" loop: "{{ _renew_list | default([]) }}"
when: > register: _sign_results
nebula_cert_force_renew | bool or
(_cert_status[item].expired_or_missing | default(true))
- name: Neue Certs für alle anderen Nodes signieren (falls nötig) - name: Signing-Ergebnis anzeigen
command: > debug:
{{ nebula_cert_dir }}/nebula-cert sign msg: "{{ item.item }}: {{ 'neu signiert' if item.changed else 'übersprungen (Cert existiert bereits)' }}"
-name "{{ item }}" loop: "{{ _sign_results.results }}"
-ip "{{ hostvars[item].nebula_internal_ip_addr }}/{{ nebula_network_cidr }}" loop_control:
-duration "{{ nebula_client_cert_duration }}" label: "{{ item.item }}"
args:
chdir: "{{ nebula_cert_dir }}"
creates: "{{ nebula_cert_dir }}/{{ item }}.crt"
loop: >-
{{
_all_nebula_nodes
| difference(groups['nebula_lighthouse'])
}}
when: >
nebula_cert_force_renew | bool or
(_cert_status[item].expired_or_missing | default(true))
- name: Neue Ablaufdaten zur Bestätigung anzeigen # -------------------------------------------------------------------------
# Neue Ablaufdaten zur Kontrolle anzeigen
# -------------------------------------------------------------------------
- name: Neue Ablaufdaten prüfen
command: > command: >
{{ nebula_cert_dir }}/nebula-cert print -json {{ nebula_cert_dir }}/nebula-cert print -json
-path {{ nebula_cert_dir }}/{{ item }}.crt -path {{ nebula_cert_dir }}/{{ item }}.crt
register: _new_cert_info register: _new_cert_check
loop: "{{ _all_nebula_nodes }}" loop: "{{ _renew_list | default([]) }}"
changed_when: false changed_when: false
ignore_errors: true ignore_errors: yes
- name: Neue Cert-Laufzeiten anzeigen - name: Neue Ablaufdaten anzeigen
debug: debug:
msg: >- msg: >-
{{ item.item }}: {{ item.item }}:
gültig bis {{ (item.stdout | from_json).details.notAfter | int | strftime('%Y-%m-%d %H:%M') }} neues Cert gültig bis
loop: "{{ _new_cert_info.results }}" {{ (item.stdout | from_json).details.notAfter | int | strftime('%Y-%m-%d %H:%M UTC') }}
loop: "{{ _new_cert_check.results }}"
loop_control: loop_control:
label: "{{ item.item }}" label: "{{ item.item }}"
when: item.rc == 0 when: item.rc == 0
# ----------------------------------------------------------------------------- # =============================================================================
# PHASE 2: Certs auf Lighthouse-Nodes selbst deployen # PLAY 2 Auf allen Nodes: neue Certs deployen, Nebula per SIGHUP neu laden
# Nebula auf dem Lighthouse neu laden (SIGHUP - kein Verbindungsabbruch!) #
# ----------------------------------------------------------------------------- # Strategie für remote-only Nodes (nur per Nebula-IP erreichbar):
- name: "Nebula Cert Renewal - Phase 2: Certs auf Lighthouse deployen" # - Certs werden per slurp vom Lighthouse geholt (kein SCP, kein temp-file)
hosts: nebula_lighthouse # - Nebula wird per SIGHUP neu geladen (kein systemd stop/start)
gather_facts: false # - SIGHUP lässt bestehende Tunnel aktiv → SSH-Verbindung bleibt stabil
become: true # - serial: 1 stellt sicher dass Lighthouses nie gleichzeitig neu laden
serial: 1 # Lighthouses nacheinander - immer einer aktiv # =============================================================================
- name: "Nebula Cert Renewal - Schritt 2: Neue Certs auf alle Nodes deployen"
vars: hosts: all
nebula_cert_dir: /opt/nebula gather_facts: no
nebula_cert_renew_threshold_days: 30 become: yes
nebula_cert_force_renew: false # Lighthouses zuerst und einzeln, dann alle anderen gleichzeitig
# Ansible sortiert: nebula_lighthouse kommt vor servers/anderen Gruppen
tasks: serial:
- 1 # Erste Runde: 1 Node (Primary Lighthouse)
- name: Cert-Dateien vom Primary Lighthouse einlesen - 1 # Zweite Runde: 1 Node (Secondary Lighthouse falls vorhanden)
slurp: - "100%" # Rest: alle gleichzeitig
src: "{{ nebula_cert_dir }}/{{ item }}"
register: _lh_cert_files
delegate_to: "{{ groups['nebula_lighthouse'][0] }}"
loop:
- "{{ inventory_hostname }}.crt"
- "{{ inventory_hostname }}.key"
- ca.crt
- name: Neue Cert/Key/CA auf Lighthouse-Node schreiben
copy:
dest: "{{ nebula_cert_dir }}/{{ item.item }}"
content: "{{ item.content | b64decode }}"
owner: root
group: root
mode: '0600'
loop: "{{ _lh_cert_files.results }}"
loop_control:
label: "{{ item.item }}"
register: _lh_cert_written
notify: nebula lighthouse hot-reload
# WICHTIG: SIGHUP statt Neustart - Nebula lädt Certs ohne Verbindungsabbruch
handlers:
- name: nebula lighthouse hot-reload
command: pkill -HUP -f "nebula.*config.yml"
# Alternativ falls systemd verwendet wird:
# systemd: name=lighthouse state=reloaded
# Nebula reagiert auf SIGHUP mit Reload der Certs seit v1.6+
ignore_errors: true
# -----------------------------------------------------------------------------
# PHASE 3: Certs auf alle regulären Nodes deployen
# Remote-only Nodes: Verbindung über Nebula-IP bleibt durch SIGHUP-Strategie stabil
# -----------------------------------------------------------------------------
- name: "Nebula Cert Renewal - Phase 3: Certs auf Nodes deployen"
hosts: "{{ groups.get('servers', []) + groups.get('nebula_nodes', []) | unique }}"
gather_facts: false
become: true
serial: 5 # 5 Nodes gleichzeitig - anpassen nach Bedarf
vars: vars:
nebula_cert_dir: /opt/nebula nebula_cert_dir: /opt/nebula
@@ -288,29 +279,29 @@
tasks: tasks:
# Prüfen ob dieser Node auf der Renewal-Liste des Lighthouse steht
# Wir lesen die Variable vom Lighthouse via hostvars
- name: Prüfen ob dieser Node ein Cert-Renewal benötigt - name: Prüfen ob dieser Node ein Cert-Renewal benötigt
command: > set_fact:
{{ nebula_cert_dir }}/nebula-cert print -json _this_node_needs_renewal: >-
-path {{ nebula_cert_dir }}/{{ inventory_hostname }}.crt {{
register: _local_cert_check inventory_hostname in
changed_when: false (hostvars[groups['nebula_lighthouse'][0]]._renew_list | default([]))
ignore_errors: true }}
delegate_to: "{{ groups['nebula_lighthouse'][0] }}"
# Wir prüfen auf dem Lighthouse, nicht lokal - der hat das neue Cert
- name: Cert-Erneuerung überspringen (kein Renewal nötig) - name: Node überspringen wenn kein Renewal nötig
meta: end_host debug:
when: > msg: "{{ inventory_hostname }}: kein Cert-Renewal nötig, überspringe."
not (nebula_cert_force_renew | bool) and when: not _this_node_needs_renewal | bool
_local_cert_check.rc == 0 and
((_local_cert_check.stdout | from_json).details.notAfter | int) >
(lookup('pipe', 'date +%s') | int + nebula_cert_renew_threshold_days * 86400)
# Cert-Dateien vom Primary Lighthouse per slurp holen (in-memory, kein temp-file) - meta: end_host
- name: Cert-Dateien vom Primary Lighthouse einlesen when: not _this_node_needs_renewal | bool
# Cert-Dateien vom Primary Lighthouse per slurp holen (in-memory, sicher)
- name: Neue Cert-Dateien vom Primary Lighthouse einlesen
slurp: slurp:
src: "{{ nebula_cert_dir }}/{{ item }}" src: "{{ nebula_cert_dir }}/{{ item }}"
register: _node_cert_files register: _cert_files
delegate_to: "{{ groups['nebula_lighthouse'][0] }}" delegate_to: "{{ groups['nebula_lighthouse'][0] }}"
loop: loop:
- "{{ inventory_hostname }}.crt" - "{{ inventory_hostname }}.crt"
@@ -324,64 +315,76 @@
owner: root owner: root
group: root group: root
mode: '0600' mode: '0600'
loop: "{{ _node_cert_files.results }}" loop: "{{ _cert_files.results }}"
loop_control: loop_control:
label: "{{ item.item }}" label: "{{ item.item }}"
register: _node_cert_written notify: nebula hot reload
notify: nebula node hot-reload
- name: Bestätigung
debug:
msg: "{{ inventory_hostname }}: neue Certs geschrieben, SIGHUP wird gesendet."
# SIGHUP: Nebula lädt das neue Cert ohne die bestehende Tunnel-Verbindung zu trennen.
# Das ist der entscheidende Trick für remote-only Nodes:
# Die SSH-Verbindung über Nebula bleibt aktiv während das Cert neu geladen wird.
handlers: handlers:
- name: nebula node hot-reload # SIGHUP statt Neustart: Nebula lädt das neue Cert ohne Tunnel zu trennen.
command: pkill -HUP -f "nebula.*config.yml" # Das ist der Schlüssel für remote-only Nodes: die SSH-Session über Nebula
# Alternativ: # bleibt aktiv während das Cert gewechselt wird.
# systemd: name=nebula state=reloaded - name: nebula hot reload
ignore_errors: true shell: |
# Lighthouse oder normaler Node?
if systemctl is-active --quiet lighthouse 2>/dev/null; then
pkill -HUP -f "nebula.*config.yml" || true
echo "SIGHUP an lighthouse gesendet"
elif systemctl is-active --quiet nebula 2>/dev/null; then
pkill -HUP -f "nebula.*config.yml" || true
echo "SIGHUP an nebula gesendet"
else
echo "Kein aktiver Nebula-Prozess gefunden"
fi
register: _reload_result
changed_when: true
- name: SIGHUP-Ergebnis anzeigen
debug:
msg: "{{ _reload_result.stdout }}"
# ----------------------------------------------------------------------------- # =============================================================================
# PHASE 4: Abschlussbericht # PLAY 3 Abschlussbericht auf dem Primary Lighthouse
# ----------------------------------------------------------------------------- # =============================================================================
- name: "Nebula Cert Renewal - Phase 4: Abschlussbericht" - name: "Nebula Cert Renewal - Schritt 3: Abschlussbericht"
hosts: "{{ groups['nebula_lighthouse'][0] }}" hosts: nebula_lighthouse[0]
gather_facts: false gather_facts: no
become: true become: yes
vars: vars:
nebula_cert_dir: /opt/nebula nebula_cert_dir: /opt/nebula
_all_nebula_nodes: >-
{{
(groups['nebula_lighthouse'] + groups.get('servers', []) + groups.get('nebula_nodes', []))
| unique
}}
tasks: tasks:
- name: Finale Cert-Ablaufdaten ermitteln - name: Finale Cert-Ablaufdaten für alle Nodes prüfen
command: > command: >
{{ nebula_cert_dir }}/nebula-cert print -json {{ nebula_cert_dir }}/nebula-cert print -json
-path {{ nebula_cert_dir }}/{{ item }}.crt -path {{ nebula_cert_dir }}/{{ item }}.crt
register: _final_cert_info register: _final_certs
loop: "{{ _all_nebula_nodes }}" loop: "{{ groups['all'] }}"
changed_when: false changed_when: false
ignore_errors: true ignore_errors: yes
- name: Abschlussbericht - name: Abschlussbericht
debug: debug:
msg: >- msg: >-
{{ item.item | ljust(40) }} {{ '%-45s' | format(item.item) }}
{% if item.rc == 0 %}
gültig bis: {{ (item.stdout | from_json).details.notAfter | int | strftime('%Y-%m-%d') }} gültig bis: {{ (item.stdout | from_json).details.notAfter | int | strftime('%Y-%m-%d') }}
loop: "{{ _final_cert_info.results }}" {% else %}
*** CERT NICHT LESBAR ***
{% endif %}
loop: "{{ _final_certs.results }}"
loop_control: loop_control:
label: "{{ item.item }}" label: "{{ item.item }}"
when: item.rc == 0
- name: Nodes mit Fehler (Cert nicht lesbar) - name: Hinweis auf Backup
debug: debug:
msg: "WARNUNG: Cert für {{ item.item }} konnte nicht gelesen werden!" msg: >-
loop: "{{ _final_cert_info.results }}" Alte Zertifikate gesichert in:
loop_control: {{ nebula_cert_dir }}/cert_backup_{{ hostvars[inventory_hostname]._now_ts.stdout | default('siehe Lighthouse') }}
label: "{{ item.item }}"
when: item.rc != 0