It can be a challenge to maintain documentation & diagrams up-to-date when there are changes going on in an environment you might be responsible for the design or strategy of or general day to day front line support. Being part of a larger team or having some level of oversight responsibility means changes can occur to configurations that are not well socialised and all of a sudden what you knew or thought about a deployment of a component is no longer current which in itself can be a problem. Depending on the function you are responsible for, the changes might not directly matter that much to you hence why I say it can as opposed to it will. The changes that occur can impact processes such as the ones listed below but not just these, this list is just some of the key things impacted:
- General Configuration Management & Desired State Configuration
- Change control
- Documentation and Diagram maintenance
- Architecture and Strategy planning
- Service Dependency Mapping & Systems Monitoring
- Capacity, Availability & Disaster Recovery Planning
- Troubleshooting & Root Cause Analysis
I developed some scripts (all listed together at the bottom) to help overcome some of these challenges so I can quickly and easily see what’s been changing by just flagging changes in configuration between two points in time and then using additional tools to analyse the differences. What is key here is not so much the PowerShell scripting I developed and used (as there are always many languages and tools!) but primarily what I was trying to achieve and achieve it with relative simplicity. As you will see, I run some scripts, compare some output and get a quick indication of what’s changed and where to look to get the detail. These types of scripts are not so much required if config change logging is used and ingested by a reporting tool or if you have dynamic documentation tools that capture changes and thus automatically produce updated diagrams and so forth.
The scripts were initially written in a PowerShell 5.1.19041.1 environment with Az Module 3.7.0 on a Windows 10 VM but also tested on later Az Module versions. I kept the scripts in the user “Documents” folder including scripts that contain functions and the scripts utilise “[environment]::getfolderpath(“mydocuments”) to determine script locations and also output folder structure for text file output. The scripts do not have any special error containment or control so file system issues or similar will probably break the script and end up with slabs of error messages.
Information is gathered in a simple form from an Azure subscription and saved locally to text files in a folder structure derived from the account and subscription itself. Specific “Get-Az” commands are used in this first particular script, whilst the “Export-AzResourceGroup” is the key command in the second script. This Export function will raise warnings about limitations in the content of the Resource template that it exports and exporting resources have some maximum limitations (detailed further on). The intent behind the scripts is around capturing point in time information about the configuration state items inside a tenancy such as Resources or specific items such as Network Security Groups (it was written with a focus on network related items). Once two sets of configuration information are caught over a time period such as an hour, day or even week then a comparison function is used to compare the two most recent files and very briefly identify if a change has occurred and flag it for further investigation. This can be used for state change information for change control purposes, documentation or for providing a group of people aware of what’s going on within a subscription.
The primary script relies on specific Az Module commands being called, you can pick out what matters to you and it will cycle through all of them in the Array. It also enumerates all the subscriptions you have access to and cycles the Az Module commands through each one, or you can update the script to manually specify them if you so desire. It calls a function which does the actual work of executing the Azure PowerShell commands and capturing the output text files. The scripts do not make any changes to items inside Azure, they’re only command to read and export data, the only writes of course are made to your local file system for exported data. If you want you can download all the scripts contained in the zip file attached.
At a high level the Gathering info script https://github.com/roity57/Azure-Gather-and-Compare-Info/blob/master/AzGatherInfo.ps1 does the following:
- Define the Get- commands desired into Array
- Enumerate Account details & folder locations
- Import Info gathering function and file compare function
- Run a For each loop to process each subscription in the account
- Run a nested For each loop to process each “Get-” command and also call the compare function supplying file pattern and folder location
At a high level the https://github.com/roity57/Azure-Gather-and-Compare-Info/blob/master/AzExportResourceGroups.ps1 Script does the following:
- Enumerate Account details & folder locations
- Import Resource Group export function and file compare function
- Run a For each loop to process each subscription in the account
- Execute the export function (You can simulate the Export Resource group function by adding the “-WhatIf” statement on Line 55 of the function.)
The function code https://github.com/roity57/Azure-Gather-and-Compare-Info/blob/master/Modules/Az-GatherInfoFuncs.ps1 contains a specific command to remove any entries for the “Etag” field that some of the Azure PowerShell commands capture as this field appears to be changed by Azure itself so it presents false positives for when actual configuration changes occur. It creates a sub-folder for each Azure subscription (the first time it’s executed) and saves the command output in that folder named based on the PowerShell command called and also date and time stamped.
- Take parameters of the particular “Get-” command and the current subscription details
- Prepare filename pattern & output path location (create if required)
- Finalise output filename pattern and execute “Get-” command
- Test if output file had content
- If file contains content then Strip any lines with the “Etag” value
- If not, delete the file (prevent creation of empty files!)
The export Resource Group function can be found at https://github.com/roity57/Azure-Gather-and-Compare-Info/blob/master/Modules/Az-ExportRGFuncsAll.ps1, overview below.
- Take parameter specifying the particular subscription
- Prepare filename pattern & output path location (create if required)
- Finalise output filename pattern and execute “Get-” command
- Run a For each loop to process each resource group in the subscription
- Define the filename format for json output
- Define filename pattern for comparing versions
- Call the compare function
Azure has limits for Resource Group exports – https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/azure-subscription-service-limits#resource-group-limits. The Export Resource Group function will fail on a resource group with more than 200 resources
At a high level the file comparison function https://github.com/roity57/Azure-Gather-and-Compare-Info/blob/master/Modules/CompareFunc.ps1 does the following:
- Take parameters being the filename pattern and location
- Enumerate the files matching the pattern & determine if there are sufficient files to compare and if not then take no action and advise otherwise run through file comparison process
- Get the file hashes
- if equal no further action required
- Otherwise compare the files and write the difference output to a file also detailing which two files were different
The set of scripts are;
- https://github.com/roity57/Azure-Gather-and-Compare-Info/blob/master/AzGatherInfo.ps1
- https://github.com/roity57/Azure-Gather-and-Compare-Info/blob/master/AzExportResourceGroups.ps1
- https://github.com/roity57/Azure-Gather-and-Compare-Info/blob/master/Modules/Az-GatherInfoFuncs.ps1
- https://github.com/roity57/Azure-Gather-and-Compare-Info/blob/master/Modules/Az-ExportRGFuncsAll.ps1
- https://github.com/roity57/Azure-Gather-and-Compare-Info/blob/master/Modules/CompareFunc.ps1
The scripts here have been openly publicly posted here as my way of giving back to the IT community, your decision to use the scripts is of course at your own risk. I’ve done as much testing as practicable however this does not mitigate unexpected outcomes in data output or file comparisons. If I find issues at some point I’ll always try to apply them where referenced on the blog as timely as possible.
(Updated 2/8/2020 – all scripts now located at Github with version control)