Skip to main content

ZPA to Entra Private Access (EPA) Configuration Transformer

Overview

This PowerShell function (Convert-ZPA2EPA) transforms exported Zscaler Private Access (ZPA) application segment configurations into a format suitable for Microsoft Entra Private Access (EPA). It processes JSON export files from ZPA and generates CSV files containing Enterprise Application configurations that can be imported into Microsoft's Global Secure Access (GSA) solution.

What It Does

The function performs the following key functions:

  1. Loads ZPA Configuration: Reads JSON export files containing ZPA application segments, segment groups, access policies, and SCIM groups
  2. Processes Access Policies: Automatically maps ZPA access policies to SCIM groups and populates Entra ID group assignments
  3. Transforms Data: Converts ZPA application segments into EPA-compatible Enterprise Application configurations
  4. Detects Conflicts: Identifies potential configuration conflicts using GSA-style interval-based detection
  5. Generates Output: Creates CSV files with all necessary configurations for EPA deployment
  6. Provides Guidance: Offers detailed logging and next-step recommendations

Key Features

Access Policy Integration

  • Automatic Group Mapping: Processes ZPA access policies to automatically populate Entra ID group assignments
  • User and Group Support: Processes both SCIM groups and individual SCIM usernames from access policies
  • APP_GROUP Expansion: Automatically expands application segment groups to individual applications
  • SCIM Group Resolution: Resolves SCIM group IDs to group names from identity provider
  • Policy Filtering: Intelligently filters and processes only valid access policies
  • Smart Placeholders: Uses different placeholder values based on whether access policies are found

Advanced Filtering

  • Exact Name Matching: Process specific application segments by name
  • Wildcard Pattern Matching: Use patterns like *web* to match multiple segments
  • Skip Filters: Exclude specific segments or patterns from processing
  • Combination Filtering: Apply multiple filters simultaneously

Intelligent Conflict Detection

  • IP Range Overlaps: Detects conflicts between IP addresses and CIDR ranges
  • Port Range Conflicts: Identifies overlapping port ranges across protocols
  • FQDN Conflicts: Catches duplicate hostnames with conflicting configurations
  • Wildcard Domain Handling: Manages conflicts with wildcard DNS patterns (*.domain.com)

Comprehensive Validation

  • CIDR Validation: Ensures proper subnet notation and valid IP ranges
  • Port Range Validation: Validates TCP/UDP port ranges (1-65535)
  • IP Address Validation: Checks IP address format and octet values
  • Data Integrity: Handles malformed or incomplete configurations gracefully

Comprehensive Output

  • Structured Logging: Color-coded console output with file logging
  • Progress Tracking: Real-time progress indicators for large datasets
  • CSV Export: Clean, Excel-compatible CSV output
  • Conflict Reporting: Detailed conflict analysis and resolution guidance

Prerequisites

System Requirements

  • PowerShell: Version 5.1 or later (PowerShell 7+ recommended)
  • Operating System: Windows 10/11 or Windows Server 2016+
  • Memory: Minimum 4GB RAM (8GB+ recommended for large configurations)
  • Storage: Sufficient disk space for input JSON files and output CSV files

Required Files

  • Required: ZPA Application Segments JSON export file (typically named application_segments.json)
  • Optional: ZPA Segment Groups JSON export file (segment_groups.json) - for deduplication and APP_GROUP expansion
  • Optional: ZPA Access Policies JSON export file (access_policies.json) - for automatic group mapping
  • Optional: SCIM Groups JSON export file (scim_groups.json) - for SCIM group name resolution
  • All files generated by the companion Export-ZPAConfig function

Parameters

Input/Output Parameters

ParameterTypeRequiredDescription
AppSegmentPathStringNoPath to the ZPA Application Segments JSON file (default: App_Segments.json in current directory)
OutputBasePathStringNoBase directory for output files (default: current directory)
PassThruSwitchNoReturn results to pipeline instead of just saving to file

Access Policy Parameters (Optional)

ParameterTypeRequiredDescription
SegmentGroupPathStringNoPath to ZPA Segment Groups JSON file (used for deduplication and APP_GROUP expansion)
AccessPolicyPathStringNoPath to ZPA Access Policies JSON file (default: access_policies.json in current directory)
ScimGroupPathStringNoPath to SCIM Groups JSON file (default: scim_groups.json in current directory)

Filtering Parameters

ParameterTypeRequiredDescription
TargetAppSegmentNameStringNoProcess only the segment with this exact name
AppSegmentNamePatternStringNoWildcard pattern for segment names (e.g., *web*, prod-*)
SkipAppSegmentNameStringNoComma-separated list of exact segment names to skip
SkipAppSegmentNamePatternStringNoComma-separated list of wildcard patterns to skip

Debug Parameter

ParameterTypeRequiredDescription
EnableDebugLoggingSwitchNoEnable verbose debug logging for troubleshooting

Usage Examples

Basic Usage

Transform all application segments using default settings:

Convert-ZPA2EPA

Specify Custom Paths

Use custom input and output paths:

Convert-ZPA2EPA -AppSegmentPath "C:\ZPA\exports\App_Segments.json" -OutputBasePath "C:\EPA\output"

Process Specific Segment

Transform only a specific application segment:

Convert-ZPA2EPA -TargetAppSegmentName "Web-Application-Prod"

Pattern-Based Filtering

Process all production web applications:

Convert-ZPA2EPA -AppSegmentNamePattern "*web*prod*"

Skip Specific Segments

Process all segments except test environments:

Convert-ZPA2EPA -SkipAppSegmentNamePattern "*test*,*dev*"

Debug Mode

Enable detailed logging for troubleshooting:

Convert-ZPA2EPA -EnableDebugLogging

With Access Policy Integration

Automatically populate Entra ID group assignments from ZPA access policies:

Convert-ZPA2EPA `
-AppSegmentPath "C:\ZPA\application_segments.json" `
-SegmentGroupPath "C:\ZPA\segment_groups.json" `
-AccessPolicyPath "C:\ZPA\access_policies.json" `
-ScimGroupPath "C:\ZPA\scim_groups.json" `
-OutputBasePath "C:\EPA\output"

Complex Filtering Example

Process production segments while skipping legacy applications:

Convert-ZPA2EPA `
-AppSegmentNamePattern "*prod*" `
-SkipAppSegmentName "Legacy-App-1,Legacy-App-2" `
-SkipAppSegmentNamePattern "*deprecated*" `
-AccessPolicyPath ".\access_policies.json" `
-ScimGroupPath ".\scim_groups.json" `
-EnableDebugLogging

Input File Format

The script expects a JSON file containing an array of ZPA application segments. Each segment should have the following structure:

[
{
"name": "Web-Application-Prod",
"domainNames": ["webapp.company.com", "*.api.company.com"],
"tcpPortRange": [
{"from": 80, "to": 80},
{"from": 443, "to": 443}
],
"udpPortRange": [
{"from": 53, "to": 53}
],
"segmentGroupName": "Production Apps",
"serverGroups": [
{"name": "Web-Servers-Group"}
]
}
]

Required Fields

  • name: Application segment name
  • domainNames: Array of domains (IP addresses, CIDR ranges, or FQDNs)

Optional Fields

  • tcpPortRange: Array of TCP port ranges
  • udpPortRange: Array of UDP port ranges
  • segmentGroupName: Segment group name
  • serverGroups: Array of server group objects

Output

Generated Files

  1. CSV Export: YYYYMMDD_HHMMSS_GSA_EnterpriseApps_All.csv

    • Timestamped filename for easy identification
    • Contains all transformed Enterprise Application configurations
    • Ready for EPA import or manual configuration
  2. Log File: Convert-ZPA2EPA.log

    • Detailed execution log with timestamps
    • Error tracking and debugging information
    • Color-coded console output mirrored to file

CSV Output Structure

ColumnDescription
SegmentIdUnique segment identifier (SEG-XXXXXX format)
OriginalAppNameOriginal ZPA application segment name
EnterpriseAppNameGenerated EPA Enterprise Application name (prefixed with "GSA-")
destinationHostTarget host (IP, CIDR, or FQDN)
DestinationTypeType of destination (ipAddress, ipRangeCidr, or FQDN)
ProtocolNetwork protocol (TCP or UDP)
PortsPort range (single port or range like "80-443")
SegmentGroupOriginal ZPA segment group
ServerGroupsAssociated server groups
EntraGroupsAuto-populated from access policies or placeholder (see EntraGroups Values below)
EntraUsersAuto-populated from access policies or placeholder for individual user assignments
ConnectorGroupPlaceholder for connector group (replace with actual values)
Conflict"Yes" if conflicts detected, "No" otherwise
ConflictingEnterpriseAppNames of conflicting applications
Provision"Yes" if ready to provision, "No" if conflicts need resolution

EntraGroups and EntraUsers Values

The EntraGroups and EntraUsers columns are automatically populated based on access policy configuration:

EntraGroups Column:

  • Group1; Group2; Group3: Semicolon-separated SCIM group names when access policies are found
  • No_Access_Policy_Found_Replace_Me: Access policy files provided but no policy found for this application
  • Placeholder_Replace_Me: Access policy files not provided (backward compatible mode)

EntraUsers Column:

  • user1@domain.com; user2@domain.com: Semicolon-separated usernames when individual user access policies are found
  • Empty or placeholder: No individual user access policies found for this application

Access Policy Integration

The function can automatically process ZPA access policies to populate Entra ID group assignments, eliminating manual placeholder replacement for the EntraGroups column.

How It Works

  1. Load Access Policies: Reads ZPA access policies from JSON export
  2. Load SCIM Groups: Reads SCIM group mappings from identity provider
  3. Filter Policies: Processes only valid ALLOW policies with simple AND logic
  4. Extract Targets: Identifies which applications and application groups are targeted
  5. Expand APP_GROUPs: Uses segment group membership to expand groups to individual apps
  6. Resolve Groups: Converts SCIM group IDs to group names and extracts SCIM usernames
  7. Build Lookup: Creates mapping of Application ID → SCIM group names and usernames
  8. Populate CSV: Automatically fills EntraGroups and EntraUsers columns with semicolon-separated values

Policy Filtering Criteria

The script processes policies that meet all of these criteria:

  • ✅ Policy Type = "1" (Access Policy)
  • ✅ Action = "ALLOW"
  • ✅ Root Operator = "AND"
  • ✅ Contains APP or APP_GROUP targets
  • ✅ Contains SCIM_GROUP or SCIM username conditions
  • ✅ No negated conditions

Policies that don't meet these criteria are skipped with logged reasons.

Conflict Detection

The function implements sophisticated conflict detection to prevent configuration issues:

IP Range Conflicts

  • Detects overlapping IP addresses (ipAddress) and CIDR ranges (ipRangeCidr)
  • Handles subnet containment and intersection scenarios
  • Validates CIDR notation and IP address formats

Port Range Conflicts

  • Identifies overlapping port ranges within the same protocol
  • Handles single ports and port ranges
  • Separates TCP and UDP conflict detection

Domain Conflicts

  • Catches duplicate FQDN configurations
  • Manages wildcard domain conflicts (*.domain.com)
  • Validates domain name formats

Conflict Resolution

When conflicts are detected:

  1. The conflicting configuration is marked with Conflict: Yes
  2. The ConflictingEnterpriseApp column lists all conflicting applications
  3. The Provision column is set to "No" to prevent automatic deployment
  4. Detailed conflict information is logged for manual review

Post-Processing Steps

After running the function, follow these steps:

1. Review Output

  • Open the generated CSV file in Excel or a text editor
  • Review the summary statistics in the console output
  • Check the log file for any errors or warnings

2. Review and Update Values

The CSV may contain values that need review or replacement:

  • EntraGroups:
    • Auto-populated: If access policies were provided, review the automatically assigned groups for accuracy
    • No_Access_Policy_Found_Replace_Me: Replace with appropriate Entra ID group names for applications without policies
    • Placeholder_Replace_Me: Replace with appropriate Entra ID group names if access policies weren't provided
  • EntraUsers:
    • Auto-populated: If access policies with individual users were found, review the automatically assigned usernames for accuracy
    • Empty or placeholder: Add individual user assignments if needed
  • ConnectorGroup: Replace Placeholder_Replace_Me with appropriate connector group names

3. Resolve Conflicts

For records marked with Conflict: Yes:

  • Review the ConflictingEnterpriseApp column for details
  • Determine if conflicts are legitimate or can be consolidated
  • Modify configurations as needed to resolve conflicts
  • Update the Provision column to "Yes" after resolution

4. Validate Configurations

  • Confirm port ranges are correct for each application
  • Ensure Entra ID groups and connector groups exist
  • Test a small subset before bulk deployment

5. Import to Entra Private Access

Use the completed CSV to configure Enterprise Applications in Microsoft Entra Private Access.

Support and Contributing

This function is provided as-is for experimental use. When encountering issues:

  1. Enable Debug Logging: Use -EnableDebugLogging for detailed information
  2. Check Log Files: Review script.log for error details
  3. Validate Input Data: Ensure ZPA export files are complete and valid
  4. Test Incrementally: Use filtering to isolate problematic segments

For improvements or bug fixes, consider contributing to the repository.

  • Export-ZPAConfig: Companion function for exporting ZPA configurations
  • Microsoft Entra Private Access Documentation
  • Microsoft Global Secure Access Documentation