From e8ad3f6b96ac37d14bcea4c6912dc614d46aaf64 Mon Sep 17 00:00:00 2001 From: Tomas Kracmar Date: Tue, 14 Apr 2026 19:43:54 +0200 Subject: [PATCH] feat(launcher): tenant picker with name resolution in TUI - Start-IntuneToolkit.ps1 now shows a tenant picker as the first step when -TenantId is not provided. - Lists saved tenants from Settings.json, attempting to display cached tenant names alongside GUIDs. - Offers '[+ Onboard new tenant]' option for entering new tenants. - Automatically resolves unknown tenant names via Graph /organization and caches them back to Settings.json for future use. --- Scripts/Start-IntuneToolkit.ps1 | 185 ++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) diff --git a/Scripts/Start-IntuneToolkit.ps1 b/Scripts/Start-IntuneToolkit.ps1 index 78b5703..c3fcd6d 100644 --- a/Scripts/Start-IntuneToolkit.ps1 +++ b/Scripts/Start-IntuneToolkit.ps1 @@ -86,6 +86,183 @@ function Select-MenuItem $projectRoot = Split-Path -Parent $PSScriptRoot +#region Tenant selection +function Get-DefaultSettingsPath +{ + if($IsWindows -or $env:OS -eq "Windows_NT") + { + if($env:LOCALAPPDATA) { return (Join-Path $env:LOCALAPPDATA "macOS_IntuneManagement\Settings.json") } + return (Join-Path $env:USERPROFILE "AppData\Local\macOS_IntuneManagement\Settings.json") + } + if($IsMacOS) { return (Join-Path $HOME "Library/Application Support/macOS_IntuneManagement/Settings.json") } + return (Join-Path $HOME ".local/share/macOS_IntuneManagement/Settings.json") +} + +function Get-SavedTenants +{ + param([string]$SettingsPath) + if(-not (Test-Path $SettingsPath)) { return @() } + try + { + $raw = Get-Content $SettingsPath -Raw -ErrorAction Stop | ConvertFrom-Json -AsHashtable -ErrorAction Stop + $tenants = @() + foreach($key in $raw.Keys) + { + if($key -match '^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$') + { + $name = $null + if($raw[$key] -is [hashtable] -and $raw[$key].ContainsKey('TenantName')) + { + $name = $raw[$key]['TenantName'] + } + elseif($raw[$key] -is [psobject] -and $raw[$key].PSObject.Properties['TenantName']) + { + $name = $raw[$key].TenantName + } + $display = if($name) { "$name ($key)" } else { $key } + $tenants += [PSCustomObject]@{ TenantId = $key; TenantName = $name; Display = $display } + } + } + return $tenants | Sort-Object Display + } + catch + { + return @() + } +} + +function Update-TenantNameCache +{ + param([string]$SettingsPath, [string]$TenantId, [string]$TenantName) + if(-not (Test-Path $SettingsPath)) { return } + try + { + $raw = Get-Content $SettingsPath -Raw -ErrorAction Stop | ConvertFrom-Json -AsHashtable -ErrorAction Stop + if($raw[$TenantId] -is [hashtable]) + { + $raw[$TenantId]['TenantName'] = $TenantName + } + else + { + $raw[$TenantId] = @{ TenantName = $TenantName } + } + $raw | ConvertTo-Json -Depth 10 | Set-Content -Path $SettingsPath -Force + } + catch { } +} + +function Resolve-TenantName +{ + param([string]$TenantId, [string]$SettingsPath) + $settingsObj = $null + try + { + $settingsObj = Get-Content $SettingsPath -Raw -ErrorAction Stop | ConvertFrom-Json -AsHashtable -ErrorAction Stop + } + catch { return $null } + + $tenantNode = $settingsObj[$TenantId] + if(-not $tenantNode) { return $null } + + $appId = $tenantNode['GraphAzureAppId'] + if(-not $appId) { return $null } + + $secret = $tenantNode['GraphAzureAppSecret'] + $cert = $tenantNode['GraphAzureAppCert'] + + if(-not $secret -and $IsMacOS) + { + try + { + $keychainSecret = security find-generic-password -a "IntuneManagement" -s "IntuneMgmt-$AppId" -w 2>$null + if($keychainSecret) { $secret = $keychainSecret } + } + catch { } + } + + $runtimeModule = Join-Path $projectRoot "Runtime/IntuneManagement.Runtime.psd1" + if(-not (Test-Path $runtimeModule)) { return $null } + + $invokeParams = @{ + Silent = $true + JSonSettings = $true + JSonFile = $SettingsPath + TenantId = $TenantId + AppId = $appId + AuthMode = "AppOnly" + } + if($secret) { $invokeParams.Secret = $secret } + elseif($cert) { $invokeParams.Certificate = $cert } + + try + { + Import-Module $runtimeModule -Force | Out-Null + Initialize-IntuneManagementRuntime -View "IntuneGraphAPI" @invokeParams | Out-Null + if(Get-Command Invoke-GraphRequest -ErrorAction SilentlyContinue) + { + $org = Invoke-GraphRequest "/organization" -ErrorAction Stop + if($org.value -and $org.value[0].displayName) + { + return $org.value[0].displayName + } + } + } + catch { } + return $null +} + +$settingsPath = $SettingsFile +if(-not $settingsPath) { $settingsPath = Get-DefaultSettingsPath } + +if(-not $TenantId) +{ + $tenants = Get-SavedTenants -SettingsPath $settingsPath + $tenantOptions = @() + foreach($t in $tenants) + { + $tenantOptions += $t.Display + } + $tenantOptions += "[+ Onboard new tenant]" + $tenantOptions += "[Exit]" + + $selectedTenantDisplay = Select-MenuItem -Items $tenantOptions -Header "Select a tenant" + if(-not $selectedTenantDisplay -or $selectedTenantDisplay -eq "[Exit]") + { + exit 0 + } + elseif($selectedTenantDisplay -eq "[+ Onboard new tenant]") + { + $TenantId = Read-Host "Enter the new Tenant ID (GUID)" + if(-not $TenantId) + { + Write-Host "No tenant ID provided. Exiting." -ForegroundColor Yellow + exit 0 + } + } + else + { + $TenantId = $selectedTenantDisplay -replace '.*\(([0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12})\)$', '$1' + if(-not $TenantId) + { + $TenantId = $selectedTenantDisplay + } + } +} + +$currentTenant = (Get-SavedTenants -SettingsPath $settingsPath) | Where-Object { $_.TenantId -eq $TenantId } | Select-Object -First 1 +if(-not $currentTenant -or -not $currentTenant.TenantName) +{ + Write-Host "`nResolving tenant name..." -ForegroundColor Cyan + $resolvedName = Resolve-TenantName -TenantId $TenantId -SettingsPath $settingsPath + if($resolvedName) + { + Update-TenantNameCache -SettingsPath $settingsPath -TenantId $TenantId -TenantName $resolvedName + Write-Host "Cached tenant name: $resolvedName" -ForegroundColor Green + $currentTenant = [PSCustomObject]@{ TenantId = $TenantId; TenantName = $resolvedName; Display = "$resolvedName ($TenantId)" } + } +} +#endregion + # Build common parameter hashtable $commonParams = @{ TenantId = $TenantId @@ -119,6 +296,14 @@ while($true) Write-Host "========================================" -ForegroundColor Cyan Write-Host " macOS Intune Toolkit" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan + if($currentTenant -and $currentTenant.TenantName) + { + Write-Host " Tenant: $($currentTenant.TenantName) ($TenantId)" -ForegroundColor Green + } + else + { + Write-Host " Tenant: $TenantId" -ForegroundColor Green + } Write-Host " Press Esc to go back, Space to select" -ForegroundColor DarkGray $selection = Select-MenuItem -Items $menuItems -Header "Select a tool to launch"