Note: Scroll down this article to download the terrafom files in zip format.


Cloud Security Connector MUX for Zscaler (ZIA) with PriCPA for Azure

This Terraform template deploys one or two Cloud Security Connector (CSC) MUX with PriCPA for Azure appliances into an existing Azure Virtual Network (VNet).

It is based on the official Cloud Security Connector ARM templates from the Azure Marketplace but consolidates multiple deployment scenarios (Availability Zones, Availability Sets, and single/dual VM) into a single, flexible Terraform configuration.

Features

  • Flexible Deployment: Deploy in High Availability (2 VMs) or as a single instance (1 VM) using the vm_count variable.
  • Flexible Infrastructure:
    • az: Deploys VMs across different Availability Zones.
    • as: Deploys VMs into a new Availability Set.
    • ni: Deploys VMs with no specific HA infrastructure.
  • Multi-Model Support: Supports MUX models 1, 2, 4, and 8 via the csc_model_version variable. The template automatically adjusts:
    • The number of ZTUN Public IPs and network interface configurations.
    • The correct VM Marketplace Image and Plan.
    • Accelerated Networking (enabled for models 4 and 8).
  • Automated Role Assignments: Automatically grants the VM's Managed Identity the "Contributor" and "Network Contributor" roles on:
    1. The VM's Resource Group.
    2. The VNet's Resource Group (if different from the VM's).
  • User Data Provisioning: Reads a configUserData.json file from the local directory, Base64 encodes it, and passes it to the VM's user_data property for provisioning.

Prerequisites

Before running this template, you must have:

  1. Terraform (v1.0+) and the Azure provider (v3.1+).
  2. Azure Credentials configured (e.g., by running az login).
  3. An Existing Azure VNet.
  4. Two Existing Subnets in the VNet (e.g., csc-external-subnet and csc-internal-subnet).
  5. configUserData.json file in the same directory. You can pass configuration values or leave it by default.

Usage

  1. Place all .tf files, terraform.auto.tfvars, and configUserData.json in the same directory.
  2. Edit terraform.auto.tfvars to match your environment.
  3. Edit configUserData.json with your specific CSC provisioning data.
  4. Initialize the project:
    terraform init
    
  5. Review the plan:
    terraform plan
    
  6. Apply the configuration:
    terraform apply
    

Configuration Files

1. terraform.auto.tfvars (User Configuration)

This is the primary file you will edit.

# ----------------------------------------------------------------
#               CSC Deployment Configuration
# ----------------------------------------------------------------

# --- CSC MUX Model ---
# 1 = zs-csc-mux-1 (1 ZTUN)
# 2 = zs-csc-mux-2 (2 ZTUNs)
# 4 = zs-csc-mux-4 (4 ZTUNs)
# 8 = zs-csc-mux-8 (8 ZTUNs)
csc_model_version = 2 # <--- SET YOUR MODEL HERE

# --- Select Single or HA ---
# 1 = Single VM
# 2 = High Availability (HA) Pair
vm_count        = 2

# -- Deployment Choices --
# "az" = Availability Zones (Recommended for HA)
# "as" = Availability Sets (For regions without AZs)
# "ni" = No Infrastructure (Single VM or standalone VMs)
deployment_type = "az"

# -- Availability Zone Settings (Only used if deployment_type = "az") --
# Ensure you have one zone per VM in vm_count.
availability_zones      = ["1", "2"]


# -- Availability Set Settings (Only used if deployment_type = "as") --
availability_set_name   = "zs-csc-av-set"
fault_domains           = 2
update_domains          = 5

# -- VM Configuration --
# This is the base name for all your VMs (e.g., "zs-csc-mux")
vm_name_prefix          = "zs-csc-mux-2-az"

# The resource group where the new VMs and NICs will be created.
resource_group_name       = "my-zscaler-rg"

# --- IMPORTANT ---
# Recommended VM Sizes:
# zs-csc-mux-1: "Standard_B2ats_v2"
# zs-csc-mux-2: "Standard_D2s_v3"
# zs-csc-mux-4: "Standard_D4s_v3"
# zs-csc-mux-8: "Standard_D8s_v3"
# Models 4 and 8 require Accelerated Networking.
vm_size                 = "Standard_B2ats_v2"

# Example: "Standard_LRS", "Premium_LRS", "StandardSSD_LRS"
storage_disk_type       = "Standard_LRS"


# -- VM Authentication --
# "sshPublicKey" or "password"
authentication_type     = "sshPublicKey"

# Paste your *full public SSH key* here (if using sshPublicKey)
# or your desired password (if using password).
admin_password_or_key   = "ssh-rsa AAAA..." # <--- REPLACE THIS

# The names of your *existing* network resources.
vnet_name                = "my-vnet"
vnet_resource_group_name = "my-network-rg"
external_subnet_name     = "csc-external-subnet"
internal_subnet_name     = "csc-internal-subnet"

Outputs

NameDescription
virtual_machine_namesThe names of the created virtual machines.
vm_public_ipsA map of all external IPs (Bypass and ZTUNs) for each VM.
vm_private_ipsA map of the primary private IPs for each VM's internal NIC.
vm_managed_identity_principal_idsA map of the Managed Identity Principal IDs for each VM, used for role-based access control.