Add Azure user roaming and reproducible Laboratorio wallpaper policy
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
$repositoryRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
|
||||
$bicepPath = Join-Path $repositoryRoot 'infra\azure\main.bicep'
|
||||
$deploymentPath = Join-Path $repositoryRoot 'scripts\Deploy-SguAzureInfrastructure.ps1'
|
||||
$configurationPath = Join-Path $repositoryRoot 'scripts\Enable-SguAzureUserRoaming.ps1'
|
||||
$installerPath = Join-Path $repositoryRoot 'scripts\Install-SguFsLogix.ps1'
|
||||
$clientBootstrapPath = Join-Path $repositoryRoot 'scripts\Invoke-SguClientBootstrap.ps1'
|
||||
$azureLauncherPath = Join-Path $repositoryRoot 'scripts\Start-SguAzureClientEnrollment.cmd'
|
||||
$packagePath = Join-Path $repositoryRoot 'scripts\New-SguBootstrapPackages.ps1'
|
||||
|
||||
foreach ($scriptPath in @(
|
||||
$deploymentPath,
|
||||
$configurationPath,
|
||||
$installerPath,
|
||||
$clientBootstrapPath,
|
||||
$packagePath)) {
|
||||
$tokens = $null
|
||||
$parseErrors = $null
|
||||
[Management.Automation.Language.Parser]::ParseFile(
|
||||
$scriptPath,
|
||||
[ref]$tokens,
|
||||
[ref]$parseErrors) | Out-Null
|
||||
if ($parseErrors.Count -gt 0) {
|
||||
throw "$scriptPath contains PowerShell parser errors: $($parseErrors -join '; ')"
|
||||
}
|
||||
}
|
||||
|
||||
$configurationTokens = $null
|
||||
$configurationParseErrors = $null
|
||||
$configurationAst = [Management.Automation.Language.Parser]::ParseFile(
|
||||
$configurationPath,
|
||||
[ref]$configurationTokens,
|
||||
[ref]$configurationParseErrors)
|
||||
$samFunction = $configurationAst.Find({
|
||||
param($node)
|
||||
$node -is [Management.Automation.Language.FunctionDefinitionAst] -and
|
||||
$node.Name -eq 'Get-SguStorageSamAccountName'
|
||||
}, $true)
|
||||
Invoke-Expression $samFunction.Extent.Text
|
||||
|
||||
Describe 'SGU Azure user-roaming infrastructure' {
|
||||
It 'deploys dedicated private Azure Files resources by default' {
|
||||
$source = Get-Content -LiteralPath $bicepPath -Raw
|
||||
$source | Should Match 'param deployUserRoaming bool = true'
|
||||
$source | Should Match "purpose: 'SGU-user-roaming'"
|
||||
$source | Should Match "publicNetworkAccess: 'Disabled'"
|
||||
$source | Should Match "privateLinkServiceId: userRoamingStorageAccount.id"
|
||||
$source | Should Match "'file'"
|
||||
$source | Should Match "privatelink\.file\.\$\{storageEndpointSuffix\}"
|
||||
$source | Should Match 'dhcpOptions:'
|
||||
$source | Should Match 'dnsServers:'
|
||||
$source | Should Match 'domainControllerPrivateIp'
|
||||
$source | Should Match 'fsLogixProfilesShare'
|
||||
$source | Should Match 'redirectedFoldersShare'
|
||||
}
|
||||
|
||||
It 'does not repurpose the temporary bootstrap staging account' {
|
||||
(Get-Content -LiteralPath $bicepPath -Raw) | Should Not Match 'sgustage|SGU-bootstrap-staging'
|
||||
}
|
||||
|
||||
It 'requires a private P2S route when roaming is enabled' {
|
||||
$source = Get-Content -LiteralPath $deploymentPath -Raw
|
||||
$source | Should Match '\$DeployUserRoaming -and -not \$DeployVpnGateway'
|
||||
$source | Should Match 'private Azure Files endpoint'
|
||||
}
|
||||
|
||||
It 'returns every post-domain setup value from the Azure deployment' {
|
||||
$source = Get-Content -LiteralPath $deploymentPath -Raw
|
||||
foreach ($name in @(
|
||||
'UserRoamingEnabled',
|
||||
'UserRoamingStorageAccountName',
|
||||
'FsLogixProfilesSharePath',
|
||||
'RedirectedFoldersSharePath',
|
||||
'UserRoamingSetupArguments')) {
|
||||
$source | Should Match $name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'SGU role-specific roaming policies' {
|
||||
It 'uses an AD computer identity with AES-256 Kerberos' {
|
||||
$source = Get-Content -LiteralPath $configurationPath -Raw
|
||||
$source | Should Match "DomainAccountType = 'ComputerAccount'"
|
||||
$source | Should Match 'KerberosEncryptionType AES256'
|
||||
$source | Should Match 'PasswordNeverExpires \$true'
|
||||
$source | Should Match 'StorageFileDataSmbShareContributor'
|
||||
}
|
||||
|
||||
It 'isolates per-user directories with CREATOR OWNER ACLs' {
|
||||
$source = Get-Content -LiteralPath $configurationPath -Raw
|
||||
$source | Should Match "SecurityIdentifier\]::new\('S-1-3-0'\)"
|
||||
$source | Should Match 'PropagationFlags\]::InheritOnly'
|
||||
$source | Should Match 'SetAccessRuleProtection\(\$true, \$false\)'
|
||||
}
|
||||
|
||||
It 'redirects only the student Desktop and Documents folders' {
|
||||
$source = Get-Content -LiteralPath $configurationPath -Raw
|
||||
$source | Should Match "ValueName 'Desktop'"
|
||||
$source | Should Match "ValueName 'Personal'"
|
||||
$source | Should Match '%USERNAME%\\Desktop'
|
||||
$source | Should Match '%USERNAME%\\Documents'
|
||||
$source | Should Match "ValueName 'DisableFRAdminPin'"
|
||||
}
|
||||
|
||||
It 'enables FSLogix only through the AD and DO group SIDs' {
|
||||
$source = Get-Content -LiteralPath $configurationPath -Raw
|
||||
$source | Should Match "\$fsLogixRoot = 'HKLM\\SOFTWARE\\FSLogix\\Profiles'"
|
||||
$source | Should Match '\\ObjectSpecific\\\$\(\$staffGroup\.SID\.Value\)'
|
||||
$source | Should Match '\$professorGroup, \$administrativeGroup'
|
||||
$source | Should Match "ValueName 'Enabled' -Type DWord -Value 0"
|
||||
$source | Should Match 'VHDLocations = @\{ Type = ''String''; Value = \$profilesSharePath \}'
|
||||
}
|
||||
|
||||
It 'does not delete existing staff profiles unless explicitly requested' {
|
||||
$source = Get-Content -LiteralPath $configurationPath -Raw
|
||||
$source | Should Match '\[switch\]\$DeleteExistingStaffLocalProfiles'
|
||||
$source | Should Match 'if \(\$DeleteExistingStaffLocalProfiles\) \{ 1 \} else \{ 0 \}'
|
||||
}
|
||||
|
||||
It 'derives valid deterministic AD names for long storage account names' {
|
||||
$name = Get-SguStorageSamAccountName -StorageName 'abcdefghijklmnopqrstuvwx'
|
||||
$name.Length | Should Be 20
|
||||
$name | Should Match '^sgufs[0-9a-f]{15}$'
|
||||
(Get-SguStorageSamAccountName -StorageName 'abcdefghijklmnopqrstuvwx') | Should Be $name
|
||||
(Get-SguStorageSamAccountName -StorageName 'sguroam1234567890123') |
|
||||
Should Be 'sguroam1234567890123'
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'SGU FSLogix image enrollment' {
|
||||
It 'verifies the Microsoft signature and installs unattended' {
|
||||
$source = Get-Content -LiteralPath $installerPath -Raw
|
||||
$source | Should Match 'Get-AuthenticodeSignature'
|
||||
$source | Should Match 'CN=Microsoft Corporation'
|
||||
foreach ($argument in @('/install', '/quiet', '/norestart')) {
|
||||
$source | Should Match ([regex]::Escape($argument))
|
||||
}
|
||||
$source | Should Match "Get-Service -Name frxsvc"
|
||||
}
|
||||
|
||||
It 'exposes the optional installer through the unified Azure launcher' {
|
||||
((Get-Command $clientBootstrapPath).Parameters.Keys -contains
|
||||
'FsLogixInstallerPath') | Should Be $true
|
||||
$launcher = Get-Content -LiteralPath $azureLauncherPath -Raw
|
||||
$launcher | Should Match 'SGU_FSLOGIX_INSTALLER=%~5'
|
||||
$launcher | Should Match '-FsLogixInstallerPath'
|
||||
}
|
||||
|
||||
It 'packages both roaming setup scripts' {
|
||||
$source = Get-Content -LiteralPath $packagePath -Raw
|
||||
$source | Should Match "'Install-SguFsLogix\.ps1'"
|
||||
$source | Should Match "'Enable-SguAzureUserRoaming\.ps1'"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user