SO FUNKTIONIERT ES

TerraProvider in deinem Tenant und deiner Pipeline einrichten.

Was der Engineer, der TerraProvider einrichtet, wissen muss: wie die Anmeldung funktioniert, welche Berechtigungen benötigt werden, wie der erste Plan aussieht und wie ein bestehender Tenant unter Code kommt.

  • terraprovider/microsoft365wp
  • Terraform and OpenTofu
  • 10 Builds
  • Version 0.20.2
SETUP

Dein erster Plan in vier Schritten

Ungefähr so aufwendig wie das Einrichten eines anderen Azure-Providers, denn die Anmeldung funktioniert auf dieselbe Weise.

  1. Eine App in Entra ID registrieren.

    Single Tenant, keine Redirect-URI erforderlich. Notiere die Application (Client) ID und die Directory (Tenant) ID.
  2. Graph-Berechtigungen erteilen.

    Füge die Anwendungsberechtigungen für die Objekte hinzu, die du verwalten möchtest (siehe die Tabelle unten), und erteile die Admin-Zustimmung.
  3. Den Provider deklarieren.

    Setze ARM_TENANT_ID und ARM_CLIENT_ID sowie ARM_CLIENT_SECRET für einen ersten Test. In einer Pipeline verwende stattdessen OpenID Connect (siehe unten).
    main.tf
    terraform {  required_providers {    microsoft365wp = {      source = "terraprovider/microsoft365wp"    }  }}provider "microsoft365wp" {}
  4. Planen.

    Schreibe eine Ressource, zum Beispiel eine Compliance-Richtlinie, und führe terraform plan oder tofu plan aus. Im Tenant ändert sich nichts, bis du applyst.
    compliance.tf
    resource "microsoft365wp_device_compliance_policy" "windows_defender" {  display_name = "Windows - Defender for Endpoint"  windows10 = {    device_threat_protection_enabled = true  }  scheduled_actions_for_rule = [{    scheduled_action_configurations = [{      action_type        = "block"      grace_period_hours = 6    }]  }]  assignments = [{    target = { all_licensed_users = {} }  }]}

    Beispieldaten.

BERECHTIGUNGEN

Die Graph-Berechtigungen, die benötigt werden

Anwendungsberechtigungen, erteilt per Admin-Zustimmung. Erteile nur die Berechtigungen für die Objekte, die du verwaltest; eine Ressource, die hier nicht aufgeführt ist, nennt ihre Berechtigungen auf ihrer Dokumentationsseite.

Die Graph-Berechtigungen, die benötigt werden
BerechtigungWas sie erlaubt
DeviceManagementConfiguration.ReadWrite.AllIntune-Gerätekonfiguration und -Richtlinien
DeviceManagementApps.ReadWrite.AllIntune-Apps
DeviceManagementServiceConfig.ReadWrite.AllIntune-Dienstkonfiguration, z. B. Enrollment
Policy.ReadWrite.ConditionalAccessConditional Access-Richtlinien
Policy.Read.AllLesen der Richtlinien deiner Organisation
Application.ReadWrite.AllAnwendungen
Directory.ReadWrite.AllVerzeichnisdaten
Group.ReadWrite.AllGruppen
User.ReadWrite.AllVollständige Benutzerprofile
CloudPC.ReadWrite.AllWindows 365-Konfiguration

Quelle: Leitfaden des Providers „Configuring a Service Principal for managing EntraID".

ANMELDUNG

Dieselben Anmeldeeinstellungen wie beim azuread-Provider

Der Provider liest dieselben ARM_*-Einstellungen wie der azuread-Provider. Setze ARM_TENANT_ID und ARM_CLIENT_ID, dann wähle eine Methode.

Dieselben Anmeldeeinstellungen wie beim azuread-Provider
MethodeWann sie passtAktivieren
OpenID Connect, GitHub ActionsWorkflows ohne gespeichertes SecretARM_USE_OIDC=true
OpenID Connect, Azure DevOpsPipelines mit einer Service ConnectionARM_USE_OIDC=true
ARM_ADO_PIPELINE_SERVICE_CONNECTION_ID
OpenID Connect, beliebiger IssuerAndere CI-Systeme, die ein ID-Token ausstellenARM_USE_OIDC=true
ARM_OIDC_TOKEN / ARM_OIDC_TOKEN_FILE_PATH
Client-ZertifikatRunner, die ein Zertifikat besitzenARM_CLIENT_CERTIFICATE / ARM_CLIENT_CERTIFICATE_PATH
Client SecretEin erster Test, ein LabARM_CLIENT_SECRET / ARM_CLIENT_SECRET_FILE_PATH
Managed IdentityRunner auf AzureARM_USE_MSI=true
AKS Workload IdentityRunner auf Kubernetes in AzureARM_USE_AKS_WORKLOAD_IDENTITY=true
Azure CLIDein Laptopstandardmäßig aktiv; ARM_USE_CLI=false deaktiviert es

Jede Einstellung existiert auch als Provider-Argument (use_oidc, client_certificate_path usw.). Der OpenID-Connect-Leitfaden des Providers zeigt, wie man Entra ID dazu bringt, einem GitHub-Repository zu vertrauen. Kurz zusammengefasst: OpenID Connect (GitHub Actions, Azure DevOps, beliebiges OIDC-Token), Client-Zertifikat, Client Secret, Managed Identity, AKS Workload Identity, Azure CLI.

Vier Clouds

Setze environment oder ARM_ENVIRONMENT. Der Provider kommuniziert dann mit dem Microsoft Graph-Endpunkt der jeweiligen Cloud: global, US Government L4, US Government L5 (DoD), China.

Environment

global (auch public)
Die kommerzielle Cloud, der Standard
usgovernmentl4 (auch usgovernment)
US Government L4
usgovernmentl5 (auch dod)
US Government L5 (DoD)
china
Microsofts Cloud in China
Eigener Endpunkt
metadata_host oder ARM_METADATA_HOSTNAME
DRIFT

Was der Plan beobachtet

Terraform vergleicht deine Konfiguration mit dem, was der Tenant meldet. TerraProvider weitet diesen Vergleich auf das gesamte Objekt aus: Jedes Attribut, das du nicht setzt, erhält einen Standardwert, der davon abgeleitet wird, was die Microsoft-Portale zurückgeben, wenn du dort dasselbe Objekt anlegst. Eine Ausnahme, die im Portal zu einer Richtlinie hinzugefügt wird, ein Schalter, der im Intune Admin Center umgelegt wird, oder eine Einstellung, die ein Skript ändert, taucht damit im nächsten Plan auf, unabhängig davon, ob deine Datei sie erwähnt.
  • Collections, die du weglässt, werden standardmäßig als leer behandelt, sodass ein hinzugefügtes Mitglied, eine Ausnahme oder eine App sichtbar wird.
  • Eine neue Conditional Access-Richtlinie ohne Status wird als enabledForReportingButNotEnforced erstellt.
  • Der Standardwert jedes Attributs steht auf der Dokumentationsseite der Ressource, gekennzeichnet als Provider-Standard.

Die Kehrseite: Eine Einstellung, die jemand in einem Portal ein- und wieder ausgeschaltet hat, kann als false statt als nicht gesetzt zurückkommen und erscheint einmalig als Änderung. Ein Apply behebt das.

Im Portal: Keine Änderungen seit dem letzten Apply.

microsoft365wp_conditional_access_policy.require_mfa_admins: Refreshing state... [id=2b7f9c3e-8d41-4f6a-b0e2-5c9a1d7e3f80]No changes. Your infrastructure matches the configuration.
Beispieldaten.
BESTEHENDER TENANT

Einen bestehenden Tenant in zwei Phasen exportieren und importieren

Das Quickstart-Repository enthält eine Referenzkonfiguration mit Modulen, GitHub Actions-Workflows und einem PowerShell-Export. Der Export läuft in zwei Phasen ab, weil Richtlinien auf Gruppen und Filter verweisen.

  1. Gruppen, Filter und Benachrichtigungsvorlagen exportieren.

    Sie werden in die Module des Quickstarts geschrieben, mit einer Mapping-Datei pro Typ. Mail-aktivierte Gruppen werden ausgelassen, sofern du sie nicht explizit anforderst.
  2. Importieren.

    Das Tool ruft Terraform oder OpenTofu auf, um jedes exportierte Objekt in den State zu importieren.
  3. Compliance- und Konfigurationsrichtlinien exportieren.

    Settings-Catalog- und Endpoint-Security-Richtlinien gelten als Konfigurationsrichtlinien. Jeder Export enthält außerdem einen rohen JSON-Dump dessen, was Graph zurückgegeben hat.
  4. Importieren.

    Dasselbe Tool, zweite Phase.
  5. Planen.

    Der Plan zeigt, was noch abweicht. Nicht jedes Attribut lässt sich exportieren, daher ist vor dem ersten sauberen Plan eine kurze Nacharbeit zu erwarten.

Ein Objekt nach dem anderen

Für alles, was der Export nicht abdeckt, schreibt ein kleines Skript eine Terraform-Datei für ein einzelnes Objekt eines beliebigen Ressourcentyps, gegeben dessen id. Es verwendet Terraforms eigene Konfigurationsgenerierung, sodass die Datei genau das enthält, was der Provider selbst aus dem Tenant liest.

Der Quickstart auf GitHub
APPS

Eine Ressource enthält die App, ihr Paket und ihre Zuweisungen

microsoft365wp_mobile_app deckt 21 App-Typen ab. Bei .intunewin, MSI, APPX/MSIX, DMG, PKG Paketen verschlüsselt der Provider die Datei und lädt sie in Intune hoch, und zwar erneut nur dann, wenn sich source_sha256 ändert. Zuweisungen liegen in derselben Ressource: alle Geräte, alle lizenzierten Benutzer, eine Gruppe oder eine Ausschlussgruppe, jeweils mit einem Include- oder Exclude-Filter.
locals {  agent_package = "${path.module}/packages/contoso-agent-4.2.1.intunewin"  agent_meta    = provider::microsoft365wp::parse_intunewin_metadata(local.agent_package)}resource "microsoft365wp_mobile_app" "contoso_agent" {  display_name = "Contoso Agent"  publisher    = "Contoso"  win32_lob = {    file_name              = local.agent_meta.file_name    setup_file_path        = local.agent_meta.setup_file    install_command_line   = "setup.exe /quiet"    uninstall_command_line = "setup.exe /uninstall /quiet"    detection_rules = [{      filesystem = {        detection_type      = "exists"        path                = "C:\\Program Files\\Contoso\\Agent"        file_or_folder_name = "agent.exe"      }    }]    source_file   = local.agent_package    source_sha256 = filesha256(local.agent_package)  }  assignments = [{    target   = { group = { group_id = "3d9b2f61-7a4e-4c18-9e05-6f2a8b1c4d93" } }    settings = { win32_lob = {} }  }]}

Beispieldaten.

  • Windows

    Win32 (.intunewin), MSI, APPX/MSIX, Microsoft Store (neu, über WinGet), Microsoft Store (Legacy), Microsoft Edge, Microsoft 365 Apps, Weblinks.

  • macOS

    DMG, PKG, Microsoft Edge, Microsoft Defender, Microsoft 365 Apps, Web-Clips.

  • iOS und iPadOS

    App-Store-Apps, verwaltete iOS-Store-Apps, Web-Clips.

  • Android

    Google-Play-Store-Apps, verwaltete Google-Play-Apps, verwaltete Android-Store-Apps.

  • Jede Plattform

    Weblinks.

TENANTS

Mehrere Tenants aus einem Repository

Ein Provider-Block meldet sich bei einem Tenant an. Für mehrere Tenants deklarierst du einen Block pro Tenant mit einem Alias und dessen tenant_id, schreibst die Baseline als Modul und rufst es einmal pro Tenant auf. Jeder Block meldet sich eigenständig an, sodass jeder Tenant sein eigenes Service Principal mit eigenen Berechtigungen haben kann.
  • Unterschiede zwischen Tenants sind Modulvariablen und im Review sichtbar.
  • Ein neuer Tenant bedeutet einen Provider-Block, einen Modulaufruf und einen Plan.
main.tf
provider "microsoft365wp" {  alias     = "contoso"  tenant_id = "8a1f3c2e-5b7d-4e90-a6c4-2d9e7f1b0c35"}provider "microsoft365wp" {  alias     = "fabrikam"  tenant_id = "e4c27b91-0d3a-4f86-b5e2-7a1c9d0f6b48"}module "baseline_contoso" {  source    = "./baseline"  providers = { microsoft365wp = microsoft365wp.contoso }}module "baseline_fabrikam" {  source     = "./baseline"  providers  = { microsoft365wp = microsoft365wp.fabrikam }  allow_byod = true}

Beispieldaten.

Wie Graph-Throttling behandelt wird

Microsoft Graph begrenzt die Anzahl der Anfragen, die ein Client senden darf, und ein Plan über einen großen Tenant sendet viele. Der Provider wartet und wiederholt die Anfragen selbstständig.

Wiederholungen

Wiederholungen pro Anfrage
bis zu 10
Wartezeit zwischen Wiederholungen
3 bis 60 Sekunden
Retry-After von null
Auf das Backoff-Intervall ausgedehnt, weil Graph häufig so antwortet und ein sofortiger Wiederholungsversuch selten hilft

Mit dem Quickstart anfangen.

Klone ihn, richte ihn auf einen Test-Tenant aus und führe einen Plan aus. Die Community Edition ist für Organisationen mit bis zu 99 Benutzern kostenlos.