ZIA to Entra Internet Access (EIA) Configuration Transformer
Overview
The Convert-ZIA2EIA function converts ZScaler Internet Access (ZIA) URL filtering configuration to Microsoft Entra Internet Access (EIA) format. It processes URL filtering policies, custom URL categories, and predefined category mappings to generate CSV files ready for import into EIA.
Prerequisites
Required Input Files
-
URL Filtering Policy (
url_filtering_policy.json)- Exported from ZIA API endpoint:
/urlFilteringRules - Contains URL filtering rules with actions, users, groups, and category references
- Exported from ZIA API endpoint:
-
URL Categories (
url_categories.json)- Exported from ZIA API endpoint:
/urlCategories - Contains custom and predefined categories with URL/FQDN/IP lists
- Exported from ZIA API endpoint:
-
Category Mappings (
ZIA-to-GSA-CategoryMapping.csv)- CSV file mapping ZIA predefined categories to GSA categories
- Sample file:
Samples/ZIA2EIA/ZIA-to-GSA-CategoryMapping.rename_to_csv
PowerShell Requirements
- PowerShell 7.0 or higher
- Migrate2GSA module installed
Installation
# Import the module
Import-Module Migrate2GSA
# Verify the function is available
Get-Command Convert-ZIA2EIA
Syntax
Convert-ZIA2EIA
[-UrlFilteringPolicyPath <string>]
[-UrlCategoriesPath <string>]
[-CategoryMappingsPath <string>]
[-OutputBasePath <string>]
[-EnableDebugLogging]
[<CommonParameters>]
Parameters
-UrlFilteringPolicyPath
Path to the ZIA URL Filtering Policy JSON export file.
- Type: String
- Default:
url_filtering_policy.jsonin current directory - Required: No (uses default if not specified)
-UrlCategoriesPath
Path to the ZIA URL Categories JSON export file.
- Type: String
- Default:
url_categories.jsonin current directory - Required: No (uses default if not specified)
-CategoryMappingsPath
Path to the ZIA to EIA category mappings CSV file.
- Type: String
- Default:
ZIA-to-GSA-CategoryMapping.csvin current directory - Required: No (uses default if not specified)
-OutputBasePath
Base directory for output CSV files and log file.
- Type: String
- Default: Current directory
- Required: No (uses default if not specified)
-EnableDebugLogging
Enable verbose debug logging for detailed processing information.
- Type: Switch
- Default: False
- Required: No
Examples
Example 1: Basic Conversion
Convert-ZIA2EIA
Converts ZIA configuration using default file paths in the current directory.
Example 2: Custom Input Paths
Convert-ZIA2EIA `
-UrlFilteringPolicyPath "C:\ZIA\url_filtering_policy.json" `
-UrlCategoriesPath "C:\ZIA\url_categories.json" `
-CategoryMappingsPath "C:\ZIA\ZIA-to-GSA-CategoryMapping.csv" `
-OutputBasePath "C:\Output"
Converts ZIA configuration from specified paths and saves output to C:\Output.
Example 3: Enable Debug Logging
Convert-ZIA2EIA -EnableDebugLogging
Converts ZIA configuration with detailed debug logging enabled.
Example 4: Pipeline Usage
# Navigate to data directory and run conversion
Set-Location C:\ZIA\Export
Convert-ZIA2EIA -EnableDebugLogging | Out-Null
Get-ChildItem *.csv | Format-Table Name, Length, LastWriteTime
Changes to the data directory, runs the conversion, and lists the output files.
Output Files
All output files are created in the OutputBasePath directory with a timestamp prefix (yyyyMMdd_HHmmss).
1. EIA Policies CSV
Filename: [timestamp]_EIA_Policies.csv
Contains web content filtering policies for custom URL categories and predefined category references.
Fields:
PolicyName: Unique policy identifierPolicyType: Always "WebContentFiltering"PolicyAction: "Block", "Allow", or "Caution"Description: Policy descriptionRuleType: "FQDN", "URL", "webCategory", or "ipAddress"RuleDestinations: Semicolon-separated list of destinationsRuleName: Sub-rule identifier for grouping/splittingReviewNeeded: "Yes" or "No" flag for manual reviewReviewDetails: Semicolon-separated list of review reasonsProvision: "Yes" or "No" flag indicating if the entry should be provisioned
2. EIA Security Profiles CSV
Filename: [timestamp]_EIA_SecurityProfiles.csv
Contains security profile definitions that reference web content filtering policies and assign them to users/groups.
Fields:
SecurityProfileName: Security profile name (from rule name)Priority: Rule priority (order × 10)SecurityProfileLinks: Semicolon-separated policy names with priority suffixes (e.g.,PolicyName:100;PolicyName2:200)CADisplayName: Conditional Access policy display name (format:InternetAccess-[RuleName])EntraUsers: Semicolon-separated user emailsEntraGroups: Semicolon-separated group namesDescription: Profile descriptionProvision: "Yes" or "No" flag indicating if the profile should be provisioned
3. Log File
Filename: [timestamp]_Convert-ZIA2EIA.log
Comprehensive log file with all processing details, warnings, and statistics.
Processing Logic
Phase 1: Data Loading
- Load and validate all input JSON files
- Build lookup tables for categories and mappings
- Initialize statistics tracking
Phase 2: Custom Category Processing
- Filter and validate custom categories
- Deduplicate URL entries
- Clean destinations (remove schemas, ports, query strings, fragments)
- Classify destinations (FQDN, URL, IP address)
- Group destinations by base domain
- Split by character limit (300 characters for FQDN/URL/IP)
- Create policy entries
Phase 3: URL Filtering Rule Processing
- Filter enabled rules (skip disabled)
- Extract users and groups
- Separate custom from predefined categories
- Create/reference custom category policies (Block or Allow)
- Create predefined category policies
- Create security profiles
- Resolve priority conflicts
Phase 4: Export and Summary
- Cleanup unreferenced policies
- Export Policies CSV (with priority suffixes added to SecurityProfileLinks)
- Export Security Profiles CSV
- Display summary statistics
Phase 5: Global Secure Access Limits Validation
- Calculate unique policy count
- Calculate total FQDNs and URLs
- Validate against GSA limits:
- Max Web Content Filtering Policies: 100
- Max Rules across all policies: 1000
- Max FQDNs and URLs combined: 8000
- Max Security Profiles: 256
- Display warnings for any limit violations
URL Processing Rules
Cleaning Operations
The function automatically cleans destination entries:
- ZScaler Wildcards:
.domain.com→*.domain.com(converts ZScaler leading dot format to EIA wildcard format) - Schemas:
https://example.com→example.com - Ports:
example.com:8080→example.com(for non-IP entries) - Query strings:
example.com?param=value→example.com - Fragments:
example.com#section→example.com - IPv4 with port/path:
192.168.1.100:8080→ skipped
All cleaning operations are logged at DEBUG level.
Classification Rules
- IP Addresses: Match IPv4 pattern, validated for valid octets (0-255)
- URLs: Contain "/" or wildcard not at start (e.g.,
domain*.com) - FQDNs: Start with "
*." or no wildcards (e.g.,*.contoso.com,example.com)
Grouping and Splitting
- FQDNs and URLs: Grouped by base domain (last 2 segments)
- IP Addresses: Not grouped by domain
- Character Limit: 300 characters (excluding field quotes, including semicolons)
- Web Categories: No character limit, never split
Category Mapping
Predefined Categories
Predefined ZIA categories are mapped to GSA categories using a CSV file with the following structure:
CSV Format (ZIA-to-GSA-CategoryMapping.csv):
ZIACategory,GSACategory,Note
OTHER_ADULT_MATERIAL,PornographyAndSexuallyExplicit,Partial match - other adult material relates to sexually explicit content
SOCIAL_NETWORKING,SocialNetworking,Exact match
INTERNET_GAMBLING,Gambling,Exact match
Sample File: A comprehensive mapping file is available at Samples/ZIA2EIA/ZIA-to-GSA-CategoryMapping.rename_to_csv
Unmapped Categories
The function tracks two types of unmapped categories:
-
Missing in Mapping File: ZIA category referenced in policies but not found in the CSV file
- Logged as: "ZIA category '[CategoryID]' not found in mapping file"
- Tracked in:
UnmappedCategories_MissingInFilestatistic
-
No Matching GSA Category: Mapping exists but
GSACategorycolumn is empty or null- Logged as: "ZIA category '[CategoryID]' has no matching GSA category (empty/null GSACategory)"
- Tracked in:
UnmappedCategories_NoGSAValuestatistic
Both types are handled the same way:
- Output uses placeholder format:
[ZIACategoryID]_Unmapped ReviewNeededset to "Yes" in outputReviewDetailsincludes "Unmapped categories found"Provisionset to "No"
Policy Naming Conventions
Custom Category Policies
- Block policies:
[CategoryName]-Block(created during Phase 2) - Allow policies:
[CategoryName]-Allow(created on demand in Phase 3) - Caution policies:
[CategoryName]-Caution(created on demand in Phase 3)
Predefined Category Policies
- Format:
[RuleName]-WebCategories-[Action] - Actions:
Block,Allow, orCaution - Examples:
urlRule1-WebCategories-Block,urlRule2-WebCategories-Caution
Rule Names
- FQDN/URL rules: Base domain (e.g.,
example.com,example.com-2) - IP address rules:
IPs,IPs-2,IPs-3 - Web category rules:
WebCategories(no numeric suffix)
Action Handling
BLOCK Action
- Custom categories: Uses Block policy created in Phase 2
- Predefined categories: Creates policy with
PolicyAction = "Block"
ALLOW Action
- Custom categories: Creates Allow policy by duplicating Block policy entries with
PolicyAction = "Allow" - Predefined categories: Creates policy with
PolicyAction = "Allow"
CAUTION Action
- Custom categories: Creates Caution policy by duplicating Block policy entries with
PolicyAction = "Caution" - Predefined categories: Creates policy with
PolicyAction = "Caution" - Logged as WARNING
ReviewNeededset to "Yes"ReviewDetailsincludes "Rule action CAUTION requires review"Provisionset to "No"
Priority Conflicts
When multiple rules have the same order value:
- Calculate initial priority:
Priority = order × 10 - Check for conflicts with existing priorities
- Increment priority until unique:
Priority + 1 - Log conflict resolution at INFO level
- Each conflict resolution increments the
PriorityConflictsResolvedstatistic
Statistics
The function tracks and logs:
- Total rules loaded/processed/skipped
- Custom categories processed/skipped
- Predefined categories referenced
- Unmapped predefined categories (split into two types):
- Missing in mapping file
- No matching GSA category
- URLs/FQDNs/IPs classified
- Users/groups processed
- Policies/security profiles created
- Groups split for character limits
- Priority conflicts resolved
Known Limitations
- IP Addresses: Not supported by Entra Internet Access web content filtering
- IPv4 addresses are exported with
Provision = "No"andReviewNeeded = "Yes"for reference only - IPv6 addresses are not supported and are skipped entirely with a warning
- IPv4 addresses are exported with
- Character Limits: 300-character limit per Destinations field (except webCategory type which has no limit)
- Base Domain: Simple last-2-segments approach (may not handle all TLDs correctly)
- CIDR Ranges: Not supported for IP addresses
- Port Numbers: Not supported for IP addresses (IPv4 with port/path is skipped with warning)
- Memory: All data held in memory (acceptable for expected data sizes)
Troubleshooting
File Not Found Errors
Ensure all three input files exist in the specified paths:
Test-Path "url_filtering_policy.json"
Test-Path "url_categories.json"
Test-Path "ZIA-to-GSA-CategoryMapping.csv"
Invalid File Format Errors
Validate JSON syntax for policy and categories files:
Get-Content "url_filtering_policy.json" -Raw | ConvertFrom-Json | Out-Null
Get-Content "url_categories.json" -Raw | ConvertFrom-Json | Out-Null
Validate CSV format for category mappings:
Import-Csv "ZIA-to-GSA-CategoryMapping.csv" | Select-Object -First 5
Empty Output
Check that:
- At least one rule has
state: "ENABLED" - Custom categories contain URL entries
- Rules reference valid category IDs
Review Flags
Policies/profiles flagged for review require manual attention:
- Unmapped categories: Update category mappings file or manually map in EIA
- CAUTION actions: Verify Block action is appropriate
Priority Conflicts
Multiple rules with same priority are automatically resolved by incrementing. Review log file for details.
Related Functions
Export-ZIAConfig: Exports ZIA configuration filesConvert-ZPA2EPA: Converts ZPA to EPA configurationStart-EntraPrivateAccessProvisioning: Provisions EPA configuration
Support
For issues or questions:
- Check the log file for detailed error messages
- Enable debug logging with
-EnableDebugLogging - Review sample files in
Samples\ZIA2EIA\directory - Consult the specification document:
Specs\20251013-Convert-ZIA2EIA.md