Public/Get-MgkTenantConfig.ps1
|
function Get-MgkTenantConfig { <# .SYNOPSIS Loads and validates a tenant fleet configuration file. .DESCRIPTION Reads a JSON array of tenant entries and validates each one before anything tries to authenticate with it: required fields present, tenantId/clientId are well-formed GUIDs, certificateThumbprint is 40 hex characters. Validation failures name the tenant and the field, because "Cannot bind argument" three calls deep helps nobody. .PARAMETER Path Path to the tenants JSON file. .OUTPUTS One PSCustomObject per tenant with TenantName, TenantId, ClientId, CertificateThumbprint (PSTypeName: MspGraphKit.TenantConfig). .EXAMPLE $tenants = Get-MgkTenantConfig -Path ./tenants.json .EXAMPLE Get-MgkTenantConfig -Path ./tenants.json | Test-MgkTenantConnection #> [CmdletBinding()] [OutputType('MspGraphKit.TenantConfig')] param( [Parameter(Mandatory)] [ValidateScript({ Test-Path $_ -PathType Leaf })] [string]$Path ) $entries = Get-Content $Path -Raw | ConvertFrom-Json if ($entries -isnot [array]) { $entries = @($entries) } foreach ($entry in $entries) { $name = $entry.PSObject.Properties['tenantName'].Value ?? '<unnamed>' foreach ($field in 'tenantName', 'tenantId', 'clientId', 'certificateThumbprint') { if (-not $entry.PSObject.Properties[$field] -or [string]::IsNullOrWhiteSpace($entry.$field)) { throw "Tenant '$name': missing required field '$field' in $Path" } } foreach ($field in 'tenantId', 'clientId') { if (-not [guid]::TryParse($entry.$field, [ref][guid]::Empty)) { throw "Tenant '$name': '$field' is not a valid GUID ('$($entry.$field)')" } } if ($entry.certificateThumbprint -notmatch '^[0-9A-Fa-f]{40}$') { throw "Tenant '$name': certificateThumbprint must be 40 hex characters" } [pscustomobject]@{ PSTypeName = 'MspGraphKit.TenantConfig' TenantName = $entry.tenantName TenantId = $entry.tenantId ClientId = $entry.clientId CertificateThumbprint = $entry.certificateThumbprint.ToUpper() } } } |