federation.psm1
|
<# Copyright (c) 2026 One Identity LLC. All rights reserved. #> # Helpers Import-Module -Name "$PSScriptRoot\sslhandling.psm1" -Scope Local # Well-known SAML authentication context class that tells the external STS to # accept any authentication method. Setting an external federation provider to # this value resolves Entra ID error AADSTS75011, which occurs when a user # authenticates passwordless (Windows Hello / passkey / FIDO2) but Safeguard's # default request only accepts Password / PasswordProtectedTransport. $script:UnspecifiedAuthnContextClass = "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified" function Resolve-SafeguardExternalFederationIdentityProviderId { [CmdletBinding()] [OutputType([int])] Param( [Parameter(Mandatory=$false)] [string]$Appliance, [Parameter(Mandatory=$false)] [object]$AccessToken, [Parameter(Mandatory=$false)] [switch]$Insecure, [Parameter(Mandatory=$true,Position=0)] [object]$Provider ) if (-not $PSBoundParameters.ContainsKey("ErrorAction")) { $ErrorActionPreference = "Stop" } if (-not $PSBoundParameters.ContainsKey("Verbose")) { $VerbosePreference = $PSCmdlet.GetVariableValue("VerbosePreference") } if ($Provider.Id -as [int]) { $Provider = $Provider.Id } if ($Provider -as [int]) { # Verify the ID actually refers to an external federation provider $local:Idp = (Invoke-SafeguardMethod -AccessToken $AccessToken -Appliance $Appliance -Insecure:$Insecure Core GET "IdentityProviders/$($Provider -as [int])") if ($local:Idp.TypeReferenceName -ne "ExternalFederation") { throw "Identity provider '$Provider' is of type '$($local:Idp.TypeReferenceName)', not ExternalFederation" } $local:Idp.Id } else { $local:EscapedName = $Provider -replace "'", "\'" $local:Idps = @(Invoke-SafeguardMethod -AccessToken $AccessToken -Appliance $Appliance -Insecure:$Insecure Core GET "IdentityProviders" ` -Parameters @{ filter = "Name ieq '$($local:EscapedName)'" }) # Constrain client-side to external federation to be robust across appliance versions $local:Idps = @($local:Idps | Where-Object { $_.TypeReferenceName -eq "ExternalFederation" }) if (-not $local:Idps) { throw "Unable to find external federation identity provider matching '$Provider'" } if ($local:Idps.Count -ne 1) { throw "Found $($local:Idps.Count) external federation identity providers matching '$Provider'" } $local:Idps[0].Id } } <# .SYNOPSIS Get external federation identity providers configured in Safeguard via the Web API. .DESCRIPTION Get the SAML external federation identity providers that have been configured in Safeguard. These are used to authenticate users against an external SAML 2.0 security token service such as Microsoft Entra ID. .PARAMETER Appliance IP address or hostname of a Safeguard appliance. .PARAMETER AccessToken A string containing the bearer token to be used with Safeguard Web API. .PARAMETER Insecure Ignore verification of Safeguard appliance SSL certificate. .PARAMETER ProviderToGet An integer containing an ID or a string containing the name of the external federation identity provider to return. .PARAMETER Fields An array of the identity provider property names to return. .INPUTS None. .OUTPUTS JSON response from Safeguard Web API. .EXAMPLE Get-SafeguardExternalFederationIdentityProvider .EXAMPLE Get-SafeguardExternalFederationIdentityProvider "Entra ID" #> function Get-SafeguardExternalFederationIdentityProvider { [OutputType([object[]])] [CmdletBinding()] Param( [Parameter(Mandatory=$false)] [string]$Appliance, [Parameter(Mandatory=$false)] [object]$AccessToken, [Parameter(Mandatory=$false)] [switch]$Insecure, [Parameter(Mandatory=$false,Position=0)] [object]$ProviderToGet, [Parameter(Mandatory=$false)] [string[]]$Fields ) if (-not $PSBoundParameters.ContainsKey("ErrorAction")) { $ErrorActionPreference = "Stop" } if (-not $PSBoundParameters.ContainsKey("Verbose")) { $VerbosePreference = $PSCmdlet.GetVariableValue("VerbosePreference") } $local:Parameters = @{} if ($Fields) { $local:Parameters["fields"] = ($Fields -join ",") } if ($PSBoundParameters.ContainsKey("ProviderToGet")) { $local:Id = (Resolve-SafeguardExternalFederationIdentityProviderId -AccessToken $AccessToken -Appliance $Appliance -Insecure:$Insecure $ProviderToGet) Invoke-SafeguardMethod -AccessToken $AccessToken -Appliance $Appliance -Insecure:$Insecure Core GET "IdentityProviders/$($local:Id)" ` -Parameters $local:Parameters } else { $local:RemoveType = $Fields -and $Fields -notcontains "TypeReferenceName" if ($local:RemoveType) { # The type is needed for filtering even when it is not requested in the output. $local:Parameters["fields"] = (($Fields + "TypeReferenceName") -join ",") } # Server-side filter is not relied upon for the type; filter client-side for robustness $local:Idps = @(Invoke-SafeguardMethod -AccessToken $AccessToken -Appliance $Appliance -Insecure:$Insecure Core GET "IdentityProviders" ` -Parameters $local:Parameters) $local:Idps | Where-Object { $_.TypeReferenceName -eq "ExternalFederation" } | ForEach-Object { if ($local:RemoveType) { $_.PSObject.Properties.Remove("TypeReferenceName") } $_ } } } <# .SYNOPSIS Create a new SAML external federation identity provider in Safeguard via the Web API. .DESCRIPTION Create a new external federation identity provider that authenticates users against an external SAML 2.0 security token service such as Microsoft Entra ID. The provider is configured from the external STS's SAML metadata, supplied either as an HTTPS URL that Safeguard monitors for changes, a local metadata file, or a raw metadata XML string. .PARAMETER Appliance IP address or hostname of a Safeguard appliance. .PARAMETER AccessToken A string containing the bearer token to be used with Safeguard Web API. .PARAMETER Insecure Ignore verification of Safeguard appliance SSL certificate. .PARAMETER Name A string containing the name for this external federation identity provider. .PARAMETER Description A string containing a description for this external federation identity provider. .PARAMETER MetadataUrl An HTTPS URL to the external STS SAML metadata. Safeguard periodically monitors this URL and downloads updates automatically. .PARAMETER MetadataFile A path to a local file containing the external STS SAML metadata XML. .PARAMETER MetadataXml A string containing the external STS SAML metadata XML. .PARAMETER NameIdFormat A string containing the SAML NameID format the external STS will return, for example urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress. .PARAMETER Realm A string containing the realm (email domain suffix) used to route users to this provider, for example secureidx.com. This property is required by Safeguard. .PARAMETER AuthnContextClasses A string containing the SAML authentication context class(es) Safeguard will request from the external STS. Set this to urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified to allow passwordless / passkey / FIDO2 sign-in and resolve Entra ID error AADSTS75011. .PARAMETER AuthnContextComparison The comparison method used with AuthnContextClasses. One of Exact, Minimum, Maximum, or Better. .PARAMETER RequireAuthentication Whether the external STS must force re-authentication (SAML ForceAuthn). .PARAMETER ApplicationIdOverride A string overriding the application/entity ID Safeguard presents to the external STS. .INPUTS None. .OUTPUTS JSON response from Safeguard Web API. .EXAMPLE New-SafeguardExternalFederationIdentityProvider "Entra ID" -Realm secureidx.com -MetadataUrl "https://login.microsoftonline.com/<tenant>/federationmetadata/2007-06/federationmetadata.xml?appid=<appid>" .EXAMPLE New-SafeguardExternalFederationIdentityProvider "Entra ID" -Realm secureidx.com -MetadataFile .\entra-metadata.xml -AuthnContextClasses "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified" #> function New-SafeguardExternalFederationIdentityProvider { [CmdletBinding(DefaultParameterSetName="Url")] Param( [Parameter(Mandatory=$false)] [string]$Appliance, [Parameter(Mandatory=$false)] [object]$AccessToken, [Parameter(Mandatory=$false)] [switch]$Insecure, [Parameter(Mandatory=$true,Position=0)] [string]$Name, [Parameter(Mandatory=$false)] [string]$Description, [Parameter(ParameterSetName="Url",Mandatory=$true)] [string]$MetadataUrl, [Parameter(ParameterSetName="File",Mandatory=$true)] [string]$MetadataFile, [Parameter(ParameterSetName="Xml",Mandatory=$true)] [string]$MetadataXml, [Parameter(Mandatory=$true)] [string]$Realm, [Parameter(Mandatory=$false)] [string]$NameIdFormat, [Parameter(Mandatory=$false)] [string]$AuthnContextClasses, [Parameter(Mandatory=$false)] [ValidateSet("Exact","Minimum","Maximum","Better",IgnoreCase=$true)] [string]$AuthnContextComparison, [Parameter(Mandatory=$false)] [switch]$RequireAuthentication, [Parameter(Mandatory=$false)] [string]$ApplicationIdOverride ) if (-not $PSBoundParameters.ContainsKey("ErrorAction")) { $ErrorActionPreference = "Stop" } if (-not $PSBoundParameters.ContainsKey("Verbose")) { $VerbosePreference = $PSCmdlet.GetVariableValue("VerbosePreference") } switch ($PSCmdlet.ParameterSetName) { "Url" { $local:Metadata = $MetadataUrl } "File" { if (-not (Test-Path -LiteralPath $MetadataFile)) { throw "Metadata file '$MetadataFile' does not exist" } $local:Metadata = (Get-Content -LiteralPath $MetadataFile -Raw) } "Xml" { $local:Metadata = $MetadataXml } } $local:Fed = @{ FederationMetadata = $local:Metadata } if ($PSBoundParameters.ContainsKey("NameIdFormat")) { $local:Fed.NameIDFormat = $NameIdFormat } if ($PSBoundParameters.ContainsKey("Realm")) { $local:Fed.Realm = $Realm } if ($PSBoundParameters.ContainsKey("AuthnContextClasses")) { $local:Fed.AuthnContextClasses = $AuthnContextClasses } if ($PSBoundParameters.ContainsKey("AuthnContextComparison")) { $local:Fed.AuthnContextComparison = $AuthnContextComparison } if ($PSBoundParameters.ContainsKey("RequireAuthentication")) { $local:Fed.RequireAuthentication = [bool]$RequireAuthentication } if ($PSBoundParameters.ContainsKey("ApplicationIdOverride")) { $local:Fed.ApplicationIdOverride = $ApplicationIdOverride } $local:Body = @{ TypeReferenceName = "ExternalFederation"; Name = $Name; ExternalFederationProperties = $local:Fed } if ($PSBoundParameters.ContainsKey("Description")) { $local:Body.Description = $Description } Invoke-SafeguardMethod -AccessToken $AccessToken -Appliance $Appliance -Insecure:$Insecure Core POST "IdentityProviders" -Body $local:Body } <# .SYNOPSIS Edit an existing SAML external federation identity provider in Safeguard via the Web API. .DESCRIPTION Edit an existing external federation identity provider. Only the supplied properties are changed; all others are preserved. This is the cmdlet used to apply the AADSTS75011 fix by setting -AuthnContextClasses to urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified so that passwordless / passkey / FIDO2 sign-in is accepted. .PARAMETER Appliance IP address or hostname of a Safeguard appliance. .PARAMETER AccessToken A string containing the bearer token to be used with Safeguard Web API. .PARAMETER Insecure Ignore verification of Safeguard appliance SSL certificate. .PARAMETER ProviderToEdit An integer containing an ID or a string containing the name of the external federation identity provider to edit. .PARAMETER Name A string containing a new name for this external federation identity provider. .PARAMETER Description A string containing a new description for this external federation identity provider. .PARAMETER MetadataUrl An HTTPS URL to the external STS SAML metadata that Safeguard monitors for changes. .PARAMETER MetadataFile A path to a local file containing the external STS SAML metadata XML. .PARAMETER MetadataXml A string containing the external STS SAML metadata XML. .PARAMETER NameIdFormat A string containing the SAML NameID format the external STS will return. .PARAMETER Realm A string containing the realm (email domain suffix) used to route users to this provider. .PARAMETER AuthnContextClasses A string containing the SAML authentication context class(es) Safeguard will request. Set to urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified to allow passwordless / passkey / FIDO2 sign-in (resolves Entra ID error AADSTS75011). .PARAMETER AuthnContextComparison The comparison method used with AuthnContextClasses. One of Exact, Minimum, Maximum, or Better. .PARAMETER RequireAuthentication Whether the external STS must force re-authentication (SAML ForceAuthn). .PARAMETER ApplicationIdOverride A string overriding the application/entity ID Safeguard presents to the external STS. .PARAMETER ProviderObject An object containing the existing external federation identity provider with desired properties set. .INPUTS Object representing an external federation identity provider. .OUTPUTS JSON response from Safeguard Web API. .EXAMPLE Edit-SafeguardExternalFederationIdentityProvider "Entra ID" -AuthnContextClasses "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified" .EXAMPLE Edit-SafeguardExternalFederationIdentityProvider -ProviderObject $obj #> function Edit-SafeguardExternalFederationIdentityProvider { [CmdletBinding(DefaultParameterSetName="Attributes")] Param( [Parameter(Mandatory=$false)] [string]$Appliance, [Parameter(Mandatory=$false)] [object]$AccessToken, [Parameter(Mandatory=$false)] [switch]$Insecure, [Parameter(ParameterSetName="Attributes",Mandatory=$true,Position=0)] [object]$ProviderToEdit, [Parameter(ParameterSetName="Attributes",Mandatory=$false)] [string]$Name, [Parameter(ParameterSetName="Attributes",Mandatory=$false)] [string]$Description, [Parameter(ParameterSetName="Attributes",Mandatory=$false)] [string]$MetadataUrl, [Parameter(ParameterSetName="Attributes",Mandatory=$false)] [string]$MetadataFile, [Parameter(ParameterSetName="Attributes",Mandatory=$false)] [string]$MetadataXml, [Parameter(ParameterSetName="Attributes",Mandatory=$false)] [string]$NameIdFormat, [Parameter(ParameterSetName="Attributes",Mandatory=$false)] [string]$Realm, [Parameter(ParameterSetName="Attributes",Mandatory=$false)] [string]$AuthnContextClasses, [Parameter(ParameterSetName="Attributes",Mandatory=$false)] [ValidateSet("Exact","Minimum","Maximum","Better",IgnoreCase=$true)] [string]$AuthnContextComparison, [Parameter(ParameterSetName="Attributes",Mandatory=$false)] [switch]$RequireAuthentication, [Parameter(ParameterSetName="Attributes",Mandatory=$false)] [string]$ApplicationIdOverride, [Parameter(ParameterSetName="Object",Mandatory=$true,ValueFromPipeline=$true)] [object]$ProviderObject ) begin { if (-not $PSBoundParameters.ContainsKey("ErrorAction")) { $ErrorActionPreference = "Stop" } if (-not $PSBoundParameters.ContainsKey("Verbose")) { $VerbosePreference = $PSCmdlet.GetVariableValue("VerbosePreference") } } process { if ($PSCmdlet.ParameterSetName -eq "Object") { if (-not $ProviderObject) { throw "ProviderObject must not be null" } $local:EditObject = $ProviderObject $local:Id = (Resolve-SafeguardExternalFederationIdentityProviderId -AccessToken $AccessToken -Appliance $Appliance -Insecure:$Insecure $ProviderObject) } else { # Only one metadata source may be supplied at a time $local:MetadataSources = @("MetadataUrl","MetadataFile","MetadataXml" | Where-Object { $PSBoundParameters.ContainsKey($_) }) if ($local:MetadataSources.Count -gt 1) { throw "Specify only one of -MetadataUrl, -MetadataFile, or -MetadataXml" } $local:Id = (Resolve-SafeguardExternalFederationIdentityProviderId -AccessToken $AccessToken -Appliance $Appliance -Insecure:$Insecure $ProviderToEdit) $local:EditObject = (Invoke-SafeguardMethod -AccessToken $AccessToken -Appliance $Appliance -Insecure:$Insecure Core GET "IdentityProviders/$($local:Id)") if (-not $local:EditObject.ExternalFederationProperties) { $local:EditObject | Add-Member -NotePropertyName ExternalFederationProperties -NotePropertyValue ([PSCustomObject]@{}) -Force } $local:Fed = $local:EditObject.ExternalFederationProperties if ($PSBoundParameters.ContainsKey("Name")) { $local:EditObject.Name = $Name } if ($PSBoundParameters.ContainsKey("Description")) { $local:EditObject | Add-Member -NotePropertyName Description -NotePropertyValue $Description -Force } if ($PSBoundParameters.ContainsKey("MetadataUrl")) { $local:Fed | Add-Member -NotePropertyName FederationMetadata -NotePropertyValue $MetadataUrl -Force } if ($PSBoundParameters.ContainsKey("MetadataFile")) { if (-not (Test-Path -LiteralPath $MetadataFile)) { throw "Metadata file '$MetadataFile' does not exist" } $local:Fed | Add-Member -NotePropertyName FederationMetadata -NotePropertyValue (Get-Content -LiteralPath $MetadataFile -Raw) -Force } if ($PSBoundParameters.ContainsKey("MetadataXml")) { $local:Fed | Add-Member -NotePropertyName FederationMetadata -NotePropertyValue $MetadataXml -Force } if ($PSBoundParameters.ContainsKey("NameIdFormat")) { $local:Fed | Add-Member -NotePropertyName NameIDFormat -NotePropertyValue $NameIdFormat -Force } if ($PSBoundParameters.ContainsKey("Realm")) { $local:Fed | Add-Member -NotePropertyName Realm -NotePropertyValue $Realm -Force } if ($PSBoundParameters.ContainsKey("AuthnContextClasses")) { $local:Fed | Add-Member -NotePropertyName AuthnContextClasses -NotePropertyValue $AuthnContextClasses -Force } if ($PSBoundParameters.ContainsKey("AuthnContextComparison")) { $local:Fed | Add-Member -NotePropertyName AuthnContextComparison -NotePropertyValue $AuthnContextComparison -Force } if ($PSBoundParameters.ContainsKey("RequireAuthentication")) { $local:Fed | Add-Member -NotePropertyName RequireAuthentication -NotePropertyValue ([bool]$RequireAuthentication) -Force } if ($PSBoundParameters.ContainsKey("ApplicationIdOverride")) { $local:Fed | Add-Member -NotePropertyName ApplicationIdOverride -NotePropertyValue $ApplicationIdOverride -Force } } Invoke-SafeguardMethod -AccessToken $AccessToken -Appliance $Appliance -Insecure:$Insecure Core PUT "IdentityProviders/$($local:Id)" -Body $local:EditObject } } <# .SYNOPSIS Remove a SAML external federation identity provider from Safeguard via the Web API. .DESCRIPTION Delete an existing external federation identity provider. .PARAMETER Appliance IP address or hostname of a Safeguard appliance. .PARAMETER AccessToken A string containing the bearer token to be used with Safeguard Web API. .PARAMETER Insecure Ignore verification of Safeguard appliance SSL certificate. .PARAMETER ProviderToDelete An integer containing an ID or a string containing the name of the external federation identity provider to delete. .INPUTS None. .OUTPUTS JSON response from Safeguard Web API. .EXAMPLE Remove-SafeguardExternalFederationIdentityProvider "Entra ID" #> function Remove-SafeguardExternalFederationIdentityProvider { [CmdletBinding()] Param( [Parameter(Mandatory=$false)] [string]$Appliance, [Parameter(Mandatory=$false)] [object]$AccessToken, [Parameter(Mandatory=$false)] [switch]$Insecure, [Parameter(Mandatory=$true,Position=0)] [object]$ProviderToDelete ) if (-not $PSBoundParameters.ContainsKey("ErrorAction")) { $ErrorActionPreference = "Stop" } if (-not $PSBoundParameters.ContainsKey("Verbose")) { $VerbosePreference = $PSCmdlet.GetVariableValue("VerbosePreference") } $local:Id = (Resolve-SafeguardExternalFederationIdentityProviderId -AccessToken $AccessToken -Appliance $Appliance -Insecure:$Insecure $ProviderToDelete) Invoke-SafeguardMethod -AccessToken $AccessToken -Appliance $Appliance -Insecure:$Insecure Core DELETE "IdentityProviders/$($local:Id)" } <# .SYNOPSIS Force a refresh of an external federation provider's SAML metadata via the Web API. .DESCRIPTION When an external federation provider is configured with an HTTPS metadata URL, Safeguard periodically downloads it to check for updates. This cmdlet triggers an immediate refresh, for example after rotating the external STS's signing certificate. The refresh is also propagated to other nodes in a cluster. .PARAMETER Appliance IP address or hostname of a Safeguard appliance. .PARAMETER AccessToken A string containing the bearer token to be used with Safeguard Web API. .PARAMETER Insecure Ignore verification of Safeguard appliance SSL certificate. .PARAMETER ProviderToSync An integer containing an ID or a string containing the name of the external federation identity provider to refresh. .INPUTS None. .OUTPUTS JSON response from Safeguard Web API. .EXAMPLE Sync-SafeguardExternalFederationIdentityProvider "Entra ID" #> function Sync-SafeguardExternalFederationIdentityProvider { [CmdletBinding()] Param( [Parameter(Mandatory=$false)] [string]$Appliance, [Parameter(Mandatory=$false)] [object]$AccessToken, [Parameter(Mandatory=$false)] [switch]$Insecure, [Parameter(Mandatory=$true,Position=0)] [object]$ProviderToSync ) if (-not $PSBoundParameters.ContainsKey("ErrorAction")) { $ErrorActionPreference = "Stop" } if (-not $PSBoundParameters.ContainsKey("Verbose")) { $VerbosePreference = $PSCmdlet.GetVariableValue("VerbosePreference") } $local:Id = (Resolve-SafeguardExternalFederationIdentityProviderId -AccessToken $AccessToken -Appliance $Appliance -Insecure:$Insecure $ProviderToSync) Invoke-SafeguardMethod -AccessToken $AccessToken -Appliance $Appliance -Insecure:$Insecure Core POST "IdentityProviders/$($local:Id)/UpdateFederationMetadataFromUrl" } <# .SYNOPSIS Get Safeguard's SAML service provider metadata via the RSTS. .DESCRIPTION Safeguard's embedded security token service (RSTS) publishes SAML service provider metadata that you supply to an external SAML identity provider (such as Microsoft Entra ID) when configuring external federation. This cmdlet retrieves that metadata anonymously from the appliance. By default it returns the parsed service provider properties (entity ID, assertion consumer service URLs, etc.). Use -OutFile to instead save the raw metadata XML to a file. The value you give -OutFile controls the destination: - -OutFile . -> a default-named file in the current directory - -OutFile <existing folder> -> a default-named file in that folder - -OutFile <file path> -> written to exactly that path The default file name is <appliance>-SamlServiceProviderMetadata.xml. .PARAMETER Appliance IP address or hostname of a Safeguard appliance. Falls back to the current session appliance when omitted. .PARAMETER Insecure Ignore verification of Safeguard appliance SSL certificate. .PARAMETER OutFile Save the raw metadata XML to a file instead of returning parsed properties. If the value is an existing directory (including "." for the current directory) a default-named file is written into it; otherwise it is treated as the target file path. .INPUTS None. .OUTPUTS Parsed service provider properties, or a System.IO.FileInfo when -OutFile is used. .EXAMPLE Get-SafeguardSamlMetadata spp1.dan.test -Insecure .EXAMPLE Get-SafeguardSamlMetadata spp1.dan.test -Insecure -OutFile . .EXAMPLE Get-SafeguardSamlMetadata spp1.dan.test -Insecure -OutFile C:\temp .EXAMPLE Get-SafeguardSamlMetadata spp1.dan.test -Insecure -OutFile .\entra-sp-metadata.xml #> function Get-SafeguardSamlMetadata { [CmdletBinding(DefaultParameterSetName="Properties")] [OutputType([PSCustomObject],[System.IO.FileInfo])] Param( [Parameter(Mandatory=$false,Position=0)] [string]$Appliance, [Parameter(Mandatory=$false)] [switch]$Insecure, [Parameter(ParameterSetName="File",Mandatory=$true,Position=1)] [string]$OutFile ) if (-not $PSBoundParameters.ContainsKey("ErrorAction")) { $ErrorActionPreference = "Stop" } if (-not $PSBoundParameters.ContainsKey("Verbose")) { $VerbosePreference = $PSCmdlet.GetVariableValue("VerbosePreference") } if (-not $Appliance -and $SafeguardSession) { $Appliance = $SafeguardSession["Appliance"] if (-not $PSBoundParameters.ContainsKey("Insecure")) { $Insecure = $SafeguardSession["Insecure"] } } if (-not $Appliance) { $Appliance = (Read-Host "Appliance") } $local:Url = "https://$Appliance/RSTS/Saml2FedMetadata" try { if ($Insecure) { Disable-SslVerification } $local:WebArgs = @{ Uri = $local:Url; Method = "GET"; UseBasicParsing = $true } foreach ($local:Pref in (Get-SafeguardSslPreferences).GetEnumerator()) { # Keys are qualified (Invoke-WebRequest:SkipCertificateCheck); strip the prefix $local:WebArgs[($local:Pref.Key -split ":")[-1]] = $local:Pref.Value } $local:Response = (Invoke-WebRequest @local:WebArgs) if ($local:Response.Content -is [byte[]]) { $local:Xml = [System.Text.Encoding]::UTF8.GetString($local:Response.Content) } else { $local:Xml = $local:Response.Content } # Strip a byte-order mark if present so [xml] parsing does not choke $local:Xml = $local:Xml.TrimStart([char]0xFEFF) } finally { if ($Insecure) { Enable-SslVerification } } if ($PSCmdlet.ParameterSetName -eq "File") { $local:DefaultName = "$Appliance-SamlServiceProviderMetadata.xml" $local:Target = $OutFile # A trailing separator or an existing folder means "put the default-named file in here" $local:LooksLikeDir = $local:Target.EndsWith("\") -or $local:Target.EndsWith("/") -or ` (Test-Path -LiteralPath $local:Target -PathType Container) if (-not [System.IO.Path]::IsPathRooted($local:Target)) { $local:Target = Join-Path (Get-Location).Path $local:Target } if ($local:LooksLikeDir) { $local:FullPath = Join-Path $local:Target $local:DefaultName } else { $local:FullPath = $local:Target } # Make sure the destination directory exists so the file lands where requested $local:DestDir = [System.IO.Path]::GetDirectoryName($local:FullPath) if ($local:DestDir -and -not (Test-Path -LiteralPath $local:DestDir -PathType Container)) { New-Item -ItemType Directory -Path $local:DestDir -Force | Out-Null } # Write UTF-8 without BOM $local:Utf8NoBom = New-Object System.Text.UTF8Encoding($false) [System.IO.File]::WriteAllText($local:FullPath, $local:Xml, $local:Utf8NoBom) Get-Item -LiteralPath $local:FullPath return } [xml]$local:MetadataDoc = $local:Xml $local:Ed = $local:MetadataDoc.EntityDescriptor $local:Sp = $local:Ed.SPSSODescriptor $local:Acs = @($local:Sp.AssertionConsumerService | ForEach-Object { [PSCustomObject]@{ Index = $_.index IsDefault = $_.isDefault Binding = $_.Binding Location = $_.Location } }) $local:Slo = @($local:Sp.SingleLogoutService | ForEach-Object { [PSCustomObject]@{ Binding = $_.Binding Location = $_.Location } }) [PSCustomObject]@{ EntityId = $local:Ed.entityID AssertionConsumerServices = $local:Acs SingleLogoutServices = $local:Slo NameIdFormats = @($local:Sp.NameIDFormat) AuthnRequestsSigned = $local:Sp.AuthnRequestsSigned WantAssertionsSigned = $local:Sp.WantAssertionsSigned MetadataUrl = $local:Url RawMetadata = $local:Xml } } |