仕組み

TerraProviderをテナントとパイプラインに設定する。

TerraProviderをセットアップするエンジニアが知っておくべきこと:サインインの仕組み、要求される権限、最初のプランの構成、既存テナントをコード管理下に置く方法。

  • terraprovider/microsoft365wp
  • Terraform and OpenTofu
  • 10 ビルド
  • バージョン 0.20.2
セットアップ

4ステップで完成する最初のプラン

他のAzureプロバイダーのセットアップとほぼ同じ手順で、サインインの仕組みも共通している。

  1. Entra ID にアプリを登録する。

    シングルテナント、リダイレクトURIは不要。アプリケーション(クライアント)IDとディレクトリ(テナント)IDを控えておく。
  2. Graph権限を付与する。

    管理対象オブジェクトに必要なアプリケーション権限を追加し(下の表を参照)、管理者の同意を付与する。
  3. プロバイダーを宣言する。

    ARM_TENANT_ID と ARM_CLIENT_ID を設定し、初回テスト用に ARM_CLIENT_SECRET も追加する。パイプラインでは、代わりにOpenID Connectを使用する(後述)。
    main.tf
    terraform {  required_providers {    microsoft365wp = {      source = "terraprovider/microsoft365wp"    }  }}provider "microsoft365wp" {}
  4. プランを実行する。

    リソースを1つ(例:コンプライアンスポリシー)記述し、terraform plan または tofu plan を実行する。applyするまでテナントに変更は加わらない。
    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 = {} }  }]}

    サンプルデータ。

権限

要求されるGraph権限

管理者の同意が必要なアプリケーション権限。管理対象オブジェクトに必要なものだけを付与すること。ここに記載されていないリソースの権限は、各リソースのドキュメントページに記載されている。

要求されるGraph権限
権限許可される操作
DeviceManagementConfiguration.ReadWrite.AllIntune デバイス構成とポリシー
DeviceManagementApps.ReadWrite.AllIntune アプリ
DeviceManagementServiceConfig.ReadWrite.AllIntune サービス構成(登録など)
Policy.ReadWrite.ConditionalAccess条件付きアクセスポリシー
Policy.Read.All組織のポリシーの読み取り
Application.ReadWrite.Allアプリケーション
Directory.ReadWrite.Allディレクトリデータ
Group.ReadWrite.Allグループ
User.ReadWrite.Allユーザーの完全なプロファイル
CloudPC.ReadWrite.AllWindows 365 構成

出典:プロバイダーガイド「Configuring a Service Principal for managing EntraID」。

サインイン

azuread プロバイダーと同じサインイン設定

プロバイダーは azuread プロバイダーと同じ ARM_* 設定を読み取る。ARM_TENANT_ID と ARM_CLIENT_ID を設定したら、認証方式を選択する。

azuread プロバイダーと同じサインイン設定
方式適したシナリオ有効化方法
OpenID Connect, GitHub Actionsシークレットを保存しないワークフローARM_USE_OIDC=true
OpenID Connect, Azure DevOpsサービス接続を使用するパイプラインARM_USE_OIDC=true
ARM_ADO_PIPELINE_SERVICE_CONNECTION_ID
OpenID Connect, any issuerIDトークンを発行するその他のCIシステムARM_USE_OIDC=true
ARM_OIDC_TOKEN / ARM_OIDC_TOKEN_FILE_PATH
Client certificate証明書を保持するランナーARM_CLIENT_CERTIFICATE / ARM_CLIENT_CERTIFICATE_PATH
Client secret初回テスト、ラボ環境ARM_CLIENT_SECRET / ARM_CLIENT_SECRET_FILE_PATH
Managed identityAzure上のランナーARM_USE_MSI=true
AKS workload identityAzure上のKubernetesで動作するランナーARM_USE_AKS_WORKLOAD_IDENTITY=true
Azure CLIローカルマシンデフォルトで有効。ARM_USE_CLI=false で無効化できる

各設定はプロバイダー引数としても指定できる(use_oidc、client_certificate_path など)。プロバイダーのOpenID Connectガイドでは、Entra ID がGitHubリポジトリを信頼するよう設定する方法を説明している。まとめると:OpenID Connect(GitHub Actions、Azure DevOps、任意のOIDCトークン)、クライアント証明書、クライアントシークレット、マネージドID、AKSワークロードID、Azure CLI。

4つのクラウド

environment または ARM_ENVIRONMENT を設定すると、プロバイダーは対応するクラウドの Microsoft Graph エンドポイントに接続する。対象はglobal、US Government L4、US Government L5(DoD)、Chinaの4つ。

環境

global (also public)
商用クラウド(デフォルト)
usgovernmentl4 (also usgovernment)
US Government L4
usgovernmentl5 (also dod)
US Government L5 (DoD)
china
Microsoftの中国向けクラウド
独自エンドポイント
metadata_host or ARM_METADATA_HOSTNAME
DRIFT

プランが監視する対象

Terraform はコードの構成とテナントが返す実際の状態を比較する。TerraProvider はその比較をオブジェクト全体に拡張する。設定していない属性にはデフォルト値が割り当てられ、その値はMicrosoftのポータルで同じオブジェクトを作成したときに返される値から取得される。そのため、ポータルでポリシーに除外を追加したり、Intune 管理センターでトグルを切り替えたり、スクリプトで設定を変更したりした場合、コードに記述があるかどうかにかかわらず、次のプランで差分として表示される。
  • 省略したコレクションはデフォルトで空になるため、追加されたメンバー、除外またはアプリは差分として表示される。
  • 状態が指定されていない新しい条件付きアクセスポリシーは enabledForReportingButNotEnforced として作成される。
  • 各属性のデフォルト値はリソースのドキュメントページに記載されており、プロバイダーデフォルトとして明示されている。

注意点として、ポータルで有効にしてから無効に戻した設定が、未設定ではなく false として返ってくることがある。その場合、次のプランで1件の変更として表示されるが、一度 apply すれば解消される。

ポータルでの操作: 前回のapply以降、変更はありません。

microsoft365wp_conditional_access_policy.require_mfa_admins: Refreshing state... [id=2b7f9c3e-8d41-4f6a-b0e2-5c9a1d7e3f80]No changes. Your infrastructure matches the configuration.
サンプルデータ。
EXISTING TENANT

既存テナントを2フェーズでエクスポート・インポートする

クイックスタートリポジトリには、モジュール、GitHub Actionsワークフロー、PowerShellエクスポートを含むリファレンス構成が用意されている。ポリシーがグループやフィルターを参照するため、エクスポートは2フェーズで行う。

  1. グループ、フィルター、通知テンプレートをエクスポートする。

    クイックスタートのモジュールに書き出され、種類ごとにマッピングファイルが生成される。メール対応グループは明示的に指定しない限り除外される。
  2. インポートする。

    ツールが Terraform または OpenTofu を呼び出し、エクスポートされたすべてのオブジェクトをステートにインポートする。
  3. コンプライアンスポリシーと構成ポリシーをエクスポートする。

    設定カタログとエンドポイントセキュリティポリシーは構成ポリシーとして扱われる。各エクスポートには、Graphが返したデータの生JSONダンプも保存される。
  4. インポートする。

    同じツールを使い、第2フェーズとして実行する。
  5. プランを実行する。

    プランには残っている差分が表示される。エクスポートできない属性もあるため、最初のクリーンなプランが得られるまでに若干の修正作業が必要になる。

オブジェクト1件ずつの処理

エクスポートがカバーしていないオブジェクトについては、小さなスクリプトを使い、任意のリソースタイプのオブジェクト1件分のTerraformファイルをIDを指定して生成できる。Terraform自身のコード生成機能を利用するため、ファイルにはプロバイダーがテナントから読み取る内容がそのまま記録される。

GitHubのクイックスタート
APPS

アプリ、パッケージ、割り当てを1つのリソースで管理する

microsoft365wp_mobile_app は 21 種類のアプリタイプに対応している。.intunewin, MSI, APPX/MSIX, DMG, PKG 種類のパッケージについては、プロバイダーがファイルを暗号化して Intune にアップロードする。この処理は source_sha256 が変わったときのみ再実行される。割り当ても同じリソース内に定義できる。全デバイス、ライセンス保有ユーザー全員、グループ、除外グループのいずれかを対象に、インクルードまたはエクスクルードフィルターを組み合わせて指定できる。
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 = {} }  }]}

サンプルデータ。

  • Windows

    Win32 (.intunewin)、MSI、APPX/MSIX、Microsoft Store(新、WinGet経由)、Microsoft Store(レガシー)、Microsoft Edge、Microsoft 365 Apps、Webリンク。

  • macOS

    DMG、PKG、Microsoft Edge、Microsoft Defender、Microsoft 365 Apps、Webクリップ。

  • iOS and iPadOS

    App Storeアプリ、マネージドiOSストアアプリ、Webクリップ。

  • Android

    Google Playストアアプリ、マネージドGoogle Playアプリ、マネージドAndroidストアアプリ。

  • 全プラットフォーム

    Webリンク。

TENANTS

1つのリポジトリで複数テナントを管理する

プロバイダーブロック1つが1テナントにサインインする。複数テナントを管理する場合は、テナントごとにエイリアスと tenant_id を指定したブロックを宣言し、ベースラインをモジュールとして記述してテナントごとに1回呼び出す。各ブロックは独立してサインインするため、テナントごとに独自の権限を持つサービスプリンシパルを割り当てられる。
  • テナント間の差異はモジュール変数として表現され、レビュー時に確認できる。
  • 新しいテナントの追加は、プロバイダーブロック1つ、モジュール呼び出し1つ、プラン実行1回で完結する。
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}

サンプルデータ。

Graph throttlingへの対処方法

Microsoft Graph はクライアントが送信できるリクエスト数を制限しており、大規模テナントに対するプランでは多数のリクエストが発生する。プロバイダーは自動的に待機してリトライする。

リトライ

リクエストあたりのリトライ回数
最大 10 回
リトライ間の待機時間
3〜60秒
Retry-After が 0 の場合
バックオフ時間まで延長される。GraphがRetry-After: 0を返すことは多く、即時リトライはほとんど効果がないため。

まずクイックスタートから始める。

リポジトリをクローンし、テスト用テナントに向けてプランを実行する。Community Editionは 99 ユーザー以下の組織であれば無料で利用できる。