Examples/ca-matrix.psd1
|
@{ # A Conditional Access scenario matrix, expanded by Expand-CaScenario into every # combination of persona, resource and condition. # # $matrix = Import-PowerShellDataFile .\ca-matrix.psd1 # Expand-CaScenario -Matrix $matrix | Invoke-CaScenarioMatrix # # Held as data rather than code on purpose. It can be reviewed and extended by someone who # does not write PowerShell, it diffs cleanly next to the baseline it produces, and it is # the same artefact whether it is driving an ad hoc check or a nightly run. # # Every axis multiplies. Three personas by two resources by five conditions is thirty API # calls, which is why Expand-CaScenario refuses to expand past MaxScenarioCount rather than # quietly running a shorter matrix than the one you wrote. # One row per shape of user you actually care about, not one per user. The interesting # failures live in populations - the contractor, the service desk, the break glass account - # not in individuals. Personas = @( @{ Name = 'standard'; UserId = '00000000-0000-0000-0000-000000000001' } @{ Name = 'admin'; UserId = '00000000-0000-0000-0000-000000000002' } # The account that has to work when everything else has stopped. A policy tightened # without its emergency access exclusion is discovered during the incident it was # supposed to survive, which is the worst possible moment to find out. @{ Name = 'breakglass'; UserId = '00000000-0000-0000-0000-000000000003' } ) # Exactly one of ApplicationId, UserAction or AuthenticationContext per resource - they map # to three different signInContext types and a resource asking for two describes no request # that can be sent. Resources = @( @{ Name = 'office365'; ApplicationId = '00000003-0000-0ff1-ce00-000000000000' } # Registering security information is the user action that most often turns out to be # blocked by a policy nobody meant to point at it, stranding a user who cannot enrol # the very factor the policy is demanding. @{ Name = 'register-mfa'; UserAction = 'registerSecurityInformation' } ) # PascalCase here, camelCase on the wire - Expand-CaScenario lowercases the first letter. # Any documented signInConditions property works, and so does one Microsoft adds later. Conditions = @( @{ Name = 'managed-windows' DevicePlatform = 'windows'; ClientAppType = 'browser' SignInRiskLevel = 'low'; UserRiskLevel = 'low'; Country = 'US' DeviceInfo = @{ isCompliant = $true; trustType = 'azureAD' } } # The row that most often produces a finding. A report-only policy requiring a compliant # device applies to this sign-in exactly as it does to the managed one, and the API # reports it as applying either way - so without the device state in the request it # reads as a mild extra requirement rather than as the lockout it is. @{ Name = 'unmanaged-windows' DevicePlatform = 'windows'; ClientAppType = 'browser' SignInRiskLevel = 'low'; UserRiskLevel = 'low'; Country = 'US' DeviceInfo = @{ isCompliant = $false } } @{ Name = 'unmanaged-ios' DevicePlatform = 'iOS'; ClientAppType = 'browser' SignInRiskLevel = 'low'; UserRiskLevel = 'low'; Country = 'US' DeviceInfo = @{ isCompliant = $false } } # Legacy authentication, which should be blocked outright. Worth asserting rather than # assuming: the block is usually there, and usually has an exclusion nobody remembers. @{ Name = 'legacy-auth' DevicePlatform = 'windows'; ClientAppType = 'exchangeActiveSync' SignInRiskLevel = 'low'; UserRiskLevel = 'low'; Country = 'US' DeviceInfo = @{ isCompliant = $false } } @{ Name = 'high-risk-foreign' DevicePlatform = 'windows'; ClientAppType = 'browser' SignInRiskLevel = 'high'; UserRiskLevel = 'high'; Country = 'DE' DeviceInfo = @{ isCompliant = $false } } # Device code flow, which cannot pass device state to the device doing the # authentication - so any policy requiring a compliant or hybrid joined device is # unsatisfiable here no matter how well managed the device is. Note the deliberately # compliant, hybrid joined device below: the flow overrides it. @{ Name = 'device-code-flow' DevicePlatform = 'windows'; ClientAppType = 'mobileAppsAndDesktopClients' SignInRiskLevel = 'low'; UserRiskLevel = 'low'; Country = 'US' AuthenticationFlow = @{ transferMethod = 'deviceCodeFlow' } DeviceInfo = @{ isCompliant = $true; trustType = 'serverAD' } } ) } |