Zscaler Internet Access Terraform Provider (Unofficial)

In this article I will introduce a custom Terraform provider for ZIA. This article will describe some of the common use cases, where this ZIA provider can be useful, and how it can contribute to make organizations adopting a DevOps mindset more agile and secure. The instructions about how to install the provider plugin for different Terraform versions and operating system platforms is described in the GitHub repository README page.

Once you finish following the install instructions, then navigate to the Index page that explains about how to initialize the provider within your Terraform environment, as well as how to provide the necessary authentication credentials. There are also several configuration examples for all available resources and data sources, to assist with the configuration of your ZIA environment in the Examples folder.

:warning: Important: It is important to emphasize that this Terraform provider is not in any way supported or maintained by Zscaler engineering or support teams; hence, it is provided “AS IS” as a community effort.

Currently, the following features are supported via this Terraform provider based on API a availability:

  • Admin Account Creation
  • DLP Dictionaries
  • Cloud Firewall Policies: Rules, IP Source Groups, IP Destination Groups, Network Application Groups, Network Services Groups, Network Services,
  • Location, Location Groups, and Sub-Location Management
  • Traffic Forwarding: Static IPs, GRE Tunnels, VPN Credentials (IPSec Tunnels)
  • Local User Accounts and assignment to Groups and Departments.
  • Custom URL Categories
  • URL Filtering Policies

As more API resources become available, the provider will be updated on a best effort basis.

Terraform Limitations

Propagating configuration changes throughout the ZIA cloud requires activation, so that those changes can take effect.
One of the few limitations with Terraform at the moment, is that it does not provide native support for commits or post-activation of configuration, so any policy/configuration activation in ZIA using this provider must be handled out-of-band.
To solve this limitation, I developed a CLI utility that can be used with the provider itself. For instructions on how to use the zia activator CLI utility, please refer to the following repository document here

Most Common Use Case(s)

One of the most common use cases this provider may be used for, is to expedite and simplify the forwarding of traffic from datacenters and branch office locations to the ZIA cloud, either via IPSec or GRE tunnels. It will essentially allow for rapid templating, deployment and standardization of how you connect remote locations to the Zscaler cloud.

Deploying a Location with GRE Tunnel

Static IP Creation
The Static IP creation is one of the main requirements in order to create a location management and/or a GRE Tunnel; hence, this resource must always be created first, so Terraform can automatically interact with the API to take care of any further dependencies. In this case, I am creating a fictitious static IP resource.
It is important to note that in this snippet configuration, the option geo_override is set to false by default, which corresponds to “Automatic” in the UI; hence, the system will automatically calculate parameters such as latitude and longitude. In my opinion it is rare that you may need to set this option to true, but if so, you will need to provide the geographic coordinates accordingly.

resource "zia_traffic_forwarding_static_ip" "au_vancouver_branch_gre01"{
    ip_address    =  "1.1.1.1"
    routable_ip   = true
    comment       = "Vancouver - Branch01"
    geo_override  = false
}

GRE Tunnel Creation
The GRE Tunnel resource, depends on the Static IP to be created. In other words, the static ip resource must be created first. To manipulate the order of resource creation, we are leveraging the built-in Terraform Meta-Argument called depends_on, which essentially handles hidden resource or module dependencies that Terraform can’t automatically infer. In other words, it tells Terraform to wait until the indicated resource(s) are created before proceeding with this exact resource creation.

// Create GRE Tunnel
resource "zia_traffic_forwarding_gre_tunnel" "au_vancouver_branch_gre01" {
  source_ip      = zia_traffic_forwarding_static_ip.au_vancouver_branch_gre01.ip_address
  comment        = "GRE Tunnel Created with Terraform"
  within_country = true
  country_code   = "CA"
  ip_unnumbered  = false
  depends_on     = [ zia_traffic_forwarding_static_ip.au_vancouver_branch_gre01 ]
}

Notes:

  • IP Unnumbered: Another important parameter to note in the GRE tunnel creation, is the ip_unnumbered = false. When this value is set to false, the system will automatically choose a Zscaler internal /29 CIDR ip range. In this case, you then have the option to set the parameter internal_ip_range; however, you will need to know the range available for your ZIA tenant. I’d recommend let the system choose it automatically for you unless there is a specific reason you need a different range.

  • Within Country: This parameter basically restricts the Datacenter virtual IP address (VIPs) only to those within the same country based on the source_ip address provided.

Location Management Creation

The final step in creating a location in ZIA using the Terraform provider, is associating the previously created resources with the location resource. In this case, we need to associate the static_ip resource with it via the parameter below ip_addresses, and then indicate the dependencies by using the Meta-Argument depends_on again.
Finally, you can optionally enable features such as surrogate IP, authentication or if you are subscribed to features such as: Cloud Firewall and/or IPS Control you can also enable that in your configuration as showed in the snippet below.

resource "zia_location_management" "ca_vancouver_branch_gre01"{
    name                 = "AU - Vancouver - Branch01"
    description          = "Created with Terraform"
    country              = "CANADA"
    tz                   = "CANADA_AMERICA_VANCOUVER"
    auth_required        = true
    idle_time_in_minutes = 720
    display_time_unit    = "HOUR"
    surrogate_ip         = true
    xff_forward_enabled  = true
    ofw_enabled          = true
    ips_control          = true
    ip_addresses         = [ zia_traffic_forwarding_static_ip.ca_vancouver_branch_gre01.ip_address ]
    depends_on           = [ zia_traffic_forwarding_static_ip.ca_vancouver_branch_gre01, zia_traffic_forwarding_gre_tunnel.ca_vancouver_branch_gre01 ]
}

Deploying a Location with IPSec Tunnel
Building an IPSec tunnel in ZIA using Terraform, follows a similar logic as the previous GRE tunnel configuration. The exception here is that the GRE tunnel creation step is not required. To keep this article short, I will describe only the steps required assuming that we already have the Static IP address resource created.

  • Step 1: Create the Static IP Resource
  • Step 2: Create VPN Credentials
  • Step 3: Create the location management

In this section, I describe only Step 2 and simplify Step 3.

// Create VPN Credential
resource "zia_traffic_forwarding_vpn_credentials" "ca_vancouver_ipsec"{
    type           = "UFQDN"
    fqdn           = "vancouver@acme.com"
    comments       = "Vancouver - IPSec Tunnel"
    pre_shared_key = "P@ssw0rd123!"
}

Note: The provider treats the pre_shared_key as a sensitive value for obvious security reasons. Although, in the snippet above, the pre-shared_key parameter is specified in clear text, you can technically, store this value in an encrypted fashion in something like AWS SSM Parameter store or HashiCorp Vault, and set the ZIA provider to retrieve this value from those sources instead.

Finally, you can now create the actual location and associate the VPN credentials with the resource.

// Creating location management resource
resource "zia_location_management" "ca_vancouver_ipsec"{
    name           = "CA - Vancouver - Branch01"
    description    = "Created with Terraform"
    country        = "CANADA"
    tz             = "CANADA_AMERICA_VANCOUVER"
    ip_addresses   = [ zia_traffic_forwarding_static_ip.ca_vancouver_branch01.ip_address ]
    vpn_credentials {
       id   = zia_traffic_forwarding_vpn_credentials.ca_vancouver_ipsec.vpn_credental_id
       type = zia_traffic_forwarding_vpn_credentials.ca_vancouver_ipsec.type
    }
    depends_on     = [ zia_traffic_forwarding_static_ip.ca_vancouver_branch01, zia_traffic_forwarding_vpn_credentials.ca_vancouver_ipsec ]
}

Zscaler Cloud Firewall Rules
The other use case, is to manage cloud firewall rules in a more automated fashion, for example, as part of a CI/CD pipeline so that the creation can go through the right approval chain.
If that’s your objective, this provider will have you covered. Below is a simplified firewall rule in HCL format.

resource "zia_firewall_filtering_rule" "example" {
    name = "Example"
    description = "Example"
    action = "ALLOW"
    state = "ENABLED"
    order = 1
    enable_full_logging = true
    nw_services {
        id = [ data.zia_firewall_filtering_network_service.zscaler_proxy_nw_services.id ]
    }
    departments {
        id = [ data.zia_department_management.engineering.id ]
    }
    groups {
        id = [ data.zia_group_management.normal_internet.id ]
    }
    time_windows {
        id = [ data.zia_firewall_filtering_time_window.work_hours.id ]
    }
}

data "zia_firewall_filtering_network_service" "zscaler_proxy_nw_services" {
    name = "ZSCALER_PROXY_NW_SERVICES"
}

data "zia_department_management" "engineering" {
 name = "Engineering"
}

data "zia_group_management" "normal_internet" {
    name = "Normal_Internet"
}

data "zia_firewall_filtering_time_window" "work_hours" {
    name = "Work hours"
}

There are many more examples in the provider GitHub repository, so feel free to visit and send your comments and feedback.
Terraform is an excellent tool for managing your ZIA infrastructure. It enables you to define and configure your ZIA infrastructure programmatically, so that it is automated, predictable, and repeatable.

This, of course, is just the beginning, and as more API resources are made available, the provider will be updated, and new versions released as a best effort in the provider repository in GitHub.

Interested in exploring the Provider? To get started check out the project in the GitHub repository here. Want to contribute or open an issue? Find the project here.

3 Likes

Great work. Thanks.
I will try this and get back to you. ( I don’t prior experience on this, may struggle to set it up :slight_smile: )

Feel free to hit me offline next week, and we can discuss in more details. :wink:

2 Likes

Hi William,
Thanks for your great support.
Now I am able to successfully manage the ZIA portal through terraform.

Regards
Ramesh M