FONCTIONNEMENT

Configure TerraProvider dans ton tenant et ton pipeline.

Ce que doit savoir l'ingénieur qui configure TerraProvider : comment il se connecte, quelles autorisations il demande, à quoi ressemble le premier plan et comment un tenant existant passe sous forme de code.

  • terraprovider/microsoft365wp
  • Terraform et OpenTofu
  • 10 binaires
  • version 0.20.2
CONFIGURATION

Ton premier plan en quatre étapes

À peu près aussi long que la configuration de n'importe quel autre provider Azure, car la connexion fonctionne de la même façon.

  1. Inscris une application dans Entra ID.

    Locataire unique, aucun URI de redirection nécessaire. Note l'ID d'application (client) et l'ID de l'annuaire (locataire).
  2. Accorde les autorisations Graph.

    Ajoute les autorisations d'application pour les objets que tu veux gérer (voir le tableau ci-dessous) et accorde le consentement administrateur.
  3. Déclare le provider.

    Définis ARM_TENANT_ID et ARM_CLIENT_ID, plus ARM_CLIENT_SECRET pour un premier test. Dans un pipeline, utilise plutôt OpenID Connect (voir plus bas).
    main.tf
    terraform {  required_providers {    microsoft365wp = {      source = "terraprovider/microsoft365wp"    }  }}provider "microsoft365wp" {}
  4. Lance le plan.

    Écris une ressource, une stratégie de conformité par exemple, et lance terraform plan ou tofu plan. Rien ne change dans le tenant tant que tu n'appliques pas.
    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 = {} }  }]}

    Données d'exemple.

AUTORISATIONS

Les autorisations Graph qu'il demande

Des autorisations d'application, accordées avec le consentement administrateur. N'accorde que celles des objets que tu gères ; une ressource absente de cette liste indique ses autorisations sur sa page de documentation.

Les autorisations Graph qu'il demande
AutorisationCe qu'elle permet
DeviceManagementConfiguration.ReadWrite.AllConfiguration et stratégies des appareils Intune
DeviceManagementApps.ReadWrite.AllApplications Intune
DeviceManagementServiceConfig.ReadWrite.AllConfiguration du service Intune, comme l'enrôlement
Policy.ReadWrite.ConditionalAccessStratégies d'accès conditionnel
Policy.Read.AllLecture des stratégies de ton organisation
Application.ReadWrite.AllApplications
Directory.ReadWrite.AllDonnées de l'annuaire
Group.ReadWrite.AllGroupes
User.ReadWrite.AllProfils complets des utilisateurs
CloudPC.ReadWrite.AllConfiguration de Windows 365

Source : le guide du provider « Configuring a Service Principal for managing EntraID ».

CONNEXION

Les mêmes paramètres de connexion que le provider azuread

Le provider lit les mêmes paramètres ARM_* que le provider azuread. Définis ARM_TENANT_ID et ARM_CLIENT_ID, puis choisis une méthode.

Les mêmes paramètres de connexion que le provider azuread
MéthodeQuand l'utiliserComment l'activer
OpenID Connect, GitHub ActionsWorkflows sans secret stockéARM_USE_OIDC=true
OpenID Connect, Azure DevOpsPipelines avec une connexion de serviceARM_USE_OIDC=true
ARM_ADO_PIPELINE_SERVICE_CONNECTION_ID
OpenID Connect, tout émetteurAutres systèmes de CI qui délivrent un jeton d'IDARM_USE_OIDC=true
ARM_OIDC_TOKEN / ARM_OIDC_TOKEN_FILE_PATH
Certificat clientRunners qui détiennent un certificatARM_CLIENT_CERTIFICATE / ARM_CLIENT_CERTIFICATE_PATH
Secret clientUn premier test, un laboARM_CLIENT_SECRET / ARM_CLIENT_SECRET_FILE_PATH
Identité managéeRunners sur AzureARM_USE_MSI=true
Identité de charge de travail AKSRunners sur Kubernetes dans AzureARM_USE_AKS_WORKLOAD_IDENTITY=true
Azure CLITon portableactivée par défaut ; ARM_USE_CLI=false la désactive

Chaque paramètre existe aussi comme argument du provider (use_oidc, client_certificate_path, etc.). Le guide OpenID Connect du provider montre comment faire en sorte qu'Entra ID fasse confiance à un dépôt GitHub. En une ligne : OpenID Connect (GitHub Actions, Azure DevOps, tout jeton OIDC), certificat client, secret client, identité managée, identité de charge de travail AKS, Azure CLI.

Quatre clouds

Définis environment ou ARM_ENVIRONMENT. Le provider s'adresse alors au point de terminaison Microsoft Graph de ce cloud : mondial, US Government L4, US Government L5 (DoD), Chine.

Environnement

global (ou public)
Le cloud commercial, par défaut
usgovernmentl4 (ou usgovernment)
US Government L4
usgovernmentl5 (ou dod)
US Government L5 (DoD)
china
Le cloud de Microsoft en Chine
Ton propre point de terminaison
metadata_host ou ARM_METADATA_HOSTNAME
DÉRIVE

Ce que le plan surveille

Terraform compare ta configuration avec ce que le tenant renvoie. TerraProvider étend cette comparaison à l'objet entier : chaque attribut que tu ne définis pas reçoit une valeur par défaut, reprise de ce qu'envoient les portails Microsoft quand tu y crées le même objet. Ainsi, une exclusion ajoutée à une stratégie dans le portail, un interrupteur basculé dans le centre d'administration Intune ou un paramètre modifié par un script apparaît dans le plan suivant, que ton fichier le mentionne ou non.
  • Les collections que tu omets sont vides par défaut, si bien qu'un membre, une exclusion ou une application ajoutés sont visibles.
  • Une nouvelle stratégie d'accès conditionnel dont l'état n'est pas défini est créée en enabledForReportingButNotEnforced.
  • La valeur par défaut de chaque attribut figure sur la page de documentation de la ressource, marquée comme valeur par défaut du provider.

Le revers : un paramètre que quelqu'un a activé puis désactivé dans un portail peut revenir à false au lieu de non défini, et apparaît une fois comme une modification. Un apply règle la question.

Dans le portail : Aucune modification depuis le dernier apply.

microsoft365wp_conditional_access_policy.require_mfa_admins: Refreshing state... [id=2b7f9c3e-8d41-4f6a-b0e2-5c9a1d7e3f80]No changes. Your infrastructure matches the configuration.
Données d'exemple.
TENANT EXISTANT

Exporter et importer un tenant existant en deux phases

Le dépôt quickstart contient une configuration de référence avec des modules, des workflows GitHub Actions et un export PowerShell. L'export se fait en deux phases, car les stratégies font référence à des groupes et à des filtres.

  1. Exporte les groupes, les filtres et les modèles de notification.

    Ils sont écrits dans les modules du quickstart, avec un fichier de correspondance par type. Les groupes à extension messagerie sont laissés de côté, sauf si tu les demandes.
  2. Importe-les.

    L'outil appelle Terraform ou OpenTofu pour importer chaque objet exporté dans l'état Terraform.
  3. Exporte les stratégies de conformité et de configuration.

    Les stratégies du catalogue des paramètres et de sécurité des points de terminaison comptent comme stratégies de configuration. Chaque export conserve aussi un dump JSON brut de ce que Graph a renvoyé.
  4. Importe-les.

    Même outil, deuxième phase.
  5. Lance le plan.

    Le plan montre ce qui diffère encore. Tous les attributs ne peuvent pas être exportés, alors prévois un court nettoyage avant le premier plan propre.

Un objet à la fois

Pour tout ce que l'export ne couvre pas, un petit script écrit un fichier Terraform pour un objet de n'importe quel type de ressource, à partir de son id. Il utilise la génération de configuration propre à Terraform, si bien que le fichier contient ce que le provider lit lui-même dans le tenant.

Le quickstart sur GitHub
APPLICATIONS

Une seule ressource contient l'application, son package et ses attributions

microsoft365wp_mobile_app couvre 21 types d'applications. Pour les packages .intunewin, MSI, APPX/MSIX, DMG, PKG, le provider chiffre le fichier et le téléverse dans Intune, et ne recommence que si source_sha256 change. Les attributions se trouvent dans la même ressource : tous les appareils, tous les utilisateurs disposant d'une licence, un groupe ou un groupe d'exclusion, chacun avec un filtre d'inclusion ou d'exclusion.
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 = {} }  }]}

Données d'exemple.

  • Windows

    Win32 (.intunewin), MSI, APPX/MSIX, Microsoft Store (nouveau, via WinGet), Microsoft Store (hérité), Microsoft Edge, Microsoft 365 Apps, liens web.

  • macOS

    DMG, PKG, Microsoft Edge, Microsoft Defender, Microsoft 365 Apps, clips web.

  • iOS et iPadOS

    Applications de l'App Store, applications iOS gérées du store, clips web.

  • Android

    Applications du Google Play Store, applications Google Play gérées, applications Android gérées du store.

  • Toutes les plateformes

    Liens web.

TENANTS

Plusieurs tenants depuis un seul dépôt

Un bloc provider se connecte à un tenant. Pour plusieurs tenants, déclare un bloc par tenant avec un alias et son tenant_id, écris la configuration de référence comme un module et appelle-le une fois par tenant. Chaque bloc se connecte séparément, si bien que chaque tenant peut avoir son propre principal de service avec ses propres autorisations.
  • Les différences entre tenants sont des variables du module, visibles dans la relecture.
  • Un nouveau tenant, c'est un bloc provider, un appel de module et un 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}

Données d'exemple.

Comment il gère la limitation de Graph

Microsoft Graph limite le nombre de requêtes qu'un client peut envoyer, et un plan sur un grand tenant en envoie beaucoup. Le provider attend et réessaie de lui-même.

Nouvelles tentatives

Nouvelles tentatives par requête
jusqu'à 10
Attente entre deux tentatives
3 à 60 secondes
Un Retry-After à zéro
Porté au délai d'attente progressif, car Graph répond souvent ainsi et une nouvelle tentative immédiate aide rarement

Commence par le quickstart.

Clone-le, fais-le pointer vers un tenant de test et lance un plan. Community Edition est gratuite pour les organisations jusqu'à 99 utilisateurs.