Public/Set-NSPConditionalAccessTenantOption.ps1

function Set-NSPConditionalAccessTenantOption {
    <#
    .SYNOPSIS
        Chooses between alternative policy definitions for a tenant, such as how security-information registration is protected.
    .DESCRIPTION
        Offline; changes only the tenant profile (Options). The next deployment plan includes the
        definitions the options select. A policy this tool already owns for a definition no
        longer selected shows as Deselected; turn it off with a Disabled promotion once its
        replacement is On, so there is no gap.
 
        -Registration:
          - TrustedLocations: NSP-BASE-REG-01. Registration is blocked outside
            trusted locations, unless in the ExternalRegistration group.
          - TapOutsideTrusted (default): NSP-BASE-REG-02. A Temporary Access Pass to register outside
            trusted locations.
          - TapEverywhere: NSP-BASE-REG-03. A Temporary Access Pass to register anywhere, for
            offices without a static IP address. Users who already have MFA need one too, to add
            or change a method.
        TrustedLocations and TapOutsideTrusted also select NSP-BASE-REG-04: at trusted locations,
        registration needs the user's current MFA (someone with no methods yet may still register).
        Both TAP options use the TAP-only authentication strength (one-time or multi-use), which
        the plan creates or binds, and need the Temporary Access Pass method enabled (preflight).
 
        -AdminMfa: Mfa (default, NSP-ADMIN-MFA-01) or PhishingResistant (NSP-ADMIN-MFA-02: a
        security key, Windows Hello, or a passkey). Switch only once every admin has one.
 
        -ServiceAccountLocations: Anywhere (default) or TrustedOnly (NSP-SVC-LOC-01 blocks service
        accounts outside trusted locations; the plan holds it until the tenant has a trusted
        location and the profile has service accounts).
 
        -RiskPolicies: Off (default) or On (NSP-RISK-SIGNIN-01 and NSP-RISK-USER-01; Entra ID P2,
        which the preflight checks).
    .EXAMPLE
        Set-NSPConditionalAccessTenantOption -TenantProfile $profilePath -Registration TapEverywhere
    .EXAMPLE
        Set-NSPConditionalAccessTenantOption -TenantProfile $profilePath -AdminMfa PhishingResistant -RiskPolicies On
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory)][string]$TenantProfile,
        [ValidateSet('TrustedLocations', 'TapOutsideTrusted', 'TapEverywhere')][string]$Registration,
        [ValidateSet('Mfa', 'PhishingResistant')][string]$AdminMfa,
        [ValidateSet('Anywhere', 'TrustedOnly')][string]$ServiceAccountLocations,
        [ValidateSet('Off', 'On')][string]$RiskPolicies
    )

    $content = Get-Content -LiteralPath $TenantProfile -Raw | ConvertFrom-Json
    if (-not $content.PSObject.Properties['Options'] -or -not $content.Options) {
        $content | Add-Member -NotePropertyName Options -NotePropertyValue ([pscustomobject]@{}) -Force
    }
    $table = Get-NSPConditionalAccessOption
    foreach ($name in @($table.Keys)) {
        if ($PSBoundParameters.ContainsKey($name)) { $content.Options | Add-Member -NotePropertyName $name -NotePropertyValue $PSBoundParameters[$name] -Force }
    }
    if ($PSCmdlet.ShouldProcess($TenantProfile, 'Update tenant options')) {
        Save-NSPConditionalAccessJson -InputObject $content -Path $TenantProfile
    }
    $result = [ordered]@{}
    foreach ($name in @($table.Keys | Sort-Object)) {
        $value = if ($content.Options.PSObject.Properties[$name]) { $content.Options.$name } else { $table[$name].Default }
        $result[$name] = $value
    }
    [pscustomobject]$result
}