Active Directory automatisieren: Benutzer, Gruppen und OUs mit Ansible
TL;DR Active-Directory-Änderungen per GUI oder unversionierten PowerShell-Skripten sind …
azure.azcollection vollständig automatisieren: Benutzer, Gruppen, App-Registrierungen und sogar die Dokumentation Ihrer Conditional Access Policies.Für Windows-Admins und Azure-Admins hat sich das Zentrum der Identitätsverwaltung längst von klassischem On-Prem-AD zu Azure Entra ID verschoben. Benutzer, Gruppen und App-Registrierungen werden heute immer häufiger direkt dort gemanagt – oft aber noch per Portal-Klick.
Das funktioniert, bis eine der folgenden Situationen eintritt:
Automatisierung mit Ansible löst genau diese Probleme:
Mit Polycrate liegt diese Automatisierung nicht als lose Playbooksammlung auf mehreren Laptops, sondern als strukturierter Workspace, inklusive verschlüsselten Secrets und reproduzierbarer Container-Umgebung.
Bevor wir Benutzer und Gruppen in Entra ID anfassen, lohnt sich ein Blick auf das “Wie”.
Das klassische Ansible-Problem für Azure kennen Sie vermutlich:
azure.azcollection zieht eine halbe Azure-SDK-Landschaft nach sich.Polycrate nimmt diesen Schmerz weg:
Dockerfile.poly – dabei leiten Sie immer vom offiziellen Image ab (siehe unten).azure.azcollection) installieren Sie in genau dieser Erweiterung; Python und ansible-core kommen aus dem Basis-Image.Details dazu finden Sie in der Ansible-Integration und den Best Practices.
Ein Dockerfile.poly muss immer vom offiziellen Polycrate-Image ausgehen (cargo.ayedo.cloud/library/polycrate), nicht von einem nackten python:-Image: Polycrate erwartet die mitgelieferte Toolchain, Mounts und Umgebung. Ein reines Python-Image würde als Action-Runtime nicht funktionieren. Hintergrund: Der Polycrate Container.
Zusätzliche Collections installierst du in einer dünnen Schicht darauf. Minimal könnte das so aussehen:
FROM cargo.ayedo.cloud/library/polycrate:latest
# requirements.yml für Collections (z. B. neben Dockerfile.poly im Workspace)
COPY requirements.yml /workspace/requirements.yml
# Azure Collection installieren (Ansible ist bereits im Polycrate-Base-Image)
RUN ansible-galaxy collection install -r /workspace/requirements.yml
WORKDIR /workspaceDie zugehörige requirements.yml:
---
collections:
- name: azure.azcollection
version: 1.18.0Damit steht azure.azcollection im Polycrate-Container für alle Blöcke bereit – keine lokale Installation mehr nötig.
Wir nutzen das Beispiel-Setup acme-corp-automation und legen einen dedizierten Block für Entra ID an.
name: acme-corp-automation
organization: acme
blocks:
- name: entra-id-mgmt
from: registry.acme.corp/blocks/entra-id-mgmt:0.1.0
config:
default_domain: "acme-corp.com"
azure_credentials_file: "artifacts/secrets/azure-sp.json"Wichtig:
from: zeigt hier die Registry-Notation eines Blocks (<registry>/<pfad>:<version>). registry.acme.corp ist nur ein fiktives Beispiel; in der Praxis nutzt du z. B. polycrate blocks pull … oder eure eigene OCI-Registry.workspace.poly und block.poly gibt es kein Jinja2 – azure_credentials_file ist ein fester Pfad zur Datei unter artifacts/secrets/ (nach Entschlüsselung im Container nutzbar). Im Ansible-Playbook greifst du weiter mit {{ block.config.azure_credentials_file }} zu.Im Block-Verzeichnis blocks/entra-id-mgmt legen wir eine block.poly an:
name: entra-id-mgmt
version: 0.1.0
kind: ansible
config:
default_domain: ""
azure_credentials_file: ""
actions:
- name: users
description: "Benutzer in Entra ID verwalten"
playbook: users.yml
- name: groups
description: "Gruppen und Mitgliedschaften verwalten"
playbook: groups.yml
- name: apps
description: "App-Registrierungen und Service Principals verwalten"
playbook: apps.yml
- name: policies
description: "Conditional Access Policies dokumentieren (read-only)"
playbook: policies.ymlUnter config: stehen nur die erwarteten Schlüssel (hier mit leeren Defaults); kein Jinja2 in .poly-Dateien. Die konkreten Werte setzt du bei der Block-Instanz in workspace.poly (siehe oben).
Damit haben wir klare Guardrails:
polycrate run entra-id-mgmt users statt komplexer Ansible-CLI-Aufrufe.Mehr zu Blöcken und Actions finden Sie unter Blöcke und Actions.
Für Entra-ID-Automation brauchen wir einen dedizierten Service Principal.
Je nachdem, was Sie automatisieren, benötigen Sie unterschiedliche Entra-Rollen. Ein gängiges Setup:
User AdministratorGroups AdministratorApplication Administrator oder feiner granulierte App-Registration-BerechtigungenBest Practice:
Legen Sie im Workspace die Datei artifacts/secrets/azure-sp.json an:
{
"client_id": "00000000-0000-0000-0000-000000000000",
"client_secret": "SUPER-GEHEIMER-WERT",
"tenant_id": "11111111-1111-1111-1111-111111111111",
"subscription_id": "22222222-2222-2222-2222-222222222222"
}Konfigurieren Sie diese Datei über secrets.poly als zu verschlüsselndes Secret (Details in der Workspace-Verschlüsselung) und verschlüsseln Sie den Workspace anschließend:
polycrate workspace encryptDamit:
artifacts/secrets/azure-sp.json) bereit.Jetzt wird es konkret: Wir verwalten Entra-ID-Benutzer mit azure.azcollection.azure_rm_aduser.
Die Datei blocks/entra-id-mgmt/users.yml:
---
- name: Benutzer in Entra ID verwalten
hosts: localhost
connection: local
gather_facts: false
vars:
azure_credentials_file: "{{ block.config.azure_credentials_file }}"
default_domain: "{{ block.config.default_domain }}"
tasks:
- name: Azure Service Principal Credentials laden
ansible.builtin.include_vars:
file: "{{ azure_credentials_file }}"
name: azure
- name: Benutzer anlegen oder aktualisieren
azure.azcollection.azure_rm_aduser:
state: present
user_principal_name: "alice@{{ default_domain }}"
display_name: "Alice Example"
password: "InitialPassw0rd!"
account_enabled: true
force_password_change: true
tenant: "{{ azure.tenant_id }}"
client_id: "{{ azure.client_id }}"
secret: "{{ azure.client_secret }}"
auth_source: client_secret
register: alice_result
- name: Benutzer deaktivieren (Beispiel)
azure.azcollection.azure_rm_aduser:
state: present
user_principal_name: "bob@{{ default_domain }}"
display_name: "Bob Example"
account_enabled: false
tenant: "{{ azure.tenant_id }}"
client_id: "{{ azure.client_id }}"
secret: "{{ azure.client_secret }}"
auth_source: client_secret
- name: Benutzer löschen (Beispiel)
azure.azcollection.azure_rm_aduser:
state: absent
user_principal_name: "temp.user@{{ default_domain }}"
tenant: "{{ azure.tenant_id }}"
client_id: "{{ azure.client_id }}"
secret: "{{ azure.client_secret }}"
auth_source: client_secret
- name: Kurze Zusammenfassung ausgeben
ansible.builtin.debug:
msg: "Benutzerverwaltung abgeschlossen. Alice-Änderung: {{ alice_result.changed }}"Wichtig:
hosts: localhost und connection: local sind hier korrekt – das Playbook läuft im Polycrate-Container und spricht die Azure-APIs, nicht einen SSH-Host.block.poly oder im Playbook hinterlegt.Ausführen der Action:
polycrate run entra-id-mgmt usersMit plain Ansible müssten Sie dafür sorgen, dass lokal:
azure.azcollection und alle Abhängigkeiten installiert sind.Mit Polycrate reicht es, den Workspace zu clonen, polycrate run zu nutzen, und alles läuft im definierten Container.
Gruppen sind das Herzstück von Berechtigungen in Entra ID. Das Prinzip ist identisch: deklarativ beschreiben, welche Gruppen existieren und welche Mitglieder dazugehören.
---
- name: Gruppen in Entra ID verwalten
hosts: localhost
connection: local
gather_facts: false
vars:
azure_credentials_file: "{{ block.config.azure_credentials_file }}"
default_domain: "{{ block.config.default_domain }}"
tasks:
- name: Azure Service Principal Credentials laden
ansible.builtin.include_vars:
file: "{{ azure_credentials_file }}"
name: azure
- name: Sicherheitsgruppe "HR-Staff" sicherstellen
azure.azcollection.azure_rm_adgroup:
state: present
display_name: "HR-Staff"
mail_nickname: "hr-staff"
security_enabled: true
description: "HR Mitarbeiter"
tenant: "{{ azure.tenant_id }}"
client_id: "{{ azure.client_id }}"
secret: "{{ azure.client_secret }}"
auth_source: client_secret
register: hr_group
- name: Mitglieder in HR-Staff pflegen
azure.azcollection.azure_rm_adgroup:
state: present
display_name: "HR-Staff"
security_enabled: true
members:
# Beispiel UPNs, in der Praxis besser Object IDs verwenden
- "alice@{{ default_domain }}"
tenant: "{{ azure.tenant_id }}"
client_id: "{{ azure.client_id }}"
secret: "{{ azure.client_secret }}"
auth_source: client_secret
- name: Gruppe "Legacy-Group" löschen (falls noch vorhanden)
azure.azcollection.azure_rm_adgroup:
state: absent
display_name: "Legacy-Group"
tenant: "{{ azure.tenant_id }}"
client_id: "{{ azure.client_id }}"
secret: "{{ azure.client_secret }}"
auth_source: client_secretAusführen:
polycrate run entra-id-mgmt groupsSo entsteht ein reproduzierbarer Zielzustand für Ihre Gruppen. Änderungen laufen über Pull-Requests und die Git-History dokumentiert, wann welche Gruppen angepasst wurden.
Viele Windows-/Azure-Teams haben Dutzende App-Registrierungen: Skripte, Automatisierungs-Accounts, Drittanbieter-Anwendungen. Diese manuell im Portal anzulegen, ist fehleranfällig.
---
- name: App-Registrierungen in Entra ID verwalten
hosts: localhost
connection: local
gather_facts: false
vars:
azure_credentials_file: "{{ block.config.azure_credentials_file }}"
tasks:
- name: Azure Service Principal Credentials laden
ansible.builtin.include_vars:
file: "{{ azure_credentials_file }}"
name: azure
- name: Anwendung "acme-hr-portal" registrieren
azure.azcollection.azure_rm_adapplication:
state: present
display_name: "acme-hr-portal"
identifier_uris:
- "api://acme-hr-portal"
reply_urls:
- "https://hr.acme-corp.com/auth/callback"
available_to_other_tenants: false
tenant: "{{ azure.tenant_id }}"
client_id: "{{ azure.client_id }}"
secret: "{{ azure.client_secret }}"
auth_source: client_secret
register: hr_app
- name: Service Principal für "acme-hr-portal" sicherstellen
azure.azcollection.azure_rm_adserviceprincipal:
state: present
app_id: "{{ hr_app.object_id }}"
tenant: "{{ azure.tenant_id }}"
client_id: "{{ azure.client_id }}"
secret: "{{ azure.client_secret }}"
auth_source: client_secret
- name: App-Details anzeigen
ansible.builtin.debug:
msg: "App acme-hr-portal registriert mit Object ID {{ hr_app.object_id }}"Ausführen:
polycrate run entra-id-mgmt appsDamit können Sie:
Conditional Access Policies sind sicherheitskritisch. Änderungen daran sollten nachvollziehbar und dokumentiert sein. Anstelle von manuellen Screenshots oder Excel-Listen können Sie diese mit Ansible auslesen und als JSON im Repository ablegen.
Ein vereinfachtes Beispiel für policies.yml, das die bestehenden Policies per Microsoft Graph ausliest und in einer Datei dokumentiert. Hier gehen wir davon aus, dass Sie ein Access-Token außerhalb des Playbooks erzeugen und im Secret ablegen (z.B. per kleinem Hilfsskript).
---
- name: Conditional Access Policies dokumentieren
hosts: localhost
connection: local
gather_facts: false
vars:
azure_credentials_file: "{{ block.config.azure_credentials_file }}"
tasks:
- name: Azure Service Principal Daten laden (inkl. access_token)
ansible.builtin.include_vars:
file: "{{ azure_credentials_file }}"
name: azure
- name: Conditional Access Policies via Microsoft Graph abrufen
ansible.builtin.uri:
url: "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies"
method: GET
headers:
Authorization: "Bearer {{ azure.access_token }}"
Content-Type: "application/json"
return_content: true
register: ca_policies
- name: Policies in Datei schreiben
ansible.builtin.copy:
dest: "artifacts/entra-id/conditional-access-policies.json"
content: "{{ ca_policies.content }}"Ausführen:
polycrate run entra-id-mgmt policiesDer wichtige Punkt:
Compliance-Anforderungen (z.B. aus der DSGVO, die seit dem 25.05.2018 gilt, oder aus internen Richtlinien) verlangen nachvollziehbare Prozesse:
Mit Polycrate + Ansible + Git bekommen Sie das quasi “by design”:
Statt manueller Excel-Listen oder Screenshots erhalten Sie eine saubere, technische Nachvollziehbarkeit.
Nein. Als Windows- oder Azure-Admin müssen Sie kein Linux-Experte sein. Polycrate kapselt die Linux-/Container-Seite in Dockerfile.poly. Sie arbeiten hauptsächlich mit YAML (Ansible-Playbooks, workspace.poly, block.poly) und führen Aktionen mit einfachen Befehlen wie:
polycrate run entra-id-mgmt usersDie Container-Laufzeit kümmert sich um Python, Ansible, azure.azcollection und alle Abhängigkeiten.
Weil Ihre Automatisierung:
azure.azcollection mit einer konkreten Version in requirements.yml gepinnt ist,haben Sie einen stabilen Stand. Updates passieren kontrolliert:
So vermeiden Sie Überraschungen bei spontanen Modul- oder API-Änderungen.
Polycrate ersetzt weder Ihr AD noch Azure selbst. Es ist die Schicht darüber, die:
Sie können Polycrate schrittweise einführen – z.B. zunächst nur für Entra-ID-User-Management, später für weitere Azure- oder On-Prem-Aufgaben.
Weitere Fragen? Siehe unsere FAQ
In diesem Beitrag haben Sie gesehen, wie Sie Entra ID mit Ansible und Polycrate strukturiert automatisieren:
azure.azcollection läuft in einem klar definierten Container, der das klassische Dependency-Problem von Ansible auflöst.Bei ayedo kombinieren wir genau diese Bausteine regelmäßig in Kundenprojekten: Polycrate-Workspaces, Ansible-Playbooks mit azure.azcollection, verschlüsselte Secrets und Git-basierte Prozesse. Für Windows- und Azure-Teams entsteht so ein Werkzeugkasten, mit dem sie eigenständig und sicher ihr Entra-ID-Management modernisieren können – ohne sich erst durch die komplette Cloud-Native-Welt kämpfen zu müssen.
Wenn Sie Ihre bestehende Entra-ID-Landschaft aufnehmen, automatisieren und gleichzeitig Compliance-Anforderungen sauber adressieren möchten, unterstützen wir Sie dabei in einem fokussierten Azure-Automatisierungs-Workshop – mit Ihrem Tenant, Ihren Richtlinien und Ihren Tools.
TL;DR Active-Directory-Änderungen per GUI oder unversionierten PowerShell-Skripten sind …
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 …