integrations.microsoft_defender_for_cloud — version 0.7

Source: presets/integrations/microsoft-defender-for-cloud.satz

Purpose

Microsoft Defender for Cloud — GCP onboarding, the foundation.

Defender onboards a GCP organization through workload identity federation: no service-account keys leave the estate. Microsoft's portal generates a per-customer Terraform/gcloud script; this pack is that script as Satz, with the customer-specific values as params and Microsoft's own values inlined — they are the same for every customer and are not params.

This file is the foundation every Defender deployment needs: the management project, its APIs, the workload identity pool, and the auto-provisioner plan that Microsoft always creates. One fragment per LICENSED PLAN goes beside it:

use "presets/integrations/microsoft-defender-for-cloud-cspm.satz" when mdc_plan_cspm use "presets/integrations/microsoft-defender-for-cloud-cspm-role-default.satz" when mdc_cspm_default_access

Required from the estate: customer_organization_id. The management project takes billing_account_infra unless the estate sets billing_account on it, and it is created in the folder mdc_mgmt_project_folder names — under the organisation while that param says nothing.

WHY the plans are separate files and not a list param: a pack cannot add to another fragment's project — two fragments defining one project is a fold conflict, and lists replace rather than concatenate. So this file owns the project and its complete API list, and each plan fragment declares its own resources at top level, naming the project through mdc_mgmt_project_id.

NO CLAIM is made here. Defender for Cloud is an external CSPM that READS the estate; it implements no CIS control and contributes to none.

BEFORE THE FIRST APPLY, one estate-side prerequisite: a deny-all on iam.workloadIdentityPoolProviders blocks the providers below. The estate must allow the sts.windows.net/<microsoft tenant> issuer, or document the exception.

The pack adds nothing to allowed_policy_member_subjects: the service accounts it grants roles to are created in the management project. The agentless-scanning plan grants roles to serviceAccount:mdc-agentless-scanning@guardians-prod-diskscanning.iam.gserviceaccount.com, which lives in a Microsoft-owned project; that plan is not in the library, and an estate that onboards it another way adds that account to allowed_policy_member_subjects itself, or the managed §1.1 constraint refuses the grant.

Use it

params {
  // the pack's own defaults — copy only the lines you change
  mdc_workload_pool_id = ""
  mdc_mgmt_project_id = ""
  mdc_mgmt_project_folder = ""
  mdc_plan_cspm = false
  mdc_cspm_default_access = false
  mdc_cspm_least_privilege = false
}

use "presets/integrations/microsoft-defender-for-cloud.satz"

Needs from outside the pack:

Params

param default
mdc_workload_pool_id ""
mdc_mgmt_project_id ""
mdc_mgmt_project_folder ""
mdc_plan_cspm false
mdc_cspm_default_access false
mdc_cspm_least_privilege false

Questions

What to ask before this pack is configured, and what changing the answer costs.

asks about prompt reversal blast recommends
mdc_workload_pool_id The customer's Microsoft Entra tenant id without dashes — the workload identity pool id from Microsoft's generated onboarding script recreate high —
mdc_mgmt_project_id The management project Defender is onboarded through recreate high —
mdc_mgmt_project_folder The folder the Defender management project is created in — a folder the estate declares as google_folder.<label>.name, an existing one by its numeric id, or empty for the organisation edit low —
mdc_plan_cspm Is the Defender CSPM plan licensed for this customer? edit low —
mdc_cspm_access (choice) Which access does CSPM get? edit low —

mdc_workload_pool_id — It is per customer and cannot be guessed. The pool is created with this id; a different id is a new pool, and Defender's connector has to be onboarded again.

mdc_mgmt_project_id — Customers name projects their own way, so there is no default. The pool, the provider and the service accounts are created in this project; moving them is a new onboarding.

mdc_mgmt_project_folder — It is the only thing that decides where the project lands. Left empty, the project is created directly under the organisation and inherits the organisation's policies and IAM alone. Changing it afterwards moves a live project between parents, which changes the policies and the grants the workload identity pool and the service accounts inside it inherit.

An empty answer, "", is an answer: the organisation itself; the project is created directly under it.

mdc_plan_cspm — Each licensed plan pulls in its fragment with the roles that plan needs. A plan that is on without a licence grants roles nothing uses; one that is off with a licence leaves the connector without access.

mdc_cspm_access — Switching later replaces the custom role and its binding; both modes true is a fold conflict on the role address, which is the loud failure it should be.

Contributes

resource type labels
google_iam_workload_identity_pool_provider mdc_auto_provisioner
google_organization_iam_custom_role MDCCustomRole
google_organization_iam_member serviceAccount:mdc-onboarding-sa@{mdc_mgmt_project_id}.iam.gserviceaccount.com (grant map)
google_project mdc_mgmt
google_service_account_iam_member service_account_id (grant map), principalSet://iam.googleapis.com/projects/${google_project.mdc_mgmt.number}/locations/global/workloadIdentityPools/{mdc_workload_pool_id}/* (grant map)

Claims

None — this pack proves no control by itself.

History

version date change
0.7 2026-10-14 mdc_mgmt_project_folder says what an empty answer means — the organisation itself — so an estate that binds "" has answered the question; before, "" counted as unanswered although the prompt offered it. Nothing emitted changes
0.6 2026-09-30 contributes nothing to allowed_policy_member_subjects: the agentless disk-scanning account it contributed is granted nothing by this pack — the grant belongs to the agentless-scanning plan, which the library does not ship. The header and the plan note say the per-plan audiences, service accounts and role sets are Microsoft's constants, identical in generated scripts for different tenants
0.5 2026-09-22 contributes the agentless disk-scanning account to allowed_policy_member_subjects instead of naming it as a manual prerequisite in the header
0.4 2026-09-21 a question for mdc_mgmt_project_folder: the folder the Defender management project is created in. The param is now the only thing that decides — a use line no longer stands in a folder's body — so the interview asks for it. Answering it empty creates the project under the organisation, which is where every estate that binds nothing has it today
0.3 2026-09-21 mdc_mgmt_project_folder: the folder the Defender management project is created in, said by the estate instead of read from the node the use line stands in. The default is empty, which says nothing — the enclosing node decides, exactly as before — so no estate's plan moves. An estate whose use "presets/integrations/microsoft-defender-for-cloud.satz" stands inside a folder's body writes mdc_mgmt_project_folder = "google_folder.<label>.name" for that folder and may then move the use line to the top level: the emitted HCL is byte-identical either way. A folder that already exists rather than being declared here is named by its id, "123456789012"
0.2 2026-09-10 four question blocks: the two ids only Microsoft's wizard knows (both block until typed), whether CSPM is licensed, and — only when it is — the access mode as a oneof under ask_when, the library's first gated choice. Nothing emitted changes
0.1 2026-09-03 first cut — the foundation of Microsoft's GCP onboarding as Satz: management project + its API set, the workload identity pool, the auto-provisioner plan and its custom role. Transcribed from a customer's generated wizard Terraform; Microsoft's own tenant, application-id audiences, provider ids and role ids are inlined constants, the customer's Entra tenant and the management project id are params

The whole library's history: the changelog in presets/CHANGELOG.md.

Notes

The scanning service account belongs to a Microsoft-owned project, so it must be in the CIS pack's allowed_policy_member_subjects BEFORE any grant to it is applied — otherwise the domain-restriction policy refuses the grant and the connector never finishes.

This is the foundation: the project, the workload identity pool and the CSPM plan's oneof. The plan fragments themselves are added to the estate by hand — …cspm with one of the two role fragments.

Defender reads the estate; it makes no claims, and nothing here is a compliance witness.