anpassen von git ignore

This commit is contained in:
2026-01-29 18:41:59 +01:00
parent 85bcb598df
commit dc06ee04d3
13 changed files with 336 additions and 59 deletions

5
.env.example Normal file
View File

@@ -0,0 +1,5 @@
# This is an example file.
# Create a file named .env and fill in the actual password.
# The .env file is ignored by git.
POSTGRES_PASSWORD=YourSecurePasswordHere

8
.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
# Puppet CA data should never be version-controlled
ca_data/
# Environment file with secrets
.env
# Puppet manifest with potentially sensitive data
code/environments/production/manifests/all_system.pp

139
README.md
View File

@@ -1,53 +1,118 @@
# PuppetDB API Abfragen
# Dockerized Puppet Master (OpenVox)
Dieses Dokument beschreibt, wie man die PuppetDB-API direkt über `curl` abfragt, um Informationen über den Status der Puppet-Clients zu erhalten.
Dieses Projekt konfiguriert einen Puppet Master, der in Docker-Containern läuft. Es verwendet Docker Compose für die Orchestrierung der Dienste, einschließlich des Puppet Masters (`openvox`), einer PostgreSQL-Datenbank und anderer notwendiger Komponenten.
Alle Befehle werden innerhalb des `openvox` (Puppet Master) Containers ausgeführt.
Die Konfiguration wurde optimiert, um portabel und einfach auf neuen Servern ausrollbar zu sein.
## Alle aktiven Clients (Nodes) auflisten
## Inhaltsverzeichnis
Um eine Liste aller von PuppetDB verwalteten Clients zu erhalten, die aktiv sind, verwenden Sie den folgenden Befehl:
- [Verzeichnisstruktur](#verzeichnisstruktur)
- [Lokale Inbetriebnahme](#lokale-inbetriebnahme)
- [Neuen Puppet-Agenten verbinden](#neuen-puppet-agenten-verbinden)
- [Deployment mit Ansible](#deployment-mit-ansible)
- [Backup & Portabilität](#backup--portabilität)
```bash
docker compose exec openvox curl -s http://openvoxdb:8080/pdb/query/v4/nodes
```
---
**Beispiel-Ausgabe (gekürzt):**
## Verzeichnisstruktur
```json
[
{
"certname": "arch-2.lxd",
"latest_report_status": "changed",
"facts_environment": "production",
...
}
]
```
Dies zeigt Ihnen den `certname` jedes Clients, den Sie für weitere Abfragen verwenden können.
- `docker-compose.yml`: Die zentrale Datei, die alle Docker-Services, Volumes und Netzwerke definiert.
- `code/`: Enthält den Puppet-Code (Manifeste, Module etc.), der von den Agenten angewendet wird.
- `config/`: Beinhaltet Konfigurationsdateien für die verschiedenen Dienste.
- `ca_data/`: **Wichtiges Verzeichnis.** Dies ist ein persistenter Speicher für die Certificate Authority (CA) des Puppet Masters. Es enthält alle signierten Zertifikate und wird per "bind mount" eingebunden.
- `hiera_config.md`: Erklärt die Konfiguration von Hiera, dem Key-Value-Lookup-System von Puppet, das hier zur Klassenzuweisung verwendet wird.
- `openvox_bugs.md`: Dokumentiert häufige SSL-Fehler und deren Lösungen.
- `deploy_openvox.yml`: Ein Ansible-Playbook, um das gesamte Setup automatisiert auf einem neuen Server zu deployen.
## Reports für einen bestimmten Client abrufen
---
Um zu sehen, was auf einem bestimmten Client gelaufen ist, können Sie dessen Reports abfragen. Ersetzen Sie `arch-2.lxd` mit dem `certname` des gewünschten Clients.
## Lokale Inbetriebnahme
```bash
docker compose exec openvox curl -s -G http://openvoxdb:8080/pdb/query/v4/reports --data-urlencode 'query=["=","certname","arch-2.lxd"]'
```
Um das Projekt auf einem neuen Rechner (mit installiertem Docker und Docker Compose) zum ersten Mal zu starten:
### Interpretation der Report-Ausgabe
1. **Projektverzeichnis klonen/kopieren:**
Stellen Sie sicher, dass Sie das gesamte Projektverzeichnis auf dem neuen Host haben.
Die Ausgabe ist ein JSON-Array von Reports. Jeder Report enthält wichtige Informationen:
2. **CA-Verzeichnis erstellen und Berechtigungen setzen:**
Der Puppet-Server im Container läuft nicht als `root`, sondern als Benutzer mit der ID `999`. Wir müssen das `ca_data`-Verzeichnis manuell erstellen und ihm die korrekten Berechtigungen geben. Führen Sie diese Befehle im Hauptverzeichnis des Projekts aus:
* `"status"`: Zeigt das Ergebnis des Puppet-Laufs.
* `"changed"`: Der Lauf war erfolgreich und es wurden Änderungen am System vorgenommen.
* `"unchanged"`: Der Lauf war erfolgreich, es waren aber keine Änderungen nötig.
* `"failed"`: Der Lauf ist fehlgeschlagen (z.B. wegen eines Kompilierungsfehlers).
* `"logs"`: Enthält die Log-Meldungen des Puppet-Agenten während des Laufs. Hier finden Sie Details zu Fehlern oder erfolgreichen Aktionen.
* `"resource_events"`: Zeigt im Detail, welche Ressourcen geändert wurden.
```bash
# Verzeichnis für die CA-Daten erstellen
sudo mkdir -p ./ca_data
Anhand dieser Reports können Sie genau nachvollziehen, welche Aktionen auf einem Client erfolgreich waren und welche nicht.
# Korrekte Berechtigungen setzen
sudo chown -R 999:999 ./ca_data
```
## Weiterführende Informationen
3. **Services starten:**
Starten Sie alle Dienste mit Docker Compose.
Für komplexere Abfragen können Sie die offizielle Dokumentation der PuppetDB API konsultieren:
[PuppetDB Query API Documentation](https://puppet.com/docs/puppetdb/latest/api/query/v4/overview.html)
```bash
docker compose up -d
```
4. **Status überprüfen:**
Nach etwa einer Minute sollte der `openvox`-Container als `healthy` angezeigt werden.
```bash
docker compose ps
```
---
## Neuen Puppet-Agenten verbinden
Wenn ein neuer Puppet-Agent mit dem Master verbunden werden soll, muss sein Zertifikat signiert werden:
1. **Auf dem neuen Agenten:**
Führen Sie den Agenten einmal aus. Er wird eine Zertifikatsanfrage (CSR) an den Master senden und mit einem Fehler abbrechen.
```bash
sudo puppet agent -t
```
2. **Auf dem Docker-Host (Master):**
Listen Sie die ausstehenden Anfragen auf und signieren Sie die des neuen Agenten.
```bash
# Anfragen auflisten
docker exec -it openvox puppetserver ca list
# Anfrage signieren (ersetzen Sie <agent_hostname>)
docker exec -it openvox puppetserver ca sign --certname <agent_hostname>
```
3. **Erneut auf dem Agenten:**
Führen Sie den Agenten erneut aus. Er sollte nun das signierte Zertifikat erhalten und seine Konfiguration anwenden.
```bash
sudo puppet agent -t
```
*Bei SSL-Problemen siehe `openvox_bugs.md`.*
---
## Deployment mit Ansible
Das beiliegende Ansible-Playbook `deploy_openvox.yml` automatisiert die Inbetriebnahme auf einem neuen Server.
**Voraussetzungen:**
- Auf dem **Steuer-Rechner**: Ansible und die `community.docker`-Collection (`ansible-galaxy collection install community.docker`).
- Auf dem **Ziel-Server**: Docker und Docker Compose müssen bereits installiert sein. Passwortloser SSH-Zugang vom Steuer-Rechner zum Ziel-Server.
**Ausführung:**
1. **Playbook verschieben:** Stellen Sie sicher, dass das Playbook `deploy_openvox.yml` eine Ebene *über* dem `openvox`-Projektverzeichnis liegt.
2. **Inventory erstellen:** Legen Sie eine `inventory.ini`-Datei an, um Ihre Zielserver zu definieren (siehe die Kommentare im Playbook für ein Beispiel).
3. **Playbook starten:**
```bash
# Ersetzen Sie <your_host_group> mit dem Namen aus Ihrer inventory.ini
ansible-playbook -i inventory.ini deploy_openvox.yml -e "target_host=<your_host_group>"
```
---
## Backup & Portabilität
Durch die Verwendung eines "bind mounts" für das `ca_data`-Verzeichnis ist das Projekt hochgradig portabel und einfach zu sichern.
- **Backup:** Um ein vollständiges Backup zu erstellen, sichern Sie einfach den gesamten `openvox`-Projektordner. Alle wichtigen Daten (Puppet-Code, CA-Zertifikate) sind darin enthalten.
- **Wiederherstellung/Umzug:** Kopieren Sie den gesicherten Ordner auf einen neuen Server, führen Sie die Schritte unter [Lokale Inbetriebnahme](#lokale-inbetriebnahme) aus, und Ihr Puppet-Master ist mit allen signierten Zertifikaten wieder online.

View File

@@ -0,0 +1,3 @@
---
classes:
- all_system

View File

@@ -0,0 +1,3 @@
---
classes:
- test

View File

@@ -0,0 +1,9 @@
version: 5
defaults:
datadir: data
data_hash: yaml_data
hierarchy:
- name: "Per-Node-Konfiguration (pro Server)"
path: "nodes/%{trusted.certname}.yaml"
- name: "Allgemeine Konfiguration (für alle)"
path: "common.yaml"

View File

@@ -4,7 +4,7 @@ class all_system {
owner => 'root',
group => 'root',
mode => '0644',
content => "<-----------------------Dieser Server wird zum Teil von Puppet verwaltet.----------------------->\n",
content => "<-----------------------Dieser Server wird zum Teil von Puppet verwaltet. Finger WEG !!!----------------------->\n",
}
@@ -23,6 +23,11 @@ class all_system {
}
schedule { 'weekly':
period => weekly,
repeat => 1,
}
case $facts['os']['name'] {
'CentOS', 'RedHat': {
# Configuration for RedHat-based systems
@@ -35,12 +40,15 @@ class all_system {
group => 'root',
mode => '0755',
}
cron { 'apt_update_upgrade':
exec { 'apt-update-upgrade':
command => '/usr/bin/apt-get update && /usr/bin/apt-get -y upgrade',
provider => 'shell',
logoutput => 'on_failure',
schedule => 'weekly',
path => ['/usr/bin', '/bin'],
user => 'root',
weekday => 0, # 0 = Sonntag
hour => '2',
minute => '0',
group => 'root',
timeout => 0,
require => File['/usr/bin/apt-get'],
}
package { 'apache2':
@@ -56,11 +64,6 @@ class all_system {
ensure => 'present',
provider => 'pacman',
}
# Configuration for Arch-based systems
schedule { 'weekly':
period => weekly,
repeat => 1,
}
# Führen Sie die Systemaktualisierung durch
exec { 'pacman-update':

View File

@@ -1,4 +1 @@
node default {
include all_system
}
lookup('classes', {merge => 'unique'}).include

View File

@@ -0,0 +1,30 @@
class test {
# Schleifen Loop möglichkeit 1
$dateinamen = [ 'datei_1.txt', 'datei_2.test' ]
$dateinamen.each |String $dateiname| {
file { "/tmp/${dateiname}":
ensure => file,
owner => 'root',
group => 'root',
mode => '0644',
content => "Dies ist eine Datei ${dateiname}\n"
}
}
# möglichkeit 2
$konfigurations_dateien = {
'/tmp/my_config' =>
"port=3306\nbind-address=127.0.0.1\n",
'/tmp/httpd.conf' =>
"Listen 80\nServerName localhost\n"
}
$konfigurations_dateien.each|String $pfad, String $inhalt| {
file { $pfad:
ensure => file,
content => $inhalt,
mode => '0640',
}
}
}

47
deploy_openvox.yml Normal file
View File

@@ -0,0 +1,47 @@
---
- name: Deploy OpenVox Docker Compose Project
hosts: "{{ target_host | default('localhost') }}"
become: true
vars:
project_dir_name: "openvox"
# ANNAHME: Das Playbook wird aus dem übergeordneten Verzeichnis von 'openvox' ausgeführt.
# Passen Sie ggf. den Pfad an.
project_local_path: "{{ playbook_dir }}/{{ project_dir_name }}"
project_remote_path: "/opt/{{ project_dir_name }}"
tasks:
- name: "Stellt sicher, dass das Projektverzeichnis auf dem Zielhost existiert"
ansible.builtin.file:
path: "{{ project_remote_path }}"
state: directory
mode: '0755'
- name: "Kopiert die Projektdateien auf den Zielhost"
ansible.builtin.copy:
src: "{{ project_local_path }}/"
dest: "{{ project_remote_path }}/"
- name: "Stellt sicher, dass das ca_data Verzeichnis existiert"
ansible.builtin.file:
path: "{{ project_remote_path }}/ca_data"
state: directory
mode: '0755'
- name: "Setzt die Berechtigungen für das ca_data Verzeichnis"
ansible.builtin.file:
path: "{{ project_remote_path }}/ca_data"
owner: '999'
group: '999'
recurse: true
- name: "Startet die Docker Compose Services"
community.docker.docker_compose_v2:
project_src: "{{ project_remote_path }}"
state: present # 'present' entspricht 'up -d'
register: compose_output
- name: "Zeigt den Output von Docker Compose an"
ansible.builtin.debug:
var: compose_output

View File

@@ -12,8 +12,10 @@ services:
- ./config/puppet/puppet.conf:/etc/puppetlabs/puppet/puppet.conf
- ./code:/etc/puppetlabs/code
- ca_ssl_data:/etc/puppetlabs/puppet/ssl
- ./ca_data:/etc/puppetlabs/puppetserver/ca
environment:
- OPENVOXSERVER_ENVIRONMENT_TIMEOUT=10
# - CA_ENABLED="true"
networks:
- openvox_network
@@ -24,7 +26,7 @@ services:
hostname: postgres
environment:
POSTGRES_USER: openvox
POSTGRES_PASSWORD: StartStart1234
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: openvoxdb
POSTGRES_EXTENSIONS: pg_trgm
volumes:
@@ -54,17 +56,16 @@ services:
OPENVOXDB_POSTGRES_PORT: 5432
OPENVOXDB_POSTGRES_DATABASE: openvoxdb
OPENVOXDB_POSTGRES_USER: openvox
OPENVOXDB_POSTGRES_PASSWORD: StartStart1234
OPENVOXDB_POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
networks:
- openvox_network
volumes:
- openvoxdb_data:/var/lib/openvoxdb
- openvoxdb_ca:/etc/puppetlabs/puppetserver/ca
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "PGPASSWORD=StartStart1234 pg_isready -h postgres -p 5432 -U openvox"]
test: ["CMD-SHELL", "PGPASSWORD=${POSTGRES_PASSWORD} pg_isready -h postgres -p 5432 -U openvox"]
interval: 5s
timeout: 5s
retries: 5
@@ -73,7 +74,6 @@ services:
volumes:
postgres_data:
openvoxdb_data:
openvoxdb_ca:
ca_ssl_data:
networks:

49
hiera_config.md Normal file
View File

@@ -0,0 +1,49 @@
# Hiera Konfiguration: Kurzbeschreibung
Diese Datei erklärt die grundlegenden Einstellungen in der `hiera.yaml`, die für dieses Projekt konfiguriert wurde.
## Die Datei `hiera.yaml`
```yaml
version: 5
defaults:
datadir: data
data_hash: yaml_data
hierarchy:
- name: "Per-Node-Konfiguration (pro Server)"
path: "nodes/%{trusted.certname}.yaml"
- name: "Allgemeine Konfiguration (für alle)"
path: "common.yaml"
```
### `version: 5`
Dies ist die Standardversion für moderne Puppet-Installationen und muss an erster Stelle stehen.
### `defaults`
Hier werden Standardwerte für die gesamte Hierarchie festgelegt.
- `datadir: data`: Teilt Hiera mit, dass alle Datenpfade relativ zum Unterverzeichnis `data` sind. Das Haupt-Datenverzeichnis ist also `code/environments/production/data/`.
- `data_hash: yaml_data`: Gibt an, dass die Datenquelle eine YAML-Datei ist.
### `hierarchy`
Dies ist das Herzstück von Hiera. Es ist eine **geordnete Liste**, die definiert, in welcher Reihenfolge Puppet nach Daten sucht. Die Suche stoppt beim ersten gefundenen Wert, es sei denn, ein "merge behavior" (Zusammenführungsverhalten) ist definiert.
1. **`path: "nodes/%{trusted.certname}.yaml"`**
- **Bedeutung:** Dies ist die **höchste** Priorität. Hiera sucht zuerst nach einer Datei im `data/nodes/`-Verzeichnis, deren Name dem Zertifikatsnamen des anfragenden Servers entspricht (z.B. `arch-2.lxd.yaml`).
- **Zweck:** Hier werden Konfigurationen hinterlegt, die **nur für einen einzigen, spezifischen Server** gelten.
- `%{trusted.certname}` ist eine Puppet-Variable, die den verifizierten Namen des Agenten enthält.
2. **`path: "common.yaml"`**
- **Bedeutung:** Dies ist die **niedrigste** Priorität. Wenn in den spezifischeren Ebenen (wie der pro-Node-Datei) kein Wert gefunden wurde, sucht Hiera hier.
- **Zweck:** Dies ist der Ort für die **Standardkonfiguration**, die für **alle Server** gelten soll.
## Die Datei `site.pp`
Die `site.pp` wurde auf eine einzige Zeile reduziert:
```puppet
lookup('classes', {merge => 'unique'}).include
```
- `lookup('classes', ...)`: Diese Funktion startet eine Suche in der Hiera-Hierarchie nach dem Schlüssel `classes`.
- `{merge => 'unique'}`: Dies ist das "Zusammenführungsverhalten". Es weist Hiera an, nicht beim ersten Treffer aufzuhören, sondern **alle Ebenen** der Hierarchie zu durchsuchen und eine Liste aller gefundenen Werte für `classes` zu erstellen, wobei Duplikate entfernt werden.
- `.include`: Diese Funktion nimmt die resultierende Liste von Klassennamen und deklariert sie, sodass Puppet sie anwendet.
Für den Server `arch-2.lxd` findet Hiera also `test` in der Node-spezifischen Datei und `all_system` in der `common.yaml`-Datei, fügt beide zu einer Liste zusammen und wendet beide Klassen an.

58
openvox_bugs.md Normal file
View File

@@ -0,0 +1,58 @@
# Puppet SSL-Fehler: Zertifikat stimmt nicht mit privatem Schlüssel überein
## Problem
Beim Ausführen von `puppet agent -t` auf einem Puppet-Agenten tritt der folgende Fehler auf, selbst nach dem Löschen des lokalen SSL-Verzeichnisses (`/etc/puppetlabs/puppet/ssl`):
```
Error: The certificate for 'CN=<agent-hostname>' does not match its private key
```
Der Agent generiert zwar einen neuen Schlüssel, erhält aber vom Puppet-Master ein altes, nicht passendes Zertifikat zurück, anstatt auf eine neue Signierung zu warten.
## Ursache
Dieses Problem tritt auf, wenn auf dem Puppet-Master bereits ein Zertifikat für den Agenten existiert. Wenn der Agent nach dem lokalen Löschen seiner Schlüssel ein neues anfordert, gibt der Master fälschlicherweise das alte, bereits vorhandene Zertifikat aus, das nicht mehr zum neuen privaten Schlüssel des Agenten passt.
## Lösung
Die korrekte Lösung besteht darin, das Zertifikat des Agenten zuerst auf dem Puppet-Master vollständig zu **bereinigen** (`clean`), bevor der Agent eine neue Anfrage stellt. Dies erzwingt einen sauberen Neuregistrierungsprozess.
### Schritt-für-Schritt-Anleitung
1. **Zertifikat auf dem Puppet-Master bereinigen:**
Führen Sie diesen Befehl auf dem System aus, auf dem Ihr Puppet-Master-Container (`openvox`) läuft. Ersetzen Sie `<agent-hostname>` durch den Hostnamen des problematischen Agenten.
```bash
# Beispiel für den Agenten 'arch-2.lxd'
docker exec -it openvox puppetserver ca clean --certname arch-2.lxd
```
2. **SSL-Verzeichnis auf dem Agenten löschen:**
Verbinden Sie sich mit dem Agenten-System und löschen Sie das SSL-Verzeichnis, um einen sauberen Zustand zu erzwingen.
```bash
sudo rm -rf /etc/puppetlabs/puppet/ssl
```
3. **Neue Zertifikatsanfrage vom Agenten senden:**
Führen Sie den Puppet-Agenten auf dem Agenten-System aus. Dieser Lauf wird wie erwartet mit einem Fehler abbrechen, da der Master die neue Anfrage noch nicht kennt und signiert hat.
```bash
sudo puppet agent -t
```
4. **Zertifikat auf dem Puppet-Master signieren:**
Gehen Sie zurück zum Master-System und signieren Sie die neue Anfrage, die in Schritt 3 erstellt wurde.
```bash
# Beispiel für den Agenten 'arch-2.lxd'
docker exec -it openvox puppetserver ca sign --certname arch-2.lxd
```
5. **Puppet-Lauf auf dem Agenten abschließen:**
Führen Sie den Agenten ein letztes Mal aus. Er sollte nun das korrekt signierte Zertifikat erhalten und den Lauf erfolgreich abschließen.
```bash
sudo puppet agent -t
```