AI Gateway im Kubernetes-Ökosystem:
Warum die nächste Evolutionsstufe der Plattform bereits begonnen hat Die Diskussion rund um …
azure.azcollection automatisiert bereitgestellt – sauber gekapselt in Polycrate-Blöcken, ohne lokale Python- oder Ansible-Installation.inventory.yml, sodass Sie direkt danach via polycrate ssh (Linux) bzw. WinRM (Windows) weiterkonfigurieren können.Viele Teams stehen irgendwo zwischen klassischem Rechenzentrum und Cloud: ein paar hundert Linux-Server On-Premise, ein Active Directory auf Windows Server, dazu einige Workloads in Azure. Genau hier spielt Polycrate seine Stärken aus:
Die Azure-Anbindung nutzt die Ansible-Integration von Polycrate. Die Azure-Module (azure.azcollection) laufen innerhalb des Polycrate-Containers und sprechen die Azure-APIs direkt an (hosts: localhost, connection: local ist hier korrekt – es wird keine VM per SSH/WinRM angesprochen, sondern nur das Azure Control Plane).
Ein zentrales Ziel dieses Beitrags: Das dynamische Inventory. Neu erstellte Azure-VMs landen automatisch in inventory.yml im Workspace-Root – gemeinsam mit Ihren On-Premise-Hosts. Damit können Sie im nächsten Schritt direkt mit denselben Ansible-Rollen weiterarbeiten, die Sie heute bereits On-Premise nutzen.
Zunächst definieren wir einen minimalen Workspace mit On-Premise-Hosts und Azure-Blöcken.
# workspace.poly
name: acme-corp-automation
organization: acme
blocks:
- name: azure-infra
from: registry.acme-corp.com/acme/infra/azure-infra:0.1.0
config:
subscription_id: "00000000-0000-0000-0000-000000000000"
location: "westeurope"
resource_group: "rg-acme-hybrid"
vnet_name: "vnet-acme-hybrid"
address_prefix: "10.50.0.0/16"
- name: azure-vms
from: registry.acme-corp.com/acme/infra/azure-vms:0.1.0
config:
subscription_id: "00000000-0000-0000-0000-000000000000"
location: "westeurope"
resource_group: "rg-acme-hybrid"
vnet_name: "vnet-acme-hybrid"
subnet_name: "default"
admin_username: "acmeadmin"
- name: azure-cost-control
from: registry.acme-corp.com/acme/infra/azure-cost-control:0.1.0
config:
subscription_id: "00000000-0000-0000-0000-000000000000"
resource_group: "rg-acme-hybrid"
tag_filter: "env=dev"
- name: azure-backup
from: registry.acme-corp.com/acme/infra/azure-backup:0.1.0
config:
subscription_id: "00000000-0000-0000-0000-000000000000"
resource_group: "rg-acme-backup"
storage_account: "acmehybridbackup"Die Blöcke liegen nicht als lose blocks/<name>-Verzeichnisse im Workspace, sondern werden per from: aus einer OCI-Registry bezogen (registry.acme-corp.com/... ist ein fiktives Beispiel; in der Praxis nutzen Sie z. B. polycrate blocks pull … oder Ihre eigene Registry). from: enthält die vollständige Referenz inklusive Versions-Tag. In workspace.poly und block.poly gibt es kein Jinja2 – Pfade zu Dateien unter artifacts/secrets/ tragen Sie als literale Strings in der Block-config ein; das lokale Admin-Passwort für Azure-Windows-VMs gehört wie im Hybrid-Artikel in secrets.poly (Merge in block.config). Details: Konfiguration.
secrets.poly (Auszug, wird mit workspace.poly gemerged):
blocks:
- name: azure-vms
config:
win_admin_password: "…"Unser gemeinsames Inventory liegt im Workspace-Root als inventory.yml. Wie im Multi-Server-Artikel und im Hybrid-Artikel stehen alle Hosts einmal unter all.hosts; unter children ordnen wir sie den Gruppen onprem_linux, onprem_windows, azure_linux und azure_windows zu – damit nutzen Ansible und polycrate ssh dieselbe kanonische Hostliste. Zunächst tragen wir nur On-Premise-Server ein; die Azure-Gruppen bleiben leer, bis die Inventory-Action läuft:
# inventory.yml (Workspace-Root)
all:
vars:
ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
ansible_python_interpreter: /usr/bin/python3
hosts:
server01.acme-corp.com:
ansible_user: ubuntu
dc01.acme-corp.com: {}
children:
onprem_linux:
hosts:
server01.acme-corp.com:
onprem_windows:
hosts:
dc01.acme-corp.com:
vars:
ansible_connection: winrm
ansible_winrm_transport: ntlm
ansible_winrm_server_cert_validation: ignore
azure_linux:
hosts: {}
azure_windows:
hosts: {}
vars:
ansible_connection: winrm
ansible_winrm_transport: ntlm
ansible_winrm_server_cert_validation: ignorePolycrate setzt ANSIBLE_INVENTORY automatisch auf dieses File. Weitere Details finden sich in den Best Practices.
Der erste Block kümmert sich um Resource Group und Virtual Network.
# blocks/registry.acme-corp.com/acme/infra/azure-infra/block.poly
# name = from: ohne Tag (vollständiger Registry-Pfad)
name: registry.acme-corp.com/acme/infra/azure-infra
version: 0.1.0
kind: generic
config:
azure_credentials_path: "artifacts/secrets/azure-credentials.json"
subscription_id: ""
location: "westeurope"
resource_group: "rg-acme-hybrid"
vnet_name: "vnet-acme-hybrid"
address_prefix: "10.50.0.0/16"
subnet_name: "default"
subnet_prefix: "10.50.1.0/24"
actions:
- name: provision
driver: ansible
playbook: provision.ymlDie Azure-Anmeldeinformationen (z. B. ein Service Principal im JSON-Format) liegen verschlüsselt im Workspace unter artifacts/secrets/azure-credentials.json. Die Verschlüsselung erfolgt mit age direkt in Polycrate – Details dazu unter Workspace-Verschlüsselung.
# …/azure-infra/provision.yml
- name: Azure Resource Group und Netzwerk provisionieren
hosts: localhost
connection: local
gather_facts: false
vars:
azure_credentials_path: "{{ block.config.azure_credentials_path }}"
subscription_id: "{{ block.config.subscription_id }}"
location: "{{ block.config.location }}"
resource_group: "{{ block.config.resource_group }}"
vnet_name: "{{ block.config.vnet_name }}"
address_prefix: "{{ block.config.address_prefix }}"
subnet_name: "{{ block.config.subnet_name }}"
subnet_prefix: "{{ block.config.subnet_prefix }}"
pre_tasks:
- name: Azure Anmeldeinformationen laden
set_fact:
azure_credentials: "{{ lookup('file', azure_credentials_path) | from_json }}"
tasks:
- name: Resource Group erstellen
azure.azcollection.azure_rm_resourcegroup:
subscription_id: "{{ subscription_id }}"
tenant: "{{ azure_credentials.tenant }}"
client_id: "{{ azure_credentials.client_id }}"
secret: "{{ azure_credentials.client_secret }}"
name: "{{ resource_group }}"
location: "{{ location }}"
- name: Virtual Network erstellen
azure.azcollection.azure_rm_virtualnetwork:
subscription_id: "{{ subscription_id }}"
tenant: "{{ azure_credentials.tenant }}"
client_id: "{{ azure_credentials.client_id }}"
secret: "{{ azure_credentials.client_secret }}"
resource_group: "{{ resource_group }}"
name: "{{ vnet_name }}"
address_prefixes:
- "{{ address_prefix }}"
- name: Subnet anlegen
azure.azcollection.azure_rm_subnet:
subscription_id: "{{ subscription_id }}"
tenant: "{{ azure_credentials.tenant }}"
client_id: "{{ azure_credentials.client_id }}"
secret: "{{ azure_credentials.client_secret }}"
resource_group: "{{ resource_group }}"
name: "{{ subnet_name }}"
address_prefix: "{{ subnet_prefix }}"
virtual_network_name: "{{ vnet_name }}"Ausführung:
polycrate run azure-infra provisionMit plain Ansible müssten Sie hier zuerst lokal die azure.azcollection installieren, Python-Versionen abstimmen und ansible.cfg passend konfigurieren. Mit Polycrate läuft dieses Playbook reproduzierbar im Container – inklusive der passenden Azure-Module.
# blocks/registry.acme-corp.com/acme/infra/azure-vms/block.poly
name: registry.acme-corp.com/acme/infra/azure-vms
version: 0.1.0
kind: generic
config:
azure_credentials_path: "artifacts/secrets/azure-credentials.json"
subscription_id: ""
location: "westeurope"
resource_group: "rg-acme-hybrid"
vnet_name: "vnet-acme-hybrid"
subnet_name: "default"
admin_username: "acmeadmin"
ssh_public_key_path: "artifacts/secrets/azure-ssh.pub"
actions:
- name: provision
driver: ansible
playbook: provision.yml
- name: inventory
driver: ansible
playbook: inventory.ymlDas Windows-Admin-Passwort für die VM-Erstellung kommt aus secrets.poly (siehe oben) und steht im Playbook nach dem Merge als block.config.win_admin_password zur Verfügung.
# …/azure-vms/provision.yml
- name: Azure Linux- und Windows-VMs bereitstellen
hosts: localhost
connection: local
gather_facts: false
vars:
azure_credentials_path: "{{ block.config.azure_credentials_path }}"
subscription_id: "{{ block.config.subscription_id }}"
location: "{{ block.config.location }}"
resource_group: "{{ block.config.resource_group }}"
vnet_name: "{{ block.config.vnet_name }}"
subnet_name: "{{ block.config.subnet_name }}"
admin_username: "{{ block.config.admin_username }}"
ssh_public_key: "{{ lookup('file', block.config.ssh_public_key_path) }}"
win_admin_password: "{{ block.config.win_admin_password }}"
linux_vms:
- name: "vm-ubuntu-01"
size: "Standard_B2s"
windows_vms:
- name: "vm-win-01"
size: "Standard_B2s"
pre_tasks:
- name: Azure Anmeldeinformationen laden
set_fact:
azure_credentials: "{{ lookup('file', azure_credentials_path) | from_json }}"
tasks:
- name: Linux-VMs erstellen
azure.azcollection.azure_rm_virtualmachine:
subscription_id: "{{ subscription_id }}"
tenant: "{{ azure_credentials.tenant }}"
client_id: "{{ azure_credentials.client_id }}"
secret: "{{ azure_credentials.client_secret }}"
resource_group: "{{ resource_group }}"
name: "{{ item.name }}"
vm_size: "{{ item.size }}"
admin_username: "{{ admin_username }}"
ssh_password_enabled: false
ssh_public_keys:
- path: "/home/{{ admin_username }}/.ssh/authorized_keys"
key_data: "{{ ssh_public_key }}"
image:
offer: "0001-com-ubuntu-server-jammy"
publisher: "Canonical"
sku: "22_04-lts"
version: "latest"
os_type: "Linux"
state: present
started: true
network_interfaces:
- name: "{{ item.name }}-nic"
virtual_network: "{{ vnet_name }}"
subnet: "{{ subnet_name }}"
public_ip_allocation_method: "Dynamic"
loop: "{{ linux_vms }}"
- name: Windows-VMs erstellen
azure.azcollection.azure_rm_virtualmachine:
subscription_id: "{{ subscription_id }}"
tenant: "{{ azure_credentials.tenant }}"
client_id: "{{ azure_credentials.client_id }}"
secret: "{{ azure_credentials.client_secret }}"
resource_group: "{{ resource_group }}"
name: "{{ item.name }}"
vm_size: "{{ item.size }}"
admin_username: "azureadmin"
admin_password: "{{ win_admin_password }}"
image:
offer: "WindowsServer"
publisher: "MicrosoftWindowsServer"
sku: "2022-Datacenter"
version: "latest"
os_type: "Windows"
state: present
started: true
network_interfaces:
- name: "{{ item.name }}-nic"
virtual_network: "{{ vnet_name }}"
subnet: "{{ subnet_name }}"
public_ip_allocation_method: "Dynamic"
loop: "{{ windows_vms }}"Ausführung:
polycrate run azure-vms provisionAlle Module stammen aus azure.azcollection. Polycrate bringt die passende Toolchain im Container mit – Sie müssen weder pip install noch ansible-galaxy collection install auf Ihrem Laptop pflegen.
Jetzt kommt der spannende Teil: Wir wollen, dass die frisch erstellten VMs automatisch in der inventory.yml landen – in den Gruppen azure_linux und azure_windows.
# …/azure-vms/inventory.yml
- name: Azure-VMs ins Inventory schreiben
hosts: localhost
connection: local
gather_facts: false
vars:
azure_credentials_path: "{{ block.config.azure_credentials_path }}"
subscription_id: "{{ block.config.subscription_id }}"
resource_group: "{{ block.config.resource_group }}"
pre_tasks:
- name: Azure Anmeldeinformationen laden
set_fact:
azure_credentials: "{{ lookup('file', azure_credentials_path) | from_json }}"
tasks:
- name: Informationen zu VMs abrufen
azure.azcollection.azure_rm_virtualmachine_info:
subscription_id: "{{ subscription_id }}"
tenant: "{{ azure_credentials.tenant }}"
client_id: "{{ azure_credentials.client_id }}"
secret: "{{ azure_credentials.client_secret }}"
resource_group: "{{ resource_group }}"
register: vm_info
- name: Hostliste für Inventory aufbereiten
set_fact:
linux_hosts: "{{ vm_info.virtual_machines | selectattr('os_type', 'equalto', 'Linux') | list }}"
windows_hosts: "{{ vm_info.virtual_machines | selectattr('os_type', 'equalto', 'Windows') | list }}"
- name: Neues Inventory generieren
template:
src: inventory.j2
dest: "{{ workspace.path }}/inventory.yml"Als dest nutzen Sie {{ workspace.path }}/inventory.yml: workspace.path ist in Polycrate-Ansible der Workspace-Root – stabiler als relative Pfade wie ../../inventory.yml, die von der Verzeichnistiefe des Blocks abhängen.
Dazu das Template im gleichen Block-Verzeichnis:
# …/azure-vms/inventory.j2
all:
vars:
ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
ansible_python_interpreter: /usr/bin/python3
hosts:
server01.acme-corp.com:
ansible_user: ubuntu
dc01.acme-corp.com: {}
{% for vm in linux_hosts %}
{{ vm.name }}:
ansible_host: {{ vm.public_ip_address }}
ansible_user: {{ block.config.admin_username }}
{% endfor %}
{% for vm in windows_hosts %}
{{ vm.name }}:
ansible_host: {{ vm.public_ip_address }}
ansible_user: azureadmin
{% endfor %}
children:
onprem_linux:
hosts:
server01.acme-corp.com:
onprem_windows:
hosts:
dc01.acme-corp.com:
vars:
ansible_connection: winrm
ansible_winrm_transport: ntlm
ansible_winrm_server_cert_validation: ignore
azure_linux:
hosts:
{% for vm in linux_hosts %}
{{ vm.name }}:
{% endfor %}
azure_windows:
hosts:
{% for vm in windows_hosts %}
{{ vm.name }}:
{% endfor %}
vars:
ansible_connection: winrm
ansible_winrm_transport: ntlm
ansible_winrm_server_cert_validation: ignoreFür SSH zu den Azure-Linux-VMs stellt Polycrate im Action-Container u. a. ANSIBLE_PRIVATE_KEY_FILE bereit – Sie tragen kein ansible_ssh_private_key_file ins Inventory. WinRM-Passwörter für Azure-Windows-Hosts gehören nicht in die YAML-Datei, sondern in secrets.poly / block.config und werden in den Playbooks verwendet (siehe Hybrid-Artikel).
Ausführung:
polycrate run azure-vms inventoryNach dieser Action kennt Ihr Inventory sowohl On-Premise-Hosts als auch Azure-VMs. Der große Vorteil gegenüber einem klassischen dynamischen Ansible-Inventory: Das Ergebnis liegt als YAML-Datei im Workspace, versionierbar in Git und kompatibel mit allen Tools, die inventory.yml lesen.
Für Linux-VMs:
polycrate ssh vm-ubuntu-01Für Windows-Server nutzen Sie reguläre Ansible-Playbooks mit WinRM, z. B. mit einem Block aus der Registry:
# workspace.poly (Auszug)
blocks:
- name: windows-hardening
from: registry.acme-corp.com/acme/infra/windows-hardening:0.1.0
config: {}polycrate run windows-hardening cis-baseline --limit vm-win-01Weitere Details zur SSH-Integration finden Sie unter SSH mit Polycrate.
Viele Backuplösungen behandeln Azure Blob Storage als S3-ähnliches Ziel, auch wenn es technisch eine eigene API ist. Mit Ansible nutzen wir die nativen Azure-Module.
# blocks/registry.acme-corp.com/acme/infra/azure-backup/block.poly
name: registry.acme-corp.com/acme/infra/azure-backup
version: 0.1.0
kind: generic
config:
azure_credentials_path: "artifacts/secrets/azure-credentials.json"
subscription_id: ""
resource_group: "rg-acme-backup"
storage_account: "acmehybridbackup"
container_name: "artifacts"
actions:
- name: prepare
driver: ansible
playbook: prepare.yml
- name: upload-artifact
driver: ansible
playbook: upload.ymlprepare.yml sorgt für Storage Account und Container:
# …/azure-backup/prepare.yml
- name: Azure Blob Storage vorbereiten
hosts: localhost
connection: local
gather_facts: false
vars:
azure_credentials_path: "{{ block.config.azure_credentials_path }}"
subscription_id: "{{ block.config.subscription_id }}"
resource_group: "{{ block.config.resource_group }}"
storage_account: "{{ block.config.storage_account }}"
container_name: "{{ block.config.container_name }}"
pre_tasks:
- name: Azure Anmeldeinformationen laden
set_fact:
azure_credentials: "{{ lookup('file', azure_credentials_path) | from_json }}"
tasks:
- name: Resource Group für Backups sicherstellen
azure.azcollection.azure_rm_resourcegroup:
subscription_id: "{{ subscription_id }}"
tenant: "{{ azure_credentials.tenant }}"
client_id: "{{ azure_credentials.client_id }}"
secret: "{{ azure_credentials.client_secret }}"
name: "{{ resource_group }}"
location: "westeurope"
- name: Storage Account anlegen
azure.azcollection.azure_rm_storageaccount:
subscription_id: "{{ subscription_id }}"
tenant: "{{ azure_credentials.tenant }}"
client_id: "{{ azure_credentials.client_id }}"
secret: "{{ azure_credentials.client_secret }}"
resource_group: "{{ resource_group }}"
name: "{{ storage_account }}"
kind: "StorageV2"
sku: "Standard_LRS"
- name: Blob-Container anlegen
azure.azcollection.azure_rm_storageblob:
subscription_id: "{{ subscription_id }}"
tenant: "{{ azure_credentials.tenant }}"
client_id: "{{ azure_credentials.client_id }}"
secret: "{{ azure_credentials.client_secret }}"
resource_group: "{{ resource_group }}"
storage_account_name: "{{ storage_account }}"
container: "{{ container_name }}"
state: presentEin einfaches Upload-Playbook könnte lokale Artefakte aus artifacts/ in den Container schieben. Sobald der Storage bereitsteht, können externe Tools, die S3-kompatible Endpoints sprechen, via Gateway oder Backup-Software darauf zugreifen.
Für kleinere Teams ist Kostenkontrolle oft ein zentraler Grund, Azure nur vorsichtig zu nutzen. Ein einfaches, praxistaugliches Pattern: Nicht-produktive VMs automatisch abends stoppen und morgens wieder starten.
# blocks/registry.acme-corp.com/acme/infra/azure-cost-control/block.poly
name: registry.acme-corp.com/acme/infra/azure-cost-control
version: 0.1.0
kind: generic
config:
azure_credentials_path: "artifacts/secrets/azure-credentials.json"
subscription_id: ""
resource_group: "rg-acme-hybrid"
tag_filter: "env=dev"
actions:
- name: stop
driver: ansible
playbook: stop.yml
- name: start
driver: ansible
playbook: start.ymlstop.yml kann alle VMs mit einem bestimmten Tag herunterfahren:
# …/azure-cost-control/stop.yml
- name: Dev-VMs stoppen
hosts: localhost
connection: local
gather_facts: false
vars:
azure_credentials_path: "{{ block.config.azure_credentials_path }}"
subscription_id: "{{ block.config.subscription_id }}"
resource_group: "{{ block.config.resource_group }}"
tag_filter: "{{ block.config.tag_filter }}"
pre_tasks:
- name: Azure Anmeldeinformationen laden
set_fact:
azure_credentials: "{{ lookup('file', azure_credentials_path) | from_json }}"
tasks:
- name: Ziel-VMs ermitteln
azure.azcollection.azure_rm_virtualmachine_info:
subscription_id: "{{ subscription_id }}"
tenant: "{{ azure_credentials.tenant }}"
client_id: "{{ azure_credentials.client_id }}"
secret: "{{ azure_credentials.client_secret }}"
resource_group: "{{ resource_group }}"
register: vm_info
- name: VM-Liste nach Tag filtern
set_fact:
target_vms: >-
{{ vm_info.virtual_machines
| selectattr('tags', 'defined')
| selectattr('tags.env', 'equalto', 'dev')
| list }}
- name: Dev-VMs stoppen
azure.azcollection.azure_rm_virtualmachine:
subscription_id: "{{ subscription_id }}"
tenant: "{{ azure_credentials.tenant }}"
client_id: "{{ azure_credentials.client_id }}"
secret: "{{ azure_credentials.client_secret }}"
resource_group: "{{ resource_group }}"
name: "{{ item.name }}"
state: present
started: false
loop: "{{ target_vms }}"start.yml ist analog, setzt started: true.
Ein Cronjob oder ein kleiner CI-Job kann dann einfach:
polycrate run azure-cost-control stopum 20:00 Uhr und
polycrate run azure-cost-control startum 07:00 Uhr ausführen. Polycrate sorgt dafür, dass dieselbe Automatisierung überall gleich läuft – ob auf einem Admin-Laptop, einem Build-Agent oder einem zentralen Automatisierungsserver.
Mit plain Ansible müssten Sie:
azure.azcollection installieren,ansible.cfg und Credential-Handling pro Entwicklerarbeitsplatz pflegen,Mit Polycrate bekommen Sie:
Das reduziert Reibungsverluste im Team und vereinfacht auch Compliance, weil Sie genau sehen, welche Blöcke welche Aktionen ausführen.
Sensible Dateien (z. B. azure-credentials.json, SSH-Keys, Passwörter) liegen im Verzeichnis artifacts/secrets/ und werden mit age verschlüsselt. Polycrate bringt die entsprechende Verschlüsselungslogik mit, sodass Sie keinen separaten Secret Store aufbauen müssen. Details finden Sie unter Workspace-Verschlüsselung.
In vielen Teams ersetzt das in frühen Phasen einen externen Vault und ist deutlich einfacher zu handhaben – gerade, wenn nur wenige Personen Zugriff auf den Workspace haben und trotzdem ein Audit-Trail über Git gewünscht ist.
Ja. Blöcke wie azure-infra, azure-vms oder azure-cost-control können versioniert und als OCI-Image in einer Registry veröffentlicht werden. Über PolyHub (siehe PolyHub-Dokumentation) lassen sich solche Bausteine teamübergreifend oder sogar öffentlich teilen.
In der Praxis heißt das: Ein Team baut saubere Azure-Blöcke, andere Teams binden sie einfach per from: cargo.ayedo.cloud/...:0.1.0 in ihren Workspace ein – inklusive konsistenter Versionierung und klar definierten config-Parametern.
Weitere Fragen? Siehe unsere FAQ
Mit dem gezeigten Setup haben Sie:
inventory.yml verwaltet,azure.azcollection.azure_rm_virtualmachine provisioniert,Sie haben damit den typischen Wildwuchs an losen Ansible-Playbooks hinter sich gelassen und eine strukturierte, wiederverwendbare Automatisierung aufgebaut – ohne lokale Abhängigkeiten, mit verschlüsselten Secrets und klaren Guardrails durch das Block-Modell. Genau diese Kombination macht Polycrate zu einem starken Hybrid-Framework: On-Premise-Server, Azure-VMs, Container-Workloads – alles im selben Arbeitsmodell.
Wenn Sie diesen Ansatz für Ihre eigene Umgebung evaluieren möchten, unterstützen wir Sie bei ayedo mit:
Vertiefung zu Inventories und Hybrid-Setups: Multi-Server-Management und Hybrid-Automatisierung. Für Formate mit ayedo: Workshops.
Polycrate fasst On-Premise und Azure in einem Workspace zusammen – ein gemeinsames Arbeitsmodell für hybride Teams.
Warum die nächste Evolutionsstufe der Plattform bereits begonnen hat Die Diskussion rund um …
TL;DR Ansible kann Azure Entra ID (ehem. Azure AD) über die azure.azcollection vollständig …
TL;DR Active-Directory-Änderungen per GUI oder unversionierten PowerShell-Skripten sind …