Cfengine 3 verspricht Admins ein effizienteres Konfigurationsmanagement und das strikte Einhalten von Policies. Es muss jedoch gegen starke Konkurrenten bestehen.
Als Konfigurationsmanagement bezeichnet man das möglichst automatisierte und einheitliche Verwalten von Systemen mit standardisierten Werkzeugen. Mittels spezieller Konfigurationssprachen füttert man das Tool der Wahl mit Anweisungen, die Zielsysteme in den gewünschten Zustand bringen und ihn erhalten sollen. Das nimmt dem Systembetreuer das Umsetzen der Systemverwaltung ab.
Die Installation und Konfiguration von Software, das Starten von von Prozessen und Diensten, das Anlegen von Benutzern und Gruppen, das Setzen von Dateirechten – all das legt der Systembetreuer einmal fest und lässt dann das Tool für sich arbeiten. Weicht ein System vom definierten Standard ab, biegt das Konfigurationsmanagement das wieder gerade. So können auch kleine Teams große Systemlandschaften automatisiert verwalten.
Zu den am häufigsten genutzten Automatisierungswerkzeugen dieser Gattung zählen die bekannten Lösungen Puppet und Chef, aber auch Ansible, Saltstack und in gewisser Weise auch Terraform. Weniger bekannt ist die Software Cfengine 3 – dabei galt ihre Vorgängerin als die erste ihrer Art.
Ehre, wem Ehre gebührt
Lange schrieben Systemadministratoren Skripte, um eine größere Zahl an Systemen einheitlich zu verwalten. Cfengine goss das Prinzip der zentralen und standardisierten Konfiguration erstmals in ein fertiges Stück Software. Schon 1993 beschrieb Mark Burgess an der Universität in Oslo Cfengine als ein Werkzeug, das mithilfe einer Abstraktion und einer Art Konfigurationssprache die Verwaltung von zahlreichen Systemen ermöglicht. Die wachsende Verbreitung mündete schließlich 2002 in der deutlich reiferen Version 2, die aufgrund ihrer Verlässlichkeit heute noch in einigen Unternehmen im Einsatz ist.
Wie bei anderen quelloffenen Projekten auch, kommerzialisierte sich das Projekt mit der breiteren Nutzung im Enterprise-Bereich zunehmend, was 2008 zu der Gründung eines Unternehmens für Support und Beratungsdienstleistungen führte. Ein Jahr später erschien dann Cfengine 3 [1], das teilweise die Abwärtskompatibilität zu seinem Vorgänger aufgibt und erstmals in Community- und Enterprise-Editionen zur Verfügung steht. Letztere fokussiert mit Features wie Reporting oder einer Weboberfläche auf Unternehmenskunden. Auch die freie Variante enthält jedoch alle wichtigen Funktionen für das tägliche Konfigurationsmanagement. Die kommerzielle Ausgabe versüßt der Hersteller damit, dass sich damit bis zu 25 Systeme kostenfrei verwalten lassen.
Designprinzipien
Das Design von Cfengine fußt auf mehreren Prinzipien, die sich wie ein roter Faden durch den Aufbau und die Nutzung des Tools ziehen. Mit einem deklarativen Ansatz definiert der Systembetreuer in einer Konfigurationssprache den gewünschten Endzustand eines Systems. Wie dieser erreicht wird, gibt er meist nicht im Detail an. Er hinterlegt die Anweisungen auf einem zentralen System, von dem sich die zu konfigurierenden Rechner die neuesten Versionen herunterladen können (Pull-Prinzip).
Cfengine führt lokal automatisch alle benötigten Schritte aus und abstrahiert damit die konkreten Befehle auf der Kommandozeile – also die Umsetzung – von der Systembeschreibung. Ein konkretes Beispiel für eine Anweisung wäre etwa: Stelle sicher, dass der Webserver Nginx installiert und gestartet ist. Einen konkreten Befehl wie »yum install nginx« muss der Betreuer nicht geben, da Cfengine für jedes unterstützte Betriebssystem eine Bibliothek von Befehlen führt, die es automatisch beim Umsetzen der Anweisungen verwendet.
Versprochen
Das wichtigste Prinzip von Cfengine stellt allerdings die sogenannte Promise Theory dar. Sie soll das Problem lösen, dass Systemadministratoren sich nicht immer sicher sind, ob sich ein Zielsystem gerade im gewünschten Zustand befindet. Im Zweifel fühlt sich der Admin zu einem manuellen Login genötigt, damit er den Zustand sichten und gegebenenfalls korrigieren kann. Nach einiger Zeit droht die Wiederholung dieses zeitraubenden Unterfangens: Andere Nutzer könnten das System ja (unfreiwillig) verändert haben, sodass es seinen ursprünglichen Zweck nicht mehr zuverlässig erfüllt.
Das Modell der Promise Theory beschreibt nun, wie sich diese permanente Ungewissheit effizient auflösen lässt. Man stattet jedes System mit einem Agenten aus, der sich der Kontrolle durch einen zentralen Server unterwirft und von dort Anweisungen bezieht, sogenannte Promises. Eigentlich ist laut den Machern der Software so ziemlich alles in Cfengine 3 ein Promise. Damit tut ein autonomes System seine Absicht kund, sich selbst an Hand der empfangenen Anweisungen in den gewünschten Zustand zu verfrachten – auch dann, wenn sich beispielsweise der zentrale Server mit den Anweisungen gerade nicht erreichen lässt. Das Versprechen beinhaltet allerdings keine Zusage über einen Erfolg, sondern nur die Intention, dem gewünschten Zustand (notfalls nach mehreren Iterationen) möglichst nahezukommen.
Was im ersten Moment reichlich schräg klingt, hat einen handfesten Vorteil: Neben der eigentlichen Beschreibung des Zustands kann der Systemadministrator auch Anweisungen hinterlegen, was geschehen soll, wenn der angestrebte Zustand gerade nicht vorliegt oder sich sogar grundsätzlich nicht erreichen lässt. Im besten Fall repariert der Cfengine-Agent das System und stellt den gewünschten Zustand her. Im schlechtesten kann er das System nicht geradebiegen und greift dann auf die Anweisung zurück, die der Administrator für solche Fälle hinterlegt hat.
Von Promises und Policies
Die kleinste in sich geschlossene und ausführbare Einheit stellt in Cfengine das Promise dar, das salopp ausgedrückt mindestens eine konkrete Anweisung enthält, etwa: Stelle sicher, dass ein User angelegt wird. Mehrere dieser Anweisungen bündelt man dann in einer Policy.
Der Name verrät, wie Cfengine 3 tickt: Schon seit Version 1 betrachten die Cfengine-Macher Systeme als Entitäten, die unternehmensweite Richtlinien (Policies) einhalten sollen. Logisch, dass eine Gruppe von Anweisungen (Policies) dann die Einzelmaßnahmen (Promises) durchsetzt. Wer mehrere Policies bündeln muss, bedient sich der nächsthöheren Gruppierungsform mit dem praktischen Namen Bundles.
Bordmittel
Cfengine 3 beherrscht die üblichen Arbeiten, die man von einem Konfigurationswerkzeug erwarten darf: Es kann Informationen über ein Zielsystem und dessen Zustand einholen und Textdateien in verschiedenen Formaten modifizieren. Dateiberechtigungen und -eigentümer vermag es ebenso zu setzen wie Posix-ACLs.
Benutzer, Gruppen, Firewall-Einträge, Prozesse, Dienste, Start von Drittprogrammen – alles, was man zur Systemverwaltung unter Linux (CentOS/RHEL, Debian, Ubuntu, SLES), Unix (AIX, HP-UX, Solaris) und Windows (nur Enterprise-Variante) benötigt, enthält Cfengine 3 standardmäßig. Daneben unterstützt es zahlreiche fortgeschrittene Operationen wie das Abfragen und Modifizieren von Datenbanken. Dank einer Anbindung an VMware, KVM, Xen und Virtualbox lassen sich auch virtuelle Maschinen über Standardanweisungen in Promises verwalten.
Der deklarative Ansatz macht die Cfengine-Policies idempotent; sie lassen sich also beliebig oft ausführen und erzielen stets dasselbe Ergebnis. Eine permanente Überwachung des lokalen Systems durch den Cfengine-Agenten stellt dabei sicher, dass geänderte Zustände aufgedeckt und korrigiert werden.
Cfengine 3 einrichten
Für den Betrieb von Cfengine 3 installiert man den zentralen Server (Policy Server oder auch Policy Hub) und mindestens einen Agenten, wobei diese Komponenten [2] für Testzwecke auf dem gleichen System laufen dürfen. Im Regelbetrieb verteilt der Policy Server seine Policy-Dateien an Agenten, die auf unterschiedlichen Systemen laufen (Abbildung 1).
Da sich der Autor stets unter Linux bewegt, hat er für diesen Artikel entsprechend eine kleine Testumgebung zusammengestellt (siehe Tabelle “Lab-Systeme”) und die Installation von Hand gemäß der offiziellen Anleitung für die Community-Edition [3] vorgenommen. Auf allen Systemen wird bei der Betriebssysteminstallation der Nutzer linuxmag eingerichtet und mit Sudo-Rechten versehen.
|
Hostname |
OS |
IP-Adresse |
Rolle |
|---|---|---|---|
|
»cf3-ubsrv« |
Ubuntu 20.04 |
192.168.38.131 |
Policy Hub, stellt Policy-Dateien bereit |
|
»cf3-ubcli« |
Ubuntu 20.04 |
192.168.38.132 |
System mit Cfengine-Agent |
|
»cf3-centcli« |
CentOS 8 |
192.168.38.133 |
System mit Cfengine-Agent |
Die notwendigen Software-Pakete gibt es direkt auf der Webseite des Herstellers [4]. Eine Installation über die Repositories der verwendeten Distributionen empfiehlt sich aufgrund veralteter Software-Stände nicht. Das Cfengine-3-Paket in den Repositories von Ubuntu 20.04 etwa war zum Zeitpunkt des Tests unvollständig und schlecht gewartet.
Auf allen beteiligten Testsystemen wurde Cfengine in der Version 3.15.3 installiert (Listing 1 bis Listing 3). Entsprechende Pakete stehen zum Herunterladen bereit, auch wenn die Online-Dokumentation von Cfengine 3 weder Ubuntu 20.04 noch CentOS 8 in der Liste der unterstützten Plattformen führt. Das dürfte schlicht daran liegen, dass die Online-Dokumentation nach ihrer Veröffentlichung schlicht nicht angepasst wurde – die jeweiligen Vorversionen beider Distributionen finden sich in der Liste.
Listing 1
Installation auf cf3-ubsrv
$ sudo wget https://cfengine-package-repos.s3.amazonaws.com/community_binaries/Community-3.15.3/agent_ubuntu18_x86_64/cfengine-community_3.15.3-1.ubuntu18_amd64.deb $ sudo apt install ./cfengine-community_3.15.3-1.ubuntu18_amd64.deb $ sudo cf-agent --bootstrap 192.168.38.131 R: Bootstrapping from host '192.168.38.131' via built-in policy '/var/cfengine/inputs/failsafe.cf' R: This host assumes the role of policy server R: Updated local policy from policy server R: Triggered an initial run of the policy R: Restarted systemd unit cfengine3 notice: Bootstrap to '192.168.38.131' completed successfully!
Listing 2
Installation auf cf3-ubcli (Agent)
$ sudo wget https://cfengine-package-repos.s3.amazonaws.com/community_binaries/Community-3.15.3/agent_ubuntu18_x86_64/cfengine-community_3.15.3-1.ubuntu18_amd64.deb $ sudo apt install ./cfengine-community_3.15.3-1.ubuntu18_amd64.deb $ sudo cf-agent --bootstrap 192.168.38.131 notice: Bootstrap mode: implicitly trusting server, use --trust-server=no if server trust is already established notice: Trusting new key: MD5=d67ad40160db5f79a616eea18bb9073c R: Bootstrapping from host '192.168.38.131' via built-in policy '/var/cfengine/inputs/failsafe.cf' R: This autonomous node assumes the role of voluntary client R: Updated local policy from policy server R: Triggered an initial run of the policy R: Restarted systemd unit cfengine3 notice: Bootstrap to '192.168.38.131' completed successfully!
Listing 3
Installation auf cf3-centcli (Agent)
$ wget https://cfengine-package-repos.s3.amazonaws.com/community_binaries/Community-3.15.3/agent_rhel8_x86_64/cfengine-community-3.15.3-1.el8.x86_64.rpm $ sudo yum localinstall cfengine-community-3.15.3-1.el8.x86_64.rpm $ sudo /var/cfengine/bin/cf-agent --bootstrap 192.168.38.131 notice: Bootstrap mode: implicitly trusting server, use --trust-server=no if server trust is already established notice: Trusting new key: MD5=d67ad40160db5f79a616eea18bb9073c R: Bootstrapping from host '192.168.38.131' via built-in policy '/var/cfengine/inputs/failsafe.cf' R: This autonomous node assumes the role of voluntary client R: Updated local policy from policy server R: Triggered an initial run of the policy R: Restarted systemd unit cfengine3 notice: Bootstrap to '192.168.38.131' completed successfully! ### Port 5308/TCP in der lokalen Firewall öffnen $ sudo firewall-cmd --zone=public --add-service=cfengine
Nach der Installation des Policy-Hub und der Agenten auf den Lab-Systemen meldete sich der Autor als Benutzer linuxmag auf dem Host »cf3-ubsrv« an und nahm mit den Befehlen aus Listing 4 einen kurzen Verbindungstest vor (Abbildung 2).
Listing 4
Verbindungstest
# /var/cfengine/bin/cf-net -H 192.168.38.131,192.168.38.132,192.168.38.133 connect
Connected & authenticated successfully to '192.168.38.131'
Connected & authenticated successfully to '192.168.38.132'
Connected & authenticated successfully to '192.168.38.133'
Prinzipiell sieht Cfengine 3 als Best Practice vor, alle Befehle unter dem Root-Account auszuführen, was die nachfolgenden Listings berücksichtigen. Cfengine 3 startet gleich mehrere Prozesse pro System, die alle verschiedenen Aufgaben nachgehen. Eine kurze Übersicht findet sich in der offiziellen Dokumentation [5].
Erste Schritte
Am Ende der Listings zur Installation auf den verschiedenen Systemen fand mit dem Bootstrapping die initiale Einrichtung von Cfengine 3 statt. Unter anderem wurden Beispielkonfigurationen aus dem installierten Paket kopiert und wichtige Verzeichnisstrukturen unter »/var/cfengine/« angelegt. Die vordefinierten Inhalte im Detail beschreibt die Online-Dokumentation [6].
Auf dem Policy Hub »cf3-ubsrv« legte der Autor selbst erstellte Cfengine-Dateien mit Anweisungen unter »/var/cfengine/masterfiles/« ab. In dem Ordner befinden sich bereits Dateien, die Cfengine automatisch erstellt hat. Der Ordnung halber sieht Cfengine 3 vor, selbst erstellte Policy-Dateien unter »/var/cfengine/masterfiles/services/« abzulegen. Soll, wie für diesen Artikel, eine Policy-Datei automatisch ausgeführt werden, speichert man sie unter »/var/cfengine/masterfiles/services/autorun/«.
Alle auf dem zentralen Policy Hub unter »/var/cfengine/masterfiles/« abgelegten Dateien (Abbildung 3) laden die Agenten standardmäßig im Intervall von fünf Minuten herunter und stellen sie lokal unter »/var/cfengine/inputs/« zur Verfügung. Nach dem Prinzip der Infrastructure as a Code empfehlen die Entwickler, den Inhalt von »/var/cfengine/masterfiles/« unter eine Versionskontrolle durch SVN oder Git zu stellen.
Zur Veranschaulichung der Arbeitsweise von Cfengine 3 führte der Autor eine einfache Policy ein, die auf den Zielsystemen den leichtgewichtigen Webserver Nginx installiert, den zugehörigen Systemd-Dienst aktiviert und im selben Zug startet. Dazu erstellte er per Texteditor auf dem Policy Hub die Datei »/var/cfengine/masterfiles/services/autorun/webserver.cf« und füllte sie mit Leben (Listing 5). Näheres dazu erläutert der Kasten “»webserver.cf« im Detail”. Mit dem Befehl aus Listing 6 lässt sich der Inhalt der Datei auf Fehler prüfen.
Listing 5
webserver.cf
bundle agent nginx_installed_running {
meta:
"tags" slist => { "autorun" };
vars:
"package_list" slist => { "nginx" };
packages:
"$(package_list)"
package_policy => "add",
package_method => generic;
services:
"$(package_list)"
service_policy => "start";
}
webserver.cf im Detail
Listing 5 beginnt mit der Definition eines Bundles, das innerhalb geschweifter Klammern mehrere Promises umfasst. Den Bundle-Namen, hier »nginx_installed_running«, darf man frei wählen, für den Bundle-Typ hingegen macht Cfengine 3 klare Vorgaben [11]. Bundles vom Typ »agent« beinhalten Promises, die direkt auf den Zielsystemen Änderungen vornehmen. Das Promise vom Typ »meta« umfasst eine Listen-Variable mit dem einzigen Element »autorun«, was dazu führt, dass Cfengine 3 dieses Bundle bei jedem automatischen Durchlauf berücksichtigt.
Das Promise vom Typ »vars« beinhaltet eine Liste zu installierender Pakete. Hier darf man auch mehrere Pakete auflisten. Das »packages«-Promise bedient sich eines Tricks: Anstelle eines Namens oder der Angabe des zu installierenden Pakets gibt der Autor hier den Namen der Liste »package_list« an, womit Cfengine 3 automatisch durch alle Einträge dieser Liste iteriert und für jedes Element die Attribute »package_policy« (»add« für hinzufügen) und »package_method« (»generic« für “verwende den jeweils passenden Paketmanager”) anwendet.
Das Promise vom Typ »services« iteriert ebenfalls durch die Paketliste und wendet jeweils das Attribut »service_policy« an, wobei der Wert »start« den zugehörigen Systemd-Service aktiviert und startet. Mehr zu den verschiedenen Promise-Typen findet sich in der Online-Dokumentation [12].
Listing 6
webserver.cf prüfen
# cf-promises -f /var/cfengine/masterfiles/services/autorun/webserver.cf
Das automatische Ausführen von eigenen Policy-Files muss man auf dem Policy Hub einmalig aktivieren. Dafür legt man unter »/var/cfengine/masterfiles/« die Datei »def.json« an (Listing 7). Sie konfiguriert die die Option (genauer: Cfengine-Klasse) »services_autorun«. In den Kommentaren in der Datei »/var/cfengine/masterfiles/promises.cf« lässt sich deren Wirkung nachlesen.
Listing 7
def.json
{
"classes":
{
"services_autorun": [ "any" ]
}
}
In der Standardkonfiguration setzt der Cfengine-Agent auf den Zielsystemen alle fünf Minuten die Promises um. Der Befehl »cf-agent –dry-run –inform« zeigt, was er bei der nächsten automatischen Ausführung anstoßen würde (Abbildung 4).
Nach der nächsten automatischen Ausführung finden sich auf den Zielsystemen das installierte Paket nginx sowie der zugehörige aktivierte und gestartete Dienst (Abbildung 5). Auf dem Laborsystem »cf3-centcli« allerdings konnte Systemd Nginx aufgrund eines Nginx-Konfigurationsproblems nicht starten, was der Autor nicht näher untersucht hat. Cfengine 3 wird künftig immer wieder versuchen, Nginx auf dem CentOS-System zu starten.

Abbildung 5: Nach dem ersten Durchlauf von Cfengine auf dem Ubuntu-Client ist Nginx installiert und gestartet.
Wer tiefer in die Materie eintauchen möchte, kann nun die Datei »webserver.cf« um Anweisungen erweitern, was im Fall von nicht erfüllbaren Promises geschehen soll. Außerdem lässt sich Nginx von anderen Systemen aus nur erreichen, wenn man die lokale Firewall öffnet. Das für zwei verschiedene Distributionen via Promise zu konfigurieren, ist gar nicht so einfach und eine weitere mögliche Übungsaufgabe.
Dokumentation und Community
In diesem Artikel wurden eigene Policy-Dateien über die Autorun-Methode eingebunden und ausgeführt. Es gibt aber noch andere Wege, über die Systemadministratoren Bundles und Policies aktivieren können [7].
Spannend wird die Nutzung von Cfengine 3 dann, wenn man auch vorgefertigte Bundles von den Machern und der Community beziehen möchte. Dazu existieren im Netz gleich mehrere Anlaufstellen, wobei das Cfengine Design Center [8] mit seinen sogenannten Sketches zu den bekanntesten gehört. Fertige Bundles sollen Einsteigern Arbeit abnehmen und als Vorlage für eigene Konfigurations-Snippets dienen.
Etwas verwirrend erscheint, dass sich die Cfengine-Dokumentation gleich über mehrere Anlaufstellen verteilt. Auf der offiziellen Webseite http://cfengine.com gibt es einen Quickstart-Guide inklusive Mini-Dokumentation, während auf http://docs.cfengine.com die offizielle Dokumentation liegt. Ein Archiv [9] beherbergt zudem ein Sammelsurium alter Anleitungen, die sich zum Teil eingängiger lesen lassen als die aktuelle Dokumentation.
Wer tiefer in Cfengine 3 eintauchen möchte, der muss etwas Zeit mitbringen. Die Handhabung wirkt teils etwas sperrig, und die vergleichsweise kleine Community macht es schwer, online gute Lernressourcen oder gar Hilfestellung zu bekommen. Es gibt allerdings einige wenige gute Bücher. Die Mitglieder, die sich in der Community engagieren, scheinen schon lange dabei zu sein und alle Tricks zu kennen. Bei seinen Recherchen für diesen Beitrag stolperte der Autor oft über dieselben Namen wie 2012 und 2013 bei seiner Arbeit für frühere Artikel.
Stärken und Schwächen
Seine Stärken spielt Cfengine dort aus, wo es gilt, eine große Zahl von heterogenen Systemen mit möglichst kleinem Fußabdruck zu verwalten. Laut Aussagen aus der Community lassen sich durchaus Umgebungen mit einer Million oder mehr Agenten realisieren, was auch daran liegt, dass man den zentralen Policy Hub kaskadieren kann, etwa mit einem Hub pro RZ.
Läuft es erst einmal, erweist sich Cfengine 3 als mächtige und schlanke Maschine, die von den Anwendungen auf den Zielsystemen kaum Leistung abknapst. Anders als etwa Puppet oder Saltstack setzt der Cfengine-Agent zudem kaum Abhängigkeiten voraus. Die Möglichkeit, Linux, Unix und Windows (in der Enterprise-Variante) über ein gemeinsames Tool zu verwalten, erweist sich in vielen Umgebungen als Vorteil.
Die Schwächen von Cfengine 3 liegen dort, wo der Einstieg schnell und einfach gelingen soll und viele aktuelle Bibliotheken mit vorgefertigten Konfigurations-Snippets voraussetzt. Obendrein ermangelt es Cfengine 3 der Popularität von Puppet und Konsorten, was den Zulauf an neuen Nutzern – und damit neuen Geldern für die Entwicklung – bremsen dürfte.
Wer sich allerdings auf Cfengine 3 einlässt und dem Tool etwas Zeit gibt, kann damit ein solides und funktionierendes Konfigurationsmanagement aufbauen. Wer Experimentierfreude aufbringt, kann zudem einen Blick auf eine Präsentation [10] auf Slideshare werfen, in der die Cfengine-Macher die Orchestrierung von Docker-Containern mittels Cfengine 3 aufzeigen. (uba/jlu)
Der Autor
Valentin Höbel berät bei der Open-i GmbH aus Stuttgart Kunden beim Einsatz von Open-Source-basierender Infrastruktur. In seiner Freizeit informiert er sich über neue Technologien und wirft mit seinem Teleskop einen Blick auf den Nachthimmel.
Infos
- Cfengine 3: https://cfengine.com/product/community/
- Dokumentation der Komponenten: https://docs.cfengine.com/docs/3.15/reference-components.html
- Installation der Community Edition: https://docs.cfengine.com/docs/3.15/guide-installation-and-configuration-general-installation-installation-community.html
- Installationspakete: https://cfengine.com/product/community/
- Dokumentation Cfengine 3: https://docs.cfengine.com/docs/3.15/reference-components.html
- Online-Dokumentation: https://docs.cfengine.com/docs/3.15/reference-masterfiles-policy-framework.html
- Aktivieren von Bundles und Policies: https://docs.cfengine.com/docs/3.15/guide-faq-integrate-custom-policy.html
- Cfengine Design Center: https://docs.cfengine.com/docs/3.10/reference-design-center.html
- Archiv: https://docs.cfengine.com/docs/archive/manuals
- Orchestrieren von Docker-Containern: https://de.slideshare.net/cfengine/the-benefits-of-using-cfengine-with-docker
- Bundle-Typen: https://docs.cfengine.com/docs/archive/manuals/cf3-Reference.html#Bundles-for-agent
- Promise-Typen: https://docs.cfengine.com/docs/3.15/reference-promise-types.html








