Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo articolo descrive un problema in cui le funzionalità di Active Directory Federation Services (AD FS), ad esempio Autenticazione del dispositivo e Individuazione OAuth, non funzionano.
Sintomi
È possibile che si verifichi uno dei sintomi seguenti:
Gli endpoint registrati da AD FS vengono persi in modo intermittente.
L'ID evento 180 viene registrato ogni cinque minuti nel registro eventi AD FS/Admin, come indicato di seguito:
Log Name: AD FS/Admin Source: AD FS Event ID: 180 Task Category: None Level: Error Keywords: AD FS Description: An error occurred while upgrading FarmBehaviorLevel 'Max' from Minor Version '0' to Minor Version '3'. Exception details: Object reference not set to an instance of an object.
L'esecuzione del
Get-AdfsGlobalAuthenticationPolicy
cmdlet di PowerShell rivela che non sono impostati metodi di autenticazione client, come illustrato nella riga inferiore dell'output seguente:Get-AdfsGlobalAuthenticationPolicy AdditionalAuthenticationProvider : {AzureMfaAuthentication} DeviceAuthenticationEnabled : True DeviceAuthenticationMethod : All TreatDomainJoinedDevicesAsCompliant : False PrimaryIntranetAuthenticationProvider : {FormsAuthentication, WindowsAuthentication, AzurePrimaryAuthentication, MicrosoftPassportAuthentication} PrimaryExtranetAuthenticationProvider : {FormsAuthentication, AzurePrimaryAuthentication, MicrosoftPassportAuthentication} WindowsIntegratedFallbackEnabled : True ClientAuthenticationMethods : None
Questo problema si verifica in una farm AD FS a cui si applicano le condizioni seguenti:
- Uno o più server AD FS (WS2016) di Windows Server 2016 (WS2016) sono stati aggiunti a una server farm ad FS di Windows Server 2012 R2 (WS2012R2) con kb 4041685 (o versioni mensili o di anteprima successive) installate.
- La server farm è stata aggiornata al livello di comportamento della farm WS2016.
- L'aggiornamento 4088787 KB è stato installato nella farm ad FS WS2016.
Causa
L'installazione dell'aggiornamento del 13 marzo 2018, KB 4088787 in un nodo primario in una farm AD FS il cui FBL è stato generato da 1 (WS2012R2) a 3 (WS2016) può causare la regressione di AD FS e un riordinamento delle righe nel database AD FS. Questo problema lascia il database in uno stato in cui alcuni elementi dati hanno occorrenze duplicate. Questo stato causa errori di avvio del server AD FS e altri errori.
Risoluzione
Per risolvere il problema, seguire questa procedura.
Passaggio 1: Verificare il problema
Determinare se l'endpoint openid-configuration può essere raggiunto eseguendo il comando seguente al prompt dei comandi di PowerShell:
Get-AdfsEndpoint -AddressPath "/adfs/.well-known/openid-configuration"
Se l'endpoint non viene trovato, viene visualizzato l'output seguente che indica che è probabile che il problema esista:
Get-AdfsEndpoint : PS0137: No Endpoint found with Address '/adfs/.well-known/openid-configuration'.
At line:1 char:1
+ Get-AdfsEndpoint -AddressPath "/adfs/.well-known/openid-configuration ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-AdfsEndpoint], ArgumentException
+ FullyQualifiedErrorId : PS0137,Microsoft.IdentityServer.Management.Commands.GetEndpointCommand
Passaggio 2: Salvare lo script trovato alla fine di questo articolo come "KB4088787_Fix.ps1"
Il team di AD FS ha sviluppato uno script di PowerShell che è possibile eseguire in un server AD FS per correggere le impostazioni di configurazione di AD FS nel database associato alla knowledge base 4088787.
Questo script è disponibile alla fine di questo articolo. Salvare lo script come "KB4088787_Fix.ps1" e copiarlo nel nodo primario della farm AD FS.
Passaggio 3: Eseguire il backup dei dati di configurazione di AD FS
Prima di eseguire lo script KB4088787_Fix.ps1, è importante eseguire il backup della configurazione di AD FS. Questa configurazione di AD FS viene archiviata nel Database interno di Windows (WID) o in un database di Microsoft SQL Server.
Se si usa WID per archiviare la configurazione di AD FS, è possibile usare lo strumento di ripristino rapido ADFS (disponibile dall'Area download Microsoft) per eseguire il backup dei dati di configurazione. Se si usa SQL Server per archiviare il database di configurazione di AD FS, è necessario creare un backup aggiuntivo di SQL Server prima di eseguire lo script. Lo stato del database può essere ripristinato da uno di questi backup, se necessario.
Passaggio 4: Eseguire lo script KB4088787_Fix.ps1
In Esplora file fare clic con il pulsante destro del mouse sul file KB4088787_Fix.ps1 appena salvato nel nodo primario della farm AD FS e quindi scegliere Esegui con PowerShell.
Lo script verifica innanzitutto che il database del server AD FS corrente sia danneggiato dal problema di aggiornamento descritto. In tal caso, lo script individua le proprietà interrotte e le corregge. Lo script KB4088787_Fix.ps1 chiederà di confermare le modifiche apportate al database e lo script riavvierà AD FS, se necessario.
Note
Ogni volta che viene eseguito lo script, viene salvata una copia del codice XML delle impostazioni del servizio. I dati vengono salvati nella directory di lavoro nel formato di nome seguente:
serviceSettingsXml_<yyyy>-<MM>-<dd>-<hh>-<mm>-<ss>.xml
Ad esempio, se lo script viene eseguito il 14 aprile 2021 alle 10:14:53, viene salvato come segue:
serviceSettingsXml_2021-04-14-10-14-53.xml
Al termine dello script e si verifica un riavvio di AD FS, è necessario correggere tutti gli errori di autenticazione del dispositivo ed endpoint.
Ulteriori informazioni
Se si applica la correzione dello script e il riavvio del sistema non risolve il problema, passare al sito Web supporto tecnico Microsoft.
Script di PowerShell: KB4088787_Fix.ps1
#
# Version 2.0.0
#
# Helper function - serializes any DataContract object to an XML string
function Get-DataContractSerializedString()
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory = $true, HelpMessage="Any object serializable with the DataContractSerializer")]
[ValidateNotNull()]
$object
)
$serializer = New-Object System.Runtime.Serialization.DataContractSerializer($object.GetType())
$serializedData = $null
try
{
# No simple write to string option, so we have to write to a memory stream
# then read back the bytes...
$stream = New-Object System.IO.MemoryStream
$writer = New-Object System.Xml.XmlTextWriter($stream,[System.Text.Encoding]::UTF8)
$null = $serializer.WriteObject($writer, $object);
$null = $writer.Flush();
# Read back the text we wrote to the memory stream
$reader = New-Object System.IO.StreamReader($stream,[System.Text.Encoding]::UTF8)
$null = $stream.Seek(0, [System.IO.SeekOrigin]::Begin)
$serializedData = $reader.ReadToEnd()
}
finally
{
if ($reader -ne $null)
{
try
{
$reader.Dispose()
}
catch [System.ObjectDisposedException] { }
}
if ($writer -ne $null)
{
try
{
$writer.Dispose()
}
catch [System.ObjectDisposedException] { }
}
if ($stream -ne $null)
{
try
{
$stream.Dispose()
}
catch [System.ObjectDisposedException] { }
}
}
return $serializedData
}
function Write-XmlIndent
{
param
(
$xmlData
)
$strWriter = New-Object System.IO.StringWriter
$xmlWriter = New-Object System.XMl.XmlTextWriter $strWriter
# Default = None, change Formatting to Indented
$xmlWriter.Formatting = "indented"
# Gets or sets how many IndentChars to write for each level in
# the hierarchy when Formatting is set to Formatting.Indented
$xmlWriter.Indentation = 1
$xmlData.WriteContentTo($xmlWriter)
$xmlWriter.Flush()
$strWriter.Flush()
$strWriter.ToString()
}
function Get-ADFSXMLServiceSettings
{
param
(
$saveData
)
$doc = new-object Xml
$doc.Load("$env:windir\ADFS\Microsoft.IdentityServer.Servicehost.exe.config")
$connString = $doc.configuration.'microsoft.identityServer.service'.policystore.connectionString
$cli = new-object System.Data.SqlClient.SqlConnection
$cli.ConnectionString = $connString
$cli.Open()
try
{
$cmd = new-object System.Data.SqlClient.SqlCommand
$cmd.CommandText = "Select ServiceSettingsData from [IdentityServerPolicy].[ServiceSettings]"
$cmd.Connection = $cli
$configString = $cmd.ExecuteScalar()
$configXml = new-object XML
$configXml.LoadXml($configString)
if($saveData)
{
$script:originalPath = "original_serviceSettingsXml_$(get-date -f yyyy-MM-dd-hh-mm-ss).xml"
Write-XmlIndent($configXml) | Out-File $script:originalPath
Write-Host "Original XML saved to: $script:originalPath"
}
write-output $configXml
}
finally
{
$cli.CLose()
}
}
# Gets internal ADFS settings by extracting them Get-AdfsProperties
function Get-AdfsInternalSettings()
{
$settings = Get-AdfsProperties
$settingsType = $settings.GetType()
$propInfo = $settingsType.GetProperty("ServiceSettingsData", [System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic)
$internalSettings = $propInfo.GetValue($settings, $null)
return $internalSettings
}
function Set-AdfsInternalSettings()
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory = $true, HelpMessage="Settings object fetched from Get-AdfsInternalSettings")]
[ValidateNotNull()]
$InternalSettings
)
$settingsData = Get-DataContractSerializedString -object $InternalSettings
$doc = new-object Xml
$doc.Load("$env:windir\ADFS\Microsoft.IdentityServer.Servicehost.exe.config")
$connString = $doc.configuration.'microsoft.identityServer.service'.policystore.connectionString
$cli = new-object System.Data.SqlClient.SqlConnection
$cli.ConnectionString = $connString
$cli.Open()
try
{
$cmd = new-object System.Data.SqlClient.SqlCommand
$cmd.CommandText = "update [IdentityServerPolicy].[ServiceSettings] SET ServiceSettingsData=@content,[ServiceSettingsVersion] = [ServiceSettingsVersion] + 1,[LastUpdateTime] = GETDATE()"
$cmd.Parameters.AddWithValue("@content", $settingsData) | out-null
$cmd.Connection = $cli
$rowsAffected = $cmd.ExecuteNonQuery()
# Update service state table for WID sync if required
if ($connString -match "##wid")
{
$cmd = new-object System.Data.SqlClient.SqlCommand
$cmd.CommandText = "UPDATE [IdentityServerPolicy].[ServiceStateSummary] SET [SerialNumber] = [SerialNumber] + 1,[LastUpdateTime] = GETDATE() WHERE ServiceObjectType='ServiceSettings'"
$cmd.Connection = $cli
$widRowsAffected = $cmd.ExecuteNonQuery()
}
}
finally
{
$cli.CLose()
}
}
function Create-EndpointConfiguration()
{
Param
(
[ValidateNotNull()]
$xmlData
)
# EndpointConfiguration
$enabled = Create-BoolFromString($xmlData.Enabled)
$proxy = Create-BoolFromString($xmlData.Proxy)
$canProxy = Create-BoolFromString($xmlData.CanProxy)
$endpointConfig = New-Object -TypeName Microsoft.IdentityServer.PolicyModel.Configuration.EndpointConfiguration -ArgumentList $xmlData.Address, $enabled , ([Microsoft.IdentityServer.PolicyModel.Configuration.EndpointMode] $xmlData.ModeValue), $proxy, $xmlData.Version, $canProxy
return $endpointConfig
}
function Create-ClientSecretSettings()
{
Param
(
[ValidateNotNull()]
$xmlData
)
# ClientSecretSettings
$clientSecretSettings = New-Object -TypeName Microsoft.IdentityServer.PolicyModel.Client.ClientSecretSettings
$clientSecretSettings.ClientSecretRolloverTimeMinutes = $xmlData.ClientSecretRolloverTimeMinutes
$clientSecretSettings.ClientSecretLockoutThreshold = $xmlData.ClientSecretLockoutThreshold;
$clientSecretSettings.SaltedHashAlgorithm = $xmlData.SaltedHashAlgorithm
$clientSecretSettings.SaltSize = $xmlData.SaltSize
$clientSecretSettings.SecretSize = $xmlData.SecretSize
return $clientSecretSettings
}
function Create-IdTokenIssuer()
{
Param
(
[ValidateNotNull()]
$xmlData
)
#IdTokenIssuer
$idTokenIssuerConfig = New-Object -TypeName Microsoft.IdentityServer.PolicyModel.Configuration.IdTokenIssuerConfiguration
$idTokenIssuerConfig.Address = $xmlData.Address
return $idTokenIssuerConfig
}
function Create-CertificateAuthorityConfiguration()
{
Param
(
[ValidateNotNull()]
$xmlData
)
# CertificateAuthorityConfiguration
$certAuthorityConfig = New-Object -TypeName Microsoft.IdentityServer.PolicyModel.Configuration.CertificateAuthorityConfiguration
$certAuthorityConfig.Mode.Value = [Microsoft.IdentityServer.PolicyModel.Configuration.CertificateAuthorityMode] $xmlData.ModeValue
$certAuthorityConfig.GenerationThresholdInMinutes = $xmlData.GenerationThresholdInMinutes
$certAuthorityConfig.PromotionThresholdInMinutes = $xmlData.PromotionThresholdInMinutes
$certAuthorityConfig.CertificateLifetimeInMinutes = $xmlData.CertificateLifetimeInMinutes
$certAuthorityConfig.RolloverIntervalInMinutes = $xmlData.RolloverIntervalInMinutes
$certAuthorityConfig.CriticalThresholdInMinutes = $xmlData.CriticalThresholdInMinutes
# Create Cert reference
if ($xmlData.PrimaryIssuerCertificate.IsEmpty -ne $true)
{
$certReference = New-Object -TypeName Microsoft.IdentityServer.PolicyModel.Configuration.CertificateReference
$certReference.IsChainIncluded = Create-BoolFromString($xmlData.PrimaryIssuerCertificate.IsChainIncluded)
$certReference.IsChainIncludedSpecified = Create-BoolFromString($xmlData.PrimaryIssuerCertificate.IsChainIncludedSpecified)
$certReference.FindValue = $xmlData.PrimaryIssuerCertificate.FindValue
$certReference.RawCertificate = $xmlData.PrimaryIssuerCertificate.RawCertificate
$certReference.EncryptedPfx = $xmlData.PrimaryIssuerCertificate.EncryptedPfx
$certReference.StoreName.Value = [System.Security.Cryptography.X509Certificates.StoreName] $xmlData.PrimaryIssuerCertificate.StoreNameValue
$certReference.StoreLocation.Value = [System.Security.Cryptography.X509Certificates.StoreLocation] $xmlData.PrimaryIssuerCertificate.StoreLocationValue
$certReference.X509FindType.Value = [System.Security.Cryptography.X509Certificates.X509FindType] $xmlData.PrimaryIssuerCertificate.X509FindTypeValue
$certAuthorityConfig.PrimaryIssuerCertificate = $certReference
}
if ($xmlData.QueuedIssuerCertificate.IsEmpty -ne $true){
# Create PromotionCert
$promotionCert = New-Object -TypeName Microsoft.IdentityServer.PolicyModel.Configuration.PromotionCertificate
$promotionCert.ObjectId = $xmlData.QueuedIssuerCertificate.ObjectId
$certAuthorityConfig.QueuedIssuerCertificate = $promotionCert
}
$certAuthorityConfig.CriticalThresholdInMinutes = $xmlData.CriticalThresholdInMinutes
if ($xmlData.CertificateAuthority.IsEmpty -ne $true){
$certAuthorityConfig.CertificateAuthority = $xmlData.CertificateAuthority
}
if ($xmlData.EnrollmentAgentCertificateTemplateName.IsEmpty -ne $true)
{
$certAuthorityConfig.EnrollmentAgentCertificateTemplateName = $xmlData.EnrollmentAgentCertificateTemplateName
}
if ($xmlData.LogonCertificateTemplateName.IsEmpty -ne $true)
{
$certAuthorityConfig.LogonCertificateTemplateName = $xmlData.LogonCertificateTemplateName
}
if ($xmlData.VPNCertificateTemplateName.IsEmpty -ne $true)
{
$certAuthorityConfig.VPNCertificateTemplateName = $xmlData.VPNCertificateTemplateName
}
if ($xmlData.WindowsHelloCertificateTemplateName.IsEmpty -ne $true)
{
$certAuthorityConfig.WindowsHelloCertificateTemplateName = $xmlData.WindowsHelloCertificateTemplateName
}
$certAuthorityConfig.AutoEnrollEnabled = Create-BoolFromString($xmlData.AutoEnrollEnabled)
$certAuthorityConfig.WindowsHelloCertificateProxyEnabled = Create-BoolFromString($xmlData.WindowsHelloCertificateProxyEnabled)
return $certAuthorityConfig
}
function Create-OAuthClientAuthenticationMethods()
{
Param
(
[ValidateNotNull()]
$xmlData
)
# OAuthClientAuthenticationMethods
return 15
}
function Create-BoolFromString()
{
Param
(
[ValidateNotNull()]
$xmlData
)
if ($xmlData -eq $null -or $xmlData.ToLower() -eq "false")
{
return 0
}else{
return 1
}
}
function Get-ObjectFromElement()
{
Param
(
[Parameter(Mandatory = $true, HelpMessage="Settings object fetched from Get-AdfsInternalSettings")]
[ValidateNotNull()]
$xmlData,
[Parameter(Mandatory = $true, HelpMessage="Settings object fetched from Get-AdfsInternalSettings")]
[ValidateNotNull()]
$elementName
)
$endpointConfigs = "DeviceRegistrationEndpoint", "OAuthJwksEndpoint", "OAuthDiscoveryEndpoint", "WebFingerEndpoint", "CertificateAuthorityCrlEndpoint", "UserInfoEndpoint"
# Microsoft.IdentityServer.PolicyModel.Configuration.EndpointConfiguration
$clientSecretSettings = "ClientSecretSettings"
# Microsoft.IdentityServer.PolicyModel.Client.ClientSecretSettings
$oauthClientAuthMethod = "OAuthClientAuthenticationMethods"
# Microsoft.IdentityServer.PolicyModel.Configuration.ClientAuthenticationMethod
$certAuthorityConfig = "CertificateAuthorityConfiguration"
# Microsoft.IdentityServer.PolicyModel.Configuration.CertificateAuthorityConfiguration
$idTokenIssuer = "IdTokenIssuer"
# Microsoft.IdentityServer.PolicyModel.Configuration.IdTokenIssuerConfiguration
$boolObjs = "EnableIdPInitiatedSignonPage", "IgnoreTokenBinding", "EnableOauthLogout"
$basicObjs = "DeviceUsageWindowInSeconds", "MaxLdapUserNameLength", "FarmBehaviorMinorVersion", "PromptLoginFederation", "PromptLoginFallbackAuthenticationType"
if ($endpointConfigs.Contains($elementName))
{
return Create-EndpointConfiguration($xmlData)
}elseif ($clientSecretSettings.Contains($elementName))
{
return Create-ClientSecretSettings($xmlData)
}elseif ($oauthClientAuthMethod.Contains($elementName))
{
return Create-OAuthClientAuthenticationMethods($xmlData)
}elseif ($certAuthorityConfig.Contains($elementName))
{
return Create-CertificateAuthorityConfiguration($xmlData)
}elseif ($idTokenIssuer.Contains($elementName))
{
return Create-IdTokenIssuer($xmlData)
}elseif ($boolObjs.Contains($elementName))
{
return Create-BoolFromString($xmlData)
}else{
return $xmlData
}
}
$role = (Get-AdfsSyncProperties).Role
if($role -ne "PrimaryComputer")
{
Write-Host "This script must execute on the primary node in the AD FS farm. Cannot continue."
exit
}
Add-Type -Path ('C:\\Windows\\ADFS\\Microsoft.IdentityServer.dll')
$script:originalPath = $null
# Get the XML of the Service Settings blob, and look for duplicate elements
$xmlData = Get-ADFSXMLServiceSettings($true)
$dataObj = Get-AdfsInternalSettings
if($dataObj.SecurityTokenService.DeviceRegistrationEndpoint.Length -ne 1)
{
if(($xmlData.ServiceSettingsData.SecurityTokenService | Select-Object "DeviceRegistrationEndpoint").DeviceRegistrationEndpoint.IsEmpty[0] -ne $True)
{
# In this case, the service settings object is showing an issue, but the XML data is not.
# This is possible in the case that the sequence of KB applications has occurred, but no Service Settings write oparation
# has occured.
# To handle this, we will prompt the user to allow us to throttle a Service Setting to force a write operation
# Do a no-op service settings action so that the duplicates are populated in the database (if issue exists)
$message = "Confirmation required"
$question = "To ensure data detection is possible, we need to perform an AD FS Properties operation. `nIf you continue, this script will add 1 minute to the value of 'ProxyTrustTokenLifetime', and then the value of 'ProxyTrustTokenLifetime' will be returned to its original setting. `nIf you wish to make a Set-AdfsProperties operation yourself, answer 'No', and perform the operation yourself. `n`nAre you sure you want to proceed?"
$choices = New-Object Collections.ObjectModel.Collection[Management.Automation.Host.ChoiceDescription]
$choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes'))
$choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&No'))
$decision = $Host.UI.PromptForChoice($message, $question, $choices, 1)
if ($decision -eq 0) {
$prop = Get-AdfsProperties
$original = $prop.ProxyTrustTokenLifetime
Set-AdfsProperties -ProxyTrustTokenLifetime ($original + 1)
Set-AdfsProperties -ProxyTrustTokenLifetime $original
# Refresh the XML and data obj
$xmlData = Get-ADFSXMLServiceSettings($false)
$dataObj = Get-AdfsInternalSettings
}else{
Write-Host "We did not perform a service settings operation. Please make some service settings change by performing a Set-AdfsProperties command, and try the script again."
}
}
}
if(($xmlData.ServiceSettingsData.SecurityTokenService | Select-Object "DeviceRegistrationEndpoint").DeviceRegistrationEndpoint.IsEmpty[0] -eq $True)
{
$possibleDuplicateElements = "DeviceRegistrationEndpoint", "DeviceUsageWindowInSeconds", "OAuthClientAuthenticationMethods", "MaxLdapUserNameLength", "EnableIdPInitiatedSignonPage", "ClientSecretSettings", "OAuthDiscoveryEndpoint", "OAuthJwksEndpoint", "IdTokenIssuer", "CertificateAuthorityConfiguration", "WebFingerEndpoint", "CertificateAuthorityCrlEndpoint", "UserInfoEndpoint", "IgnoreTokenBinding", "FarmBehaviorMinorVersion", "EnableOauthLogout", "PromptLoginFederation", "PromptLoginFallbackAuthenticationType"
$existingDups = @()
foreach( $dup in $possibleDuplicateElements )
{
$object = $xmlData.ServiceSettingsData.SecurityTokenService | Select-Object $dup
if( $object.$dup.Count -gt 1 )
{
# We have an element with duplicate values
# Take the last one in the list
$newObj = $object.$dup[$object.$dup.Count - 1]
$savableObj = Get-ObjectFromElement -xmlData $newObj -elementName $dup
$existingDups += $dup
$dataObj.SecurityTokenService.$dup = $savableObj
}
}
# Write the modified Service Settings data object back to the database
if($existingDups.Count -gt 0)
{
$filename = "modified_serviceSettingsXml_$(get-date -f yyyy-MM-dd-hh-mm-ss).xml"
$modifiedData = Get-DataContractSerializedString -object $dataObj
Write-XmlIndent([xml]$modifiedData) | Out-File $filename
Write-Host "Modifed XML saved to: $filename"
$message = "Confirmation required"
$question = "We have located duplicate data in Service Settings, and need to make a modification to the configuration database. `nIf you continue, the values of some elements will be updated in your database. `nIf you wish to see the difference, you can compare the following two files from the working directory: `n`n$script:originalPath `n$filename `n`nAre you sure you want to proceed?"
$choices = New-Object Collections.ObjectModel.Collection[Management.Automation.Host.ChoiceDescription]
$choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes'))
$choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&No'))
$decision = $Host.UI.PromptForChoice($message, $question, $choices, 1)
if ($decision -eq 0) {
Write-Host "Performing update to Service Settings"
Set-AdfsInternalSettings -InternalSettings $dataObj
Write-Host "Updated Service Settings`n`n"
Write-Host "The following elements in the service settings data were modified:`n"
foreach($d in $existingDups)
{
Write-Host $d
}
Write-Host "`nAll nodes in this farm should be restarted. This script will attempt to restart the current node, but no other nodes."
Write-Host "Please manually restart all nodes in your AD FS farm.`n`n"
$message = "Confirmation required"
$question = "An AD FS Service restart is required. Proceed with restart?"
$choices = New-Object Collections.ObjectModel.Collection[Management.Automation.Host.ChoiceDescription]
$choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes'))
$choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&No'))
$decision2 = $Host.UI.PromptForChoice($message, $question, $choices, 1)
if($decision2 -eq 0){
Write-Host "Stopping AD FS"
net stop adfssrv
Write-Host "Starting AD FS"
net start adfssrv
}else{
Write-Host "You chose not to restart AD FS. Please manually restart AD FS to allow the changes to take effect."
}
} else {
Write-Host "Cancelling"
}
}else{
Write-Host "No Operations Needed"
}
}else
{
Write-Host "No issues detected. Terminating script."
}