Azure Entra ID automatisieren: Benutzer, Gruppen und Apps mit Ansible
TL;DR Ansible kann Azure Entra ID (ehem. Azure AD) über die azure.azcollection vollständig …
community.windows.win_domain_user, community.windows.win_domain_group und community.windows.win_domain_ou verwaltet – inklusive CSV-basiertem Bulk-Onboarding und Offboarding-Playbook mit Audit-Log.polycrate workspace sync automatisch committet: Ein sauberer Audit-Trail für Compliance-Anforderungen wie die DSGVO, die seit dem 25.05.2018 gilt.Wenn Sie heute ein klassisches Active Directory verwalten, sieht der Alltag oft so aus:
Das funktioniert, solange Sie wenige Changes haben und die gleichen zwei Personen alles machen. Spätestens wenn Teams wachsen, Audits dazukommen oder mehrere Standorte entstehen, wird es schwierig:
Mit plain Ansible wird zwar einiges besser – Sie bekommen Idempotenz, verständliche YAML-Playbooks und ein mächtiges Ökosystem. Aber:
community.windows) auf jeder Maschine sauber installieren.Genau hier setzt Polycrate an.
Polycrate macht aus Ihren Ansible-Playbooks versionierte, teilbare Blöcke und löst dabei mehrere typische Probleme:
community.windows) werden im Container-Image definiert. Kein lokales Ansible, kein Python-Wirrwarr, weniger Supply-Chain-Risiko. Mehr dazu in der Ansible-Integration von Polycrate.from: ein (siehe Workspace-Beispiel unten).polycrate workspace sync (siehe Git-Integration von Polycrate).Wir bauen im Folgenden einen Workspace mit einem AD-Management-Block, der:
Zuerst legen wir den Workspace acme-corp-automation an und definieren unseren AD-Block sowie das Inventory.
name: acme-corp-automation
organization: acme
blocks:
- name: ad-mgmt
from: registry.acme-corp.com/acme/infra/ad-mgmt:1.0.0
config:
domain_name: "acme-corp.com"
default_ou: "OU=Users,DC=acme-corp,DC=com"from: enthält die vollständige OCI-Registry-Referenz inklusive Versions-Tag am Ende der Zeile (wie bei Container-Images); ein separates version-Feld unter der Block-Instanz gibt es nicht. Im Block-Paket trägt block.poly denselben logischen Namen (ad-mgmt). Die Registry registry.acme-corp.com ist ein Beispiel (kein Bezug zu ayedos Produkt-Registry). Fehlt der Block lokal, kann Polycrate ihn beim ersten polycrate run … aus der Registry nachziehen; ausgepackt liegt er unter blocks/registry.acme-corp.com/acme/infra/ad-mgmt/. Mehr dazu im Beitrag Multi-Server-Management mit Ansible-Inventories.
Mehr zu Workspaces finden Sie in der Dokumentation zu Polycrate Workspaces.
Polycrate erwartet ein YAML-Inventory im Workspace-Root als inventory.yml. Alle Hosts stehen unter all.hosts; unter children verweist die Gruppe domain_controllers nur noch per Hostname – gemeinsame WinRM-Einstellungen liegen in vars der Gruppe. Keine Passwörter im Inventory – ansible_password setzen Sie in den Playbooks aus secrets.poly / workspace.secrets.* (siehe Workspace-Verschlüsselung). Für einen Domain Controller dc01.acme-corp.com kann das so aussehen:
all:
hosts:
dc01.acme-corp.com: {}
children:
domain_controllers:
hosts:
dc01.acme-corp.com:
vars:
ansible_user: Administrator
ansible_connection: winrm
ansible_port: 5986
ansible_winrm_transport: credssp
ansible_winrm_server_cert_validation: ignoreWichtig:
secrets.poly und werden in den Playbooks als Variablen eingebunden, nicht als Klartext im inventory.yml.polycrate workspace encrypt (siehe Workspace-Verschlüsselung).WinRM-Passwort für die Playbooks: In secrets.poly legen Sie z. B. ad_dc_password ab; in jedem Play gegen domain_controllers setzen Sie darunter vars: zusätzlich ansible_password: "{{ workspace.secrets.ad_dc_password }}" (die folgenden Beispiele enthalten das).
Unser Block blocks/registry.acme-corp.com/acme/infra/ad-mgmt/block.poly (nach dem Pull aus der Registry) kapselt alle AD-Aktivitäten:
name: ad-mgmt
version: 0.1.0
kind: generic
config:
domain_name: "acme-corp.com"
default_ou: "OU=Users,DC=acme-corp,DC=com"
users_csv: "users.csv"
audit_log: "audit.log"
actions:
- name: setup_ou_and_groups
playbook: setup_ou_and_groups.yml
- name: onboarding
playbook: onboarding.yml
- name: offboarding
playbook: offboarding.ymlconfig.*-Werte können Sie im Workspace bei Bedarf überschreiben.blocks/…). Laufzeitdaten wie CSV und Audit-Log legen Sie nicht im Block ab, sondern unter artifacts/blocks/<Block-Instanzname>/ im Workspace – z. B. artifacts/blocks/ad-mgmt/users.csv. In Ansible zeigt block.artifacts.path auf genau dieses Verzeichnis (im Container: /workspace/artifacts/blocks/<name>/).Weitere Details zu Blocken finden Sie in den Polycrate Blocke-Docs.
Legen Sie die Datei im Workspace unter artifacts/blocks/ad-mgmt/users.csv an (nicht im Block-Verzeichnis unter blocks/…). Polycrate stellt den Pfad in Playbooks als {{ block.artifacts.path }} bereit (entspricht artifacts/blocks/ad-mgmt/ im Workspace).
username;givenName;sn;password;enabled;ou_dn;groups
jdoe;John;Doe;Start123!;true;OU=IT,OU=Users,DC=acme-corp,DC=com;IT-Admins,VPN-Users
mroe;Maria;Roe;Start123!;true;;Sales,VPN-Usersou_dn ist optional – fehlt er, verwenden wir default_ou.groups ist eine durch Komma getrennte Liste.win_domain_user und win_domain_groupDas Onboarding besteht aus zwei Plays:
# blocks/registry.acme-corp.com/acme/infra/ad-mgmt/onboarding.yml
- name: Load users from CSV in Polycrate container
hosts: localhost
gather_facts: false
vars:
users_csv: "{{ block.artifacts.path }}/{{ block.config.users_csv }}"
tasks:
- name: Read users from CSV
community.general.read_csv:
path: "{{ users_csv }}"
delimiter: ";"
register: csv_users
- name: Normalize user list
ansible.builtin.set_fact:
ad_users: "{{ csv_users.list }}"
- name: Create OUs and groups on domain controllers
hosts: domain_controllers
gather_facts: false
vars:
ansible_password: "{{ workspace.secrets.ad_dc_password }}"
domain_name: "{{ block.config.domain_name }}"
default_ou: "{{ block.config.default_ou }}"
tasks:
- name: Ensure base OU exists
community.windows.win_domain_ou:
name: "{{ default_ou }}"
state: present
- name: Ensure department OUs from CSV exist
community.windows.win_domain_ou:
name: "{{ item.ou_dn }}"
state: present
loop: "{{ hostvars['localhost'].ad_users | map(attribute='ou_dn') | list | unique }}"
when: item.ou_dn is defined and item.ou_dn | length > 0
- name: Collect all group names from CSV
ansible.builtin.set_fact:
all_groups: >-
{{ hostvars['localhost'].ad_users
| map(attribute='groups')
| select('defined')
| map('split', ',')
| sum(start=[])
| map('trim')
| reject('equalto', '')
| list }}
run_once: true
- name: Ensure groups exist
community.windows.win_domain_group:
name: "{{ item }}"
scope: global
state: present
loop: "{{ all_groups | default([]) }}"
run_once: true
- name: Ensure AD users exist and are in the right groups
community.windows.win_domain_user:
name: "{{ item.username }}"
upn: "{{ item.username }}@{{ domain_name }}"
given_name: "{{ item.givenName }}"
surname: "{{ item.sn }}"
password: "{{ item.password }}"
enabled: "{{ (item.enabled | default('true')) | bool }}"
path: "{{ item.ou_dn | default(default_ou) }}"
state: present
groups: >-
{{ (item.groups | default(''))
| split(',')
| map('trim')
| reject('equalto', '')
| list }}
loop: "{{ hostvars['localhost'].ad_users }}"
run_once: trueWas passiert hier?
community.general.read_csv läuft auf localhost im Polycrate-Container. Es verändert keine Zielsysteme, daher ist hosts: localhost hier korrekt.community.windows.win_domain_ou legen wir zunächst eine Basis-OU an und dann ggf. zusätzliche OUs aus den CSV-Daten.community.windows.win_domain_group erstellt alle in der CSV referenzierten Gruppen.community.windows.win_domain_user legt Benutzer an oder aktualisiert sie idempotent, inklusive OU, Passwort, Status und Gruppen.Mit plain Ansible ohne Polycrate müssten Sie:
community.windows überall gleich verfügbar ist.Mit Polycrate reicht ein strukturierter Block und ein reproduzierbarer Container.
Vom Workspace-Root aus:
cd ~/workspaces/acme-corp-automation
polycrate run ad-mgmt onboardingPolycrate kümmert sich um:
Beim Offboarding wollen Sie:
# blocks/registry.acme-corp.com/acme/infra/ad-mgmt/offboarding.yml
- name: Disable AD user and clean up group memberships
hosts: domain_controllers
gather_facts: false
vars:
ansible_password: "{{ workspace.secrets.ad_dc_password }}"
domain_name: "{{ block.config.domain_name }}"
disabled_ou: "OU=Disabled Users,DC=acme-corp,DC=com"
username: "{{ username }}"
tasks:
- name: Ensure OU for disabled users exists
community.windows.win_domain_ou:
name: "{{ disabled_ou }}"
state: present
- name: Disable user and move to disabled OU
community.windows.win_domain_user:
name: "{{ username }}"
upn: "{{ username }}@{{ domain_name }}"
enabled: false
path: "{{ disabled_ou }}"
state: present
- name: Remove user from sensitive groups
community.windows.win_domain_group:
name: "{{ item }}"
state: present
members:
- "{{ username }}"
members_state: absent
loop:
- "IT-Admins"
- "Domain Admins"
- "VPN-Users"
- name: Write audit log entry in Polycrate workspace
hosts: localhost
gather_facts: false
vars:
audit_log: "{{ block.artifacts.path }}/{{ block.config.audit_log }}"
tasks:
- name: Append audit log entry
ansible.builtin.lineinfile:
path: "{{ audit_log }}"
line: "{{ lookup('ansible.builtin.pipe', 'date -u +%Y-%m-%dT%H:%M:%SZ') }};{{ username }};offboarded"
create: yes
insertafter: EOFHinweise:
localhost) und schreibt ins audit.log unter {{ block.artifacts.path }} (Workspace: artifacts/blocks/ad-mgmt/). Dieses File ist Teil des Workspaces und wird damit versioniert und verschlüsselt.Den Benutzer über ein Extra-Var übergeben:
cd ~/workspaces/acme-corp-automation
polycrate run ad-mgmt offboarding -- -e "username=jdoe"Der Doppelstrich -- trennt die Polycrate-Argumente von den Argumenten, die an ansible-playbook gehen.
Die eigentliche Stärke für Compliance entsteht durch die Kombination:
Nach einem Onboarding- oder Offboarding-Lauf:
users.csv geändert (z. B. neue Benutzer).audit.log um einen Eintrag erweitert.Mit Polycrate halten Sie den Workspace synchron zu Git, z. B.:
cd ~/workspaces/acme-corp-automation
polycrate workspace syncPolycrate:
Details dazu finden Sie in der Git-Integration von Polycrate.
Der Compliance-Vorteil gegenüber GUI-Klicks oder losen PowerShell-Skripten:
audit.log bietet eine zusätzliche, menschenlesbare Übersicht („wann wurde welcher Benutzer offboarded?“).In Audits oder bei forensischen Analysen ist das Gold wert.
Sie entwickeln den Block im Workspace unter dem registry-kompatiblen Verzeichnis, das zu Ihrer späteren from:-Referenz passt – z. B. blocks/registry.acme-corp.com/acme/infra/ad-mgmt/ (Registry-Host und Pfad wie in der OCI-Referenz ohne Versionstag), nicht unter einem verkürzten Pfad wie ./blocks/ad-mgmt/. Anschließend veröffentlichen Sie ihn in Ihrer OCI-Registry oder im PolyHub – andere Workspaces beziehen ihn dann mit vollständiger from:-Referenz und Versionstag, wie im ersten workspace.poly-Beispiel. Dasselbe Verzeichnisprinzip gilt für die Polycrate-Registry cargo (blocks/cargo.ayedo.cloud/…). Alternativ (oder zusätzlich) nutzen Sie z. B. cargo in from: – Beispiel:
blocks:
- name: ad-mgmt
from: cargo.ayedo.cloud/acme/infra/ad-mgmt:0.1.0
config:
domain_name: "acme-corp.com"
default_ou: "OU=Users,DC=acme-corp,DC=com"Dadurch:
0.2.0) ausrollen, ohne bestehende Workspaces zu brechen.Mehr dazu in der Dokumentation zu Registry und PolyHub.
Nein. Polycrate bringt ein Container-Image mit, in dem Ansible, Python und benötigte Collections wie community.windows bereits installiert sind. Sie führen nur polycrate run ... aus, Polycrate startet den Container, bindet den Workspace ein und ruft ansible-playbook im Container auf.
Vorteile:
Der Workspace kann mit polycrate workspace encrypt über age verschlüsselt werden. Damit lassen sich Dateien wie:
secrets.poly und verschlüsselte Artefakte (AD-Credentials, keine Klartext-Passwörter im inventory.yml)verschlüsselt im Git-Repository ablegen. Nur berechtigte Personen mit den passenden Schlüsseln können den Workspace entschlüsseln.
Details finden Sie in der Dokumentation zur Workspace-Verschlüsselung.
Ja. Über blocks.config im workspace.poly können Sie pro Workspace (oder sogar pro Umgebung) andere Parameter setzen, z. B.:
domain_namedefault_ouFür Test- und Produktionsumgebungen legen Sie einfach getrennte Workspaces an, die denselben Block aus der Registry referenzieren, aber andere Konfigurationen und Inventories haben. So bleibt die Logik identisch, während Ziele und Daten je Umgebung variieren.
Weitere Fragen? Siehe unsere FAQ
Mit dem hier gezeigten AD-Block haben Sie einen wichtigen Schritt getan:
polycrate workspace sync und das Audit-Log entstehen prüfbare Spuren, die bei Audits, Pen-Tests oder internen Kontrollen überzeugen.Als ayedo begleiten wir Organisationen dabei, genau solche Automatisierungen systematisch aufzubauen – von der ersten AD-Action bis zu ganzen Landschaften aus standardisierten Polycrate-Blöcken. Ob Sie „nur“ das Onboarding/Offboarding verbessern oder ein umfassendes Policy-as-Code-Modell für Ihr Active Directory etablieren wollen: Wir bringen die Erfahrung aus Platform Engineering, Windows- und Compliance-Projekten zusammen.
Wenn Sie sehen möchten, wie dieses Setup in Ihrer Umgebung aussehen kann und welche Erweiterungen (z. B. automatische GPO-Zuordnung oder Integration in Ihr HR-System) sinnvoll sind, lohnt sich ein gemeinsamer Blick auf Ihre Anforderungen:
TL;DR Ansible kann Azure Entra ID (ehem. Azure AD) über die azure.azcollection vollständig …
TL;DR Du baust einen wiederverwendbaren Polycrate-Workflow, der auf deinen Linux-Servern automatisch …
TL;DR Ansible ist ein starkes Fundament: agentless, idempotent, menschenlesbares YAML und ein …