Files

111 lines
4.9 KiB
PowerShell

# Registration and token helpers for the offline mock tenant provider
# (Classes/AuthenticationMock.ps1). The provider only exists in a session
# started with IM_MOCK_DATA pointing at a data folder - see
# Docs/MockTenant.md and Tools/Start-MockTenant.ps1.
# Delegated scopes stamped into the mock token: every permission a policy type
# declares, so access marking shows the whole menu as usable.
$script:MockTokenScopes = @(
"Agreement.ReadWrite.All", "CloudPC.ReadWrite.All",
"DeviceManagementApps.ReadWrite.All", "DeviceManagementConfiguration.ReadWrite.All",
"DeviceManagementManagedDevices.ReadWrite.All", "DeviceManagementRBAC.ReadWrite.All",
"DeviceManagementScripts.ReadWrite.All", "DeviceManagementServiceConfig.ReadWrite.All",
"Directory.Read.All", "Group.ReadWrite.All", "Organization.ReadWrite.All",
"Policy.Read.All", "Policy.ReadWrite.ConditionalAccess", "User.Read", "User.Read.All",
"openid", "profile", "offline_access"
)
# Intune Administrator role template id: access marking skips the RBAC lookup
# for a token carrying it (Internal/EffectivePermissions.ps1).
$script:MockTokenIntuneAdminRoleId = "3a2c62db-5318-420d-8d74-23affee5d9d5"
# tenant.json merged over defaults, so a data folder only has to say what differs.
function Get-MockTenantProfile {
[CmdletBinding()]
param([Parameter(Mandatory)][string]$Root)
$profile = [ordered]@{
TenantId = "11111111-2222-3333-4444-555555555555"
TenantName = "MyLabTenant"
Domain = "mylabtenant.onmicrosoft.com"
UPN = "admin@mylabtenant.onmicrosoft.com"
DisplayName = "Lab Admin"
UserId = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
AppId = "14d82eec-204b-4c2f-b7e8-296a70dab67e"
AppName = "Microsoft Graph Command Line Tools"
}
$file = Join-Path $Root "tenant.json"
if(Test-Path -LiteralPath $file) {
try {
$data = [IO.File]::ReadAllText($file) | ConvertFrom-Json
foreach($prop in $data.PSObject.Properties) {
if($profile.Contains($prop.Name) -and $null -ne $prop.Value -and "$($prop.Value)" -ne "") { $profile[$prop.Name] = [string]$prop.Value }
}
}
catch { Write-Log "Mock provider: cannot read $file - using defaults ($($_.Exception.Message))" 2 }
}
return [PSCustomObject]$profile
}
function ConvertTo-MockBase64Url {
param([string]$Text)
$bytes = [System.Text.Encoding]::UTF8.GetBytes($Text)
return [Convert]::ToBase64String($bytes).TrimEnd('=').Replace('+', '-').Replace('/', '_')
}
# An unsigned JWT with the claims the product reads (scp, wids, tid, upn, oid,
# name, iat, exp, idtyp). Nothing verifies the signature - the mock never
# leaves the process - so the third segment is a placeholder.
function New-MockAccessToken {
[CmdletBinding()]
param([Parameter(Mandatory)]$Tenant)
$now = [DateTimeOffset]::UtcNow.ToUnixTimeSeconds()
$header = [ordered]@{ typ = "JWT"; alg = "none" }
$payload = [ordered]@{
aud = "https://graph.microsoft.com"
iss = "https://sts.windows.net/$($Tenant.TenantId)/"
iat = $now
nbf = $now
exp = $now + 31536000
app_displayname = $Tenant.AppName
appid = $Tenant.AppId
idtyp = "user"
name = $Tenant.DisplayName
oid = $Tenant.UserId
preferred_username = $Tenant.UPN
scp = ($script:MockTokenScopes -join " ")
tid = $Tenant.TenantId
unique_name = $Tenant.UPN
upn = $Tenant.UPN
ver = "1.0"
wids = @($script:MockTokenIntuneAdminRoleId)
}
$h = ConvertTo-MockBase64Url ($header | ConvertTo-Json -Compress)
$p = ConvertTo-MockBase64Url ($payload | ConvertTo-Json -Compress)
return "$h.$p.mock"
}
function Invoke-MockProviderInitialize {
[CmdletBinding()]
param()
if(-not $env:IM_MOCK_DATA) { return }
if(-not (Get-Command -Name Register-AuthProvider -ErrorAction SilentlyContinue)) { return }
if(-not (Test-Path -LiteralPath $env:IM_MOCK_DATA -PathType Container)) {
Write-Log "IM_MOCK_DATA is set but '$($env:IM_MOCK_DATA)' is not a folder - mock provider not registered" 2
return
}
# A mock session is only ever meant to run on the mock, so make it the
# session's provider unless the launcher already chose one. MSAL registers
# later with -SetActive; the AppInitialized handler applies this variable
# after every provider has registered, which is what makes it stick.
if(-not $env:IM_AUTH_PROVIDER) { $env:IM_AUTH_PROVIDER = "Mock" }
try { Register-AuthProvider -Provider ([AuthenticationMock]::new()) }
catch { Write-LogError "Failed to register the mock tenant provider" $_.Exception }
}
Invoke-MockProviderInitialize