Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 105 additions & 83 deletions README.md

Large diffs are not rendered by default.

79 changes: 66 additions & 13 deletions contributionGuide.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,72 @@
# Contribution guide

## Rule: Never hand-edit `pwsh/AzGovVizParallel.ps1`

**`pwsh/AzGovVizParallel.ps1` is a generated file.** It is assembled from `pwsh/dev/` by the build script and is roughly 39,000 lines long.

- Make **all** your changes in `pwsh/dev/` - the functions live in `pwsh/dev/functions/`, the main script body in `pwsh/dev/devAzGovVizParallel.ps1`.
- Then run the build (step 6) to regenerate `pwsh/AzGovVizParallel.ps1`.
- Any edit made directly in `pwsh/AzGovVizParallel.ps1` is silently overwritten by the next build - or, if it is committed, it makes the generated file diverge from its sources.

Commit both the `pwsh/dev/` changes **and** the regenerated `pwsh/AzGovVizParallel.ps1`.

## Prerequisites

- PowerShell Core **7.0.3** or newer (`$PSVersionTable`).
- The [AzAPICall](https://www.powershellgallery.com/packages/AzAPICall) PowerShell module.
- Internet access for the build - it compares your version against the version published in the repository.
- For step 9: an Azure tenant with at least the `Reader` role on a management group.

## Steps

1. Fork the repository.
2. Create a branch.
3. Change you working directory to `.\Azure-MG-Sub-Governance-Reporting`.
4. In the folder `.\pwsh\dev` find the function you intend to work on and apply your changes.
5. Edit the file `.\pwsh\dev\devAzGovVizParallel.ps1`.
- In the param block update the parameter variable `$ProductVersion` accordingly.
3. Change your working directory to the root of your clone. **All following commands are executed from the repository root** - the build script resolves its paths relative to it.
4. In the folder `pwsh/dev` find the function you intend to work on and apply your changes.
- Functions are located in `pwsh/dev/functions/`. The build picks up every `.ps1` file in that folder recursively, so a new function file does not need to be registered anywhere - but you do have to call it from `pwsh/dev/devAzGovVizParallel.ps1`.
5. Edit the file `pwsh/dev/devAzGovVizParallel.ps1`.
- In the param block update the parameter variable `$ProductVersion` accordingly. This is **mandatory** - the build fails if the version is equal to or lower than the version published in the repository.
- Note: Do not change anything else in this file if you did not introduce new functions!
6. Execute `.\pwsh\dev\buildAzGovVizParallel.ps1` - This step will rebuild the main `.\pwsh\AzGovVizParallel.ps1` file, incorporating all changes you did in the `.\pwsh\dev` directory.
7. Edit the file `.\README.md`.
- Update the region `Release history`, replace the changes from the previous release with your changes.
8. Edit the file `.\history.md`.
- Copy over text for the change description you just did for the `.\README.md`.
9. Execute the newly created AzGovViz version to test if it completes successfully by running `.\pwsh\AzGovVizParallel.ps1 -ShowRunIdentifier`.
6. Execute `./pwsh/dev/buildAzGovVizParallel.ps1` - This step will rebuild the main `pwsh/AzGovVizParallel.ps1` file, incorporating all changes you did in the `pwsh/dev` directory.
- While iterating locally you can skip the version check with `./pwsh/dev/buildAzGovVizParallel.ps1 -skipVersionCompare`. Run the build **without** that switch at least once before you open the pull request.
- The build also writes the product version to `version.json` in the repository root - commit that file together with your changes.
7. Edit the file `README.md`.
- Update the region `Release history`. Add a new `**Changes**` block on top for your version and keep the block of the previous release below it; older entries live in `history.md`.
- If your change is a patch to a version that is already listed, add your bullets to the existing block instead of creating a new one.
8. Edit the file `history.md`.
- Copy over the change description you just did for the `README.md`. The two blocks must be **identical**.
9. Execute the newly created AzGovViz version to test if it completes successfully by running `./pwsh/AzGovVizParallel.ps1 -ShowRunIdentifier`.
- From the very last line of the output copy the __run identifier__, you'll need that when you open your pull request.
10. Commit your changes.
11. Create a pull request.
- Provide the __run identifier__ in the pull request as a proof of successful test.
- Do not commit the report artifacts (HTML, CSV, JSON) that this run produces - they are not covered by `.gitignore`.
10. Run PSScriptAnalyzer on your changes (see [Code style and analysis](#code-style-and-analysis)).
11. Commit your changes.
12. Create a pull request.
- Provide the __run identifier__ in the pull request as a proof of successful test.

## Code style and analysis

Pull requests are checked with [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer). Run it locally before you push - the workflow does not run on forks:

```pwsh
Install-Module -Name PSScriptAnalyzer -Scope CurrentUser
Invoke-ScriptAnalyzer -Path ./pwsh -Recurse -ExcludeRule PSAvoidUsingWriteHost, PSUseDeclaredVarsMoreThanAssignments, PSReviewUnusedParameter, PSUseOutputTypeCorrectly
```

Conventions used throughout the codebase:

- `#region` / `#endregion` to structure longer blocks.
- `$script:` scope for state that is shared between functions.
- `Write-Host` for console output - the corresponding analyzer rule is excluded on purpose.

## Formatting

Formatting is defined in `.vscode/settings.json` and applied automatically by the [PowerShell extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.PowerShell) with `editor.formatOnSave`. Open the repository in VS Code with that extension and you get the expected result without thinking about it.

If you work outside of VS Code, respect these settings manually - they are the reason why an otherwise fine looking change can show up as a large diff:

- PowerShell files are saved as **UTF-8 with BOM** (matches the encoding the build writes).
- Constant strings are single quoted (`useConstantStrings`) and keywords/cmdlets use their correct casing (`useCorrectCasing`, e.g. `param` not `Param`, `default` not `Default`); aliases are expanded (`autoCorrectAliases`).
- Property value pairs in hashtables and `[PSCustomObject]` literals are aligned (`alignPropertyValuePairs`).
- Opening brace on the same line, newline after opening and after closing brace.
- Whitespace around operators, pipes and after separators; no trailing whitespace (Markdown files are exempt).
- 4 spaces for indentation.
31 changes: 31 additions & 0 deletions history.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,37 @@

### Azure Governance Visualizer version 6

**Changes** (2026-Sep-11 / 6.7.4 Patch)

- new feature "Azure Policy Linter" - custom Policy definitions are analyzed with the [Azure Policy Linter](https://github.com/Azure/azure-policy-linter); findings (severity, rule, description, JSON path and line) are reported in TenantSummary and exported to `*_PolicyLinter.csv`. In Azure DevOps / GitHub Actions the linter (`Microsoft.Azure.Policy.PolicyLinter.Cli`) is installed on the fly, on other hosts an installed `policylinter` is used - if the linter is not available the feature is skipped and the report states why
- new feature "Model Deployment Insights" for Azure OpenAI and Azure AI Services (Foundry) model deployments including usage metrics; TenantSummary and each management group and subscription scope in ScopeInsights provide an aggregated model view and a detailed model by Cognitive Services account view, plus CSV export `*_ModelDeploymentInsights.csv`. Collection runs by default and can be skipped with `-NoFoundryModelDeployments`, the metrics time range is defined with `-FoundryModelDeploymentsDays` (default=7)
- the large tables (Policy assignments, Role assignments, Resource Providers detailed) are rendered with [AG Grid](https://www.ag-grid.com/) - row virtualization, per column filters, CSV export respecting the applied filters/column order and 'Pop out grid'
- parameter `-HtmlTableRowsLimit` is obsolete - it has no effect anymore (AG Grid virtualizes rows); the parameter is kept so that existing pipelines do not break
- PIM Eligible assignments are collected from ARM (`roleEligibilityScheduleInstances`) instead of the Microsoft Graph beta `privilegedAccess/azureResources` endpoints; scopes no longer need to be 'PIM onboarded' and tenants without a Microsoft Entra ID P2 license no longer fail the run - the report is created without PIM eligibility data
- PIM Eligible assignments reporting no longer requires to execute Azure Governance Visualizer as ServicePrincipal; the Microsoft Graph application permission `PrivilegedAccess.Read.AzureResources` is replaced by the Azure permission `Microsoft.Authorization/roleEligibilitySchedules/read` (contained in the `Reader` Role), which is validated up front
- fix; PIM Eligible assignments - builtin Role names were not linked to AzAdvertizer and `RoleDataRelated` / `RoleCanDoRoleAssignments` were always reported as `false` (the Role definition cache was queried with the full Role definition resourceId instead of the Role definition GUID)
- fix; Role Assignments - PIM managed active (not eligible) assignments were never flagged, `RoleAssignmentPIMRelated`, `RoleAssignmentPIMAssignmentType` and the assignment slot start/end stayed empty; PIM managed assignments are now detected by `assignmentType` 'Activated' respectively a set `endDateTime`
- fix issue 298; Role Assignments - foreign Principals (e.g. Partner Admins) - Identity Displayname and Identity Type were not resolved for foreign identities; the `directoryObjects/getByIds` request now includes `types` (`user`, `group`, `servicePrincipal`, `device`, `directoryObjectPartnerReference`) and foreign identities are resolved into a `Foreign <objectType>` type with their displayName
- fix; Subnets - a subnet with an IPv6 address prefix aborted the Network enrichment with `An invalid IP address was specified.`; IPv6 prefixes are now ignored in all cases and subnets without an IPv4 prefix report 'n/a'. In addition single digit subnet masks (e.g. `/8`) were not evaluated at all - the available IP addresses of the previously processed subnet were reported
- fix; Orphaned resources - Azure Site Recovery (ASR) managed disks were reported as orphaned although an exclusion was in place (operator precedence in the Resource Graph query dismissed it); ASR disks are now excluded by name (`-ASRReplica`, `ms-asr-`, `asrseeddisk-`), by `ActiveSAS` disk state and by ASR / Recovery Services Vault / AKS persistent volume claim tags
- fix; JSON outputs - `Cannot index into a null array` in case a grouping had no results
- use environment-aware API version for Microsoft Defender for Cloud security settings (`Microsoft.Security/settings`); new `securitySettings` entry in parameter `APIMappingCloudEnvironment` (AzureChinaCloud requires `2021-06-01`)
- update parameter `ValidPolicyEffects` add 'auditAction'
- performance and memory optimizations for the PowerShell processing and the HTML/JSON creation, resulting in a faster run and a smaller HTML output; the JSON outputs (Tenant hierarchy JSON, `*_PolicyAll.json` and the JSON export) are streamed to disk instead of being serialized as a whole (this resolves out of memory aborts on large tenants), garbage collection including Large Object Heap compaction is triggered after the memory intensive phases and repeated lookups in the Role assignment data collection are cached
- use [AzAPICall](https://aka.ms/AzAPICall) PowerShell module version 1.4.2 (previous 1.4.1). Yet, another handle token refresh for OIDC in Azure Devops and GitHub Actions fix

**Changes** (2026-May-18 / 6.7.3 Patch)

- fix issue 294; retirement Classic Administrators

**Changes** (2025-May-21 / 6.7.2 Patch)

- use [AzAPICall](https://aka.ms/AzAPICall) PowerShell module version 1.4.1 (previous 1.4.0). Handle token refresh for OIDC in Azure Devops and GitHub Actions fix

**Changes** (2025-May-20 / 6.7.1 Patch)

- use [AzAPICall](https://aka.ms/AzAPICall) PowerShell module version 1.4.0 (previous 1.2.4). Handle token refresh for OIDC in Azure Devops and GitHub Actions

**Changes** (2025-May-19 / 6.7.0 Minor)

- New feature "ALZ Policy Assignments Checker" - This new view, will compare the current deployed ALZ hierarchy with the ALZ archetypes definitions and point out the missing policy assignments. It will also reference the missing policy assignments' payloads and [AzAdvertizer](https://www.azadvertizer.net/) links.
Expand Down
Loading
Loading