Offboard Terraform-based Azure deployments (all scopes)

Follow this procedure to offboard all Terraform-based Microsoft Azure scopes (subscription, management group, or tenant) and cleanly decommission all Cortex XSIAM resources from Microsoft Azure. Fo

Prerequisites

Before you begin, ensure you meet the following requirements:

Tooling requirements

  • Bash (version \(\ge\) 4.0)
  • Azure CLI (version \(\ge\) 2.61)
  • jq (JSON processor)
  • Terraform CLI (initialized in your Cortex deployment directory)

Required Azure permissions

The authenticated session must be run by a user or service principal with the Owner role assigned at the management group scope. This is required to delete policy resources, role assignments, role definitions, and resource groups across all child subscriptions.

Authentication

Run the following command in your terminal to authenticate with the correct Azure tenant:

az login --tenant <tenant-id>

How to offboard Microsoft Azure

  1. In the same Terraform directory used to deploy, run the destruction command. This removes all core Terraform-managed resources, including the deployment stack, onboarding resource group, managed identity, and diagnostic settings:

    terraform destroy
    
  2. Review the destruction plan carefully, then enter yes to confirm the removal.

1. Identify ext_resource_suffix

Important

This step must be performed before destroying any resources. Once terraform destroy is executed, the Terraform state is cleared, and this value cannot be recovered without contacting Palo Alto Networks support.

  1. In your local terminal within the directory containing your Cortex XSIAM Terraform configuration and run the following command to retrieve the unique resource suffix:

    terraform output ext_resource_suffix
    
  2. Copy and save the output string. It is referred to as <ext-value> in the steps below.

2. Run terraform destory

This removes all core Terraform-managed resources, including the deployment stack, onboarding resource group, managed identity, diagnostic settings, and Graph API roles.

  1. In the same Terraform directory used in Step 1, run the destruction command:

    terraform destroy
    
  2. Review the destruction plan carefully, then enter yes to confirm the removal.

3. Run offboard_policy_deployment.sh

Certain policy-deployed resources are created per-subscription by a deployIfNotExists policy and exist outside the Terraform lifecycle, so terraform destroy cannot remove them. The offboard_policy_deployment.sh script must be executed to finalize the offboarding.

For your reference, the following flags are used in the script:

FlagDescription
--management-group-id <id>

Required. Scope-specific values for --management-group-id:

  • Subscription scope: Pass the management group ID that contains the subscription being offboarded.
  • Management group scope: Pass the specific management group ID being offboarded.
  • Tenant scope: Pass the tenant-root management group ID.
--ext-resource-suffix <ext-value>Required. The suffix value saved from Step 1.
--no-dry-runAction Flag. By default, the script runs in read-only mode. You must pass this flag to execute actual resource deletions.
--yes or -yAutomation Flag. Skips the interactive confirmation prompt. (Required for CI/CD pipelines, ignored in dry-run mode).
  1. First run a dry-run to preview the planned deletions and ensure your permissions are correct:

    bash offboard_policy_deployment.sh \
      --management-group-id <mg-id> \
      --ext-resource-suffix <ext-value>
    
  2. Review the script output and confirm that all targeted resources were removed. The script runs a post-deletion verification phase automatically. A final summary is printed to the terminal indicating the outcome of each phase.\
    If the script exits with a non-zero code or reports leftover resources in the verification phase, it is usually due to transient Azure API delays. You can safely re-run the script with --no-dry-run to trigger another cleanup and verification sweep.
  3. After reviewing the dry-run output, run the script with --no-dry-run to delete the resources:

    bash offboard_policy_deployment.sh \
      --management-group-id <mg-id> \
      --ext-resource-suffix <ext-value> \
      --no-dry-run