Archive for July, 2016

How to find all the ADFS servers in your environment and run diagnostics against them

July 1, 2016 Comments off

Hey everyone!

It has been a hot minute since I’ve posted something here huh?! Life has been busy and that’s a good thing ūüôā Hope you all are well too!

I’ve been¬†real busy here at Microsoft, talking to customers and fixing their issues, most of which I should have blogged about, but hind sight is 20/20 and a bunch of other folks beat me to the punch, so on to the matter at hand.

How to find all the ADFS servers in your environment and run diagnostics against them.

I am by no means a PowerShell pro, but practice makes perfect and this is the first part of a script that I’m really proud of that I made since it fixed a real world issue I and many co-workers in Exchange Online land were dealing with.

In the blurb below it will do the following:

  1. Ask for your domain administrator credentials
  2. Grab your logon server from the user that you’re logged on with
  3. Create a session to that logon server (assuming WinRM is enabled on it, if you see a sea of red after this part, do a “WinRM qc” on that server)
  4. Set variable for finding all servers in your environment
  5. Set variable for finding all ADFS servers
  6. Executing variable $adfsservers to output your ADFS servers (excluding your WAP servers since those should be in your DMZ, right?!)

$cred = Get-Credential
$dc = $env:Logonserver -replace "\\", ""
$s = New-PSSession -ComputerName $dc -Credential $cred
Invoke-Command -Session $s {Import-Module ActiveDirectory}
Import-PSSession -Session $s -Module ActiveDirectory -Prefix dc
$services = "adfssrv","MSSQL$MICROSOFT%"
$servers = Get-dcADComputer -LDAPFilter "(&(objectcategory=computer)(OperatingSystem=*server*))"
$value = 1
if ($servers.count -lt "100") {$adfsservers = ForEach-Object {Get-WmiObject Win32_Service -ComputerName $servers.dnshostname -Filter "Name Like 'adfssrv'" -Credential $cred | select-object PSComputerName -ExpandProperty PSComputerName}}`
else {$adfsservers = @()
do {
$input = (Read-Host "Please enter ADFS server #$value (enter if last one)")
if ($input -ne '') {$adfsservers += $input}
until ($input -eq '')}



Ok great! Now that we have this information what else can we do with it? Well we can run the ADFS diagnostics script created by the ADFS team against it.

One problem, we would have to login to each ADFS server individually and run the script. How 90’s… So since we’re messing around in PowerShell, let’s leverage it!

Building on the script above we’re going to add the following:

$services = "adfssrv","MSSQL$MICROSOFT%"
$services | ForEach-Object {Get-WmiObject Win32_Service -ComputerName $servers.dnshostname -Filter "Name Like '$_'" -Credential $cred | Format-Table Name, DisplayName, State, StartMode, StartName, SystemName -auto}
$ips = $adfsservers | foreach {Resolve-DNSName $_ | Select-Object IPAddress -ExpandProperty IPAddress}
$adfssrvs = $adfsservers | ForEach {Get-dcADComputer "$_" | Select-Object DnsHostName -ExpandProperty DnsHostName}
$adfssessions = New-PSSession -ComputerName $adfssrvs -Credential $cred
Start-TranScript c:\temp\ADFS-TESTS.TXT -force
Write-host Number of ADFS Servers: ($adfsservers).count
$f = "c:\temp\ADFSDiagnostics.psm1"
$c = Get-Content $f
icm -Session $adfssessions -ScriptBlock {mkdir c:\temp -force -erroraction silentlycontinue}
icm -Session $adfssessions -ScriptBlock {param($filename,$contents) `
Set-Content -Path $filename -Value $contents} -ArgumentList $f,$c
icm -Session $adfssessions -ScriptBlock {
cd \temp
Import-Module .\ADFSDiagnostics.psm1
Write-Host -foregroundcolor "Green" Running cmdlet Get-AdfsSystemInformation on $env:computername
Write-Host -foregroundcolor "Green" Running cmdlet Get-AdfsServerConfiguration on $env:computername
Write-Host -foregroundcolor "Green" Running cmdlet Test-AdfsServerHealth on $env:computername
Test-AdfsServerHealth | ft Name,Result -AutoSize
Write-Host -foregroundcolor "Green" Running cmdlet Test-AdfsServerHealth showing failures on $env:computername
Test-AdfsServerHealth | where {$_.Result -eq "Fail"} | fl

To give a little bit of explanation of what the blurb above does:

  1. Set variables for the IP addresses of the ADFS servers, variables for the ADFS servers FQDN, variables for creating a PSsession to all ADFS servers at once.
  2. Set variables for the ADFS service and Windows Internal Database service and check their status on the ADFS servers.
  3. Copy the¬†ADFSDiagnostics.psm1 from your local c:\temp to the remote session’s c:\temp
  4. Execute a number of diagnostics on the remote server and output them on the screen.

How to find all the ADFS servers in your environment and run diagnostics against them.

But wait, we have more! There are more tests that we can kick off, we’ll need to run these on the local machine though since it leverages the invoke-webrequest cmdlet which needs Internet Explorer (if IE has never been opened it will error out, just an FYI)

In order to get the next part working I had to make use of Jeremy Jameson awesome hostnames scripts. I crammed all the .ps1 files into a .psm1 and turned them into functions.

Some more explanation on the code below:

  1. We ask for your ADFS endpoint name
  2. We import both .psm1 files
  3. Foreach ADFS server IP address we add it the hosts file one at a time and run code against it and running additional certificate checks.
  4. We do this because there’s no tool out there yet that checks against internal ADFS servers, only external host names via the SSO test on
  5. After the certificate checks, it will check for any services on the ADFS servers marked in an AUTO state that’s currently in a STOPPED state and attempt to start them.

$adfs = Read-Host -Prompt 'Please type in your adfs endpoint hostname (i.e.'
Import-Module .\ADFSDiagnostics.psm1
Import-Module .\Hostnames.psm1
foreach ($ip in $ips)
Add-Hostnames $ip $adfs
Test-AdfsServerToken -federationServer $adfs -appliesTo urn:federation:MicrosoftOnline
Test-AdfsServerToken -federationServer $adfs -appliesTo urn:federation:MicrosoftOnline -credential $cred
$token = [Xml](Test-AdfsServerToken -federationServer $adfs -appliesTo urn:federation:MicrosoftOnline)
$token.Envelope.Body.RequestSecurityTokenResponse.RequestedSecurityToken.Assertion.AttributeStatement.Attribute | ft
Remove-Hostnames $adfs}
Write-Host -foregroundcolor "Green" Starting services marked as AUTO that are now marked as STOPPED
icm -Session $adfssessions -ScriptBlock {get-wmiobject win32_service | where-object {$_.Startmode -eq "auto" -and $_.State -ne "running"}| Start-Service -Verbose}

Get-PSSession | Remove-PSSession

You can download the entire 3 piece script from

Once downloaded place them in your c:\temp folder.
Keep in mind that you need to run PowerShell as an Administrator.
Per the ADFSDiagnostics.psm1 script you will need to have PowerShell v4 on all the ADFS servers prior to running the diagnostics script.
The diagnostics script works with ADFS versions 2.0, 2.1 and 3.0