Migrating NSX Distributed Firewall Policies – part 3
As with many scripts, you start with an MVP (Minimum Viable Product). But as time goes by, you realize that improvements can be made. For the NSX DFW scripts, I changed the script to sanitize the firewall policies to remove some default strings and also change the ID to match the display name. And I added a script to validate if the migration was successful.
- Sanitize-NSXFirewallRules.ps1 — Now removes a default string from the display name before changing the ID to match that display name.
- Compare-NSXMigration.ps1 — Validates an NSX DFW migration by comparing custom objects between source and destination.
How Sanitize-NSXFirewallRules.ps1 works
The script follows a logical four-step flow to ensure data integrity:
- Mapping Initialization
The script starts by building a “dictionary” of old IDs to new IDs. It can ingest this data in two ways:
- Orchestrator Mode: Receiving a live hashtable from a parent script.
- Standalone Mode: Loading a groups_id_mapping.csv file previously generated by the group sanitization process.
- Intelligent String Matching
Replacing IDs in a path like /infra/domains/default/groups/sg-123 is tricky. To avoid errors, the script uses several “Smart Helpers”:
- Longest-Key First: It sorts the ID map by length. This prevents a short ID (like SG-1) from accidentally overwriting part of a longer ID (like SG-100).
- Regex Lookarounds: It uses regular expressions to ensure it only replaces text that is preceded by /groups/ or /services/.
- Unicode Decoding: NSX exports sometimes use hex codes (like \u0027 for a quote). The script decodes these into plain text before processing to ensure the “Find” actually finds the match.
- Rule Sanitization (NSX_Rules.csv)
For every rule in the CSV, the script updates:
- CSV Columns: SourceGroups, DestGroups, AppliedTo, and Services.
- The RawJson Blob: This is the most critical part. NSX stores the actual API payload in a column called RawJson. The script dives into this JSON string and updates the source_groups[], destination_groups[], and scope[] arrays.
- Policy Sanitization (NSX_Policies.csv)
Policies are the “containers” for rules. The script performs a deeper cleanup here:
- Suffix Removal: It strips the legacy string :: NSX Service Composer – Firewall from policy names.
- Deduplication: If stripping suffixes results in two policies having the same name, it automatically appends numeric suffixes (e.g., -1, -2) to keep them unique.
- ID Synchronization: It updates the Policy ID, DisplayName, and Relative Path to match the new, clean name.
How Compare-NSXMigration.ps1 works
This script, Compare-NSX-Migration.ps1, acts as the “Quality Control” layer of the migration process. While the other scripts are responsible for exporting, renaming, sanitizing, and importing data, this one is designed to prove that the migration was successful by comparing the state of the environment “Before” vs. “After”. It is essential to ensure that no firewall rules, groups, or services were lost in translation.
🔍 What is the Script’s Core Purpose?
The primary goal is to provide a reconciliation report. In complex NSX migrations, it is easy for a single rule or a nested group to go missing. This script connects to both the source and destination NSX Manager and compares selected objects using the mapping file that was generated during the sanitization step.
⚙️ How it Works: The Logic Flow
- Multi-Object Comparison
The script doesn’t just look at one file; it is built to handle four distinct categories of NSX data:
- Groups: Compares membership and inventory.
- Services: Checks port and protocol definitions.
- Firewall Rules: The bulk of the heavy lifting; it ensures every rule exists in the new environment.
- Policies: Verifies the high-level containers for those rules.
- Smart Mapping (The “Bridge”)
Because the target environment uses sanitized names (human-readable) while the source uses legacy IDs (system-generated), a direct “A to B” comparison would fail.
- The script uses a Mapping File (groups_id_mapping.csv) to “translate” the old names into the new ones before comparing.
- This allows the script to confirm that “SecurityGroup-123” in the old system is functionally identical to “Web_Servers_Prod” in the new system.
- The Comparison Engine
For every object found in the Source, the script performs a lookup in the Target. It categorizes each item into one of three states:
- Match: The object exists in both and the translated IDs align.
- Mismatch: The object exists on both but the IDs misalign.
- Missing on destination: An object from the source is nowhere to be found in the target.
- Extra on destination: An object exists in the target that wasn’t in the source (less common, but important for tracking).
- Detailed Reporting
The script generates a color-coded summary in the PowerShell console and exports a final CSV report. This report is often used as compliance documentation to sign off on a migration phase.
🛠️ Technical Highlights
- Normalization: It cleans up whitespace and formatting on the fly so that a simple trailing space doesn’t cause a “false negative” mismatch.
- Flexible Execution: It can be run as a standalone verification tool or called by an orchestrator script to provide an immediate “Pass/Fail” post-migration.
- Path Awareness: It specifically understands NSX pathing logic (e.g., /infra/domains/default/groups/…), ensuring it only compares the relevant ID segments of a string.