AADSTS500011: The resource principal named was not found in the tenant

Scenario: If your receive the following error when using Hybrid Modern Authentication for Exchange OnPremises, run the following scriptlet below. Our problem was a misconfigured URL set on the get-clientaccessserver where it was pointing to a Servername, and not our shared namespace.

Scriptlet:

 Get-MapiVirtualDirectory | FL server,*url*
 Get-WebServicesVirtualDirectory | FL server,*url*
 Get-ClientAccessServer | fl Name, AutodiscoverServiceInternalUri
 Get-OABVirtualDirectory | FL server,*url*
 Get-AutodiscoverVirtualDirectory | FL server,*url*
 Get-OutlookAnywhere | FL server,*url*
Advertisement

Cannot delete a Exchange Database because “This mailbox database contains one or more mailboxes, mailbox plans, archive mailboxes, public folder mailboxes or arbitration mailboxes, Audit mailboxes”

Scenario: When attempting to remove an Exchange database, you receive the following error:

This mailbox database contains one or more mailboxes, mailbox plans, archive mailboxes, public folder mailboxes or
arbitration mailboxes, Audit mailboxes.


Scriptlet: Here is a quick script to check that database for mailbox or mailbox data that may be active on it:

$Db = “DB01”
Get-Mailbox -Database $DB
Get-MailboxPlan
Get-Mailbox -Database $DB -Archive
Get-Mailbox -Database $DB -PublicFolder
Get-Mailbox -Database $DB -Arbitration.
Get-Mailbox -Database $DB -AuditLog
Get-MoveRequest |Where {($_.TargetDatabase -eq $db) -or ($_.SourceDatabase -eq $DB)}



#GoRavens

Checking SCP status during Exchange On-Premise rebuild

Scenario: You are going to build a new Exchange On-Premises server, and you want to monitor the Autodiscover SCP record that is created so you can $null it out BEFORE your customer Outlook email clients start discovering the default server and pulling in the incorrect configuration values for the email clients server settings.

Script: Here is a monitor script that you can use, or build off of, to identify when the SCP record is created and you can go directly into ADSI edit and $null out the ServiceBindingInformation:

Do{
$r = @()
$r += get-adobject “CN=ExServer1,CN=Autodiscover,CN=Protocols,CN=ExServer1,CN=Servers,CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups,CN=Enterprise Exchange,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=domain,DC=com” -Properties * | Select CN, objectclass, ServiceBindingInformation
$r += get-adobject “CN=ExServer2,CN=Autodiscover,CN=Protocols,CN=ExServer2,CN=Servers,CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups,CN=Enterprise Exchange,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=domain,DC=com” -Properties * | Select CN, objectclass, ServiceBindingInformation
$r
Sleep 10



Sleeping 10 Sec

}While($C -ne 1002)

Windows Security – Select a Certificate window opens when connecting to an Exchange IIS Virtual Directory

Scenario: You notice that when you attempt to connect to a Exchange Servers virtual directory, such as https://<my_exchange_namespace>/autodiscover/autodiscover.xml ,
you receive a prompt similar to this:

Select a Certificate
Site <domain name or server name> needs your credentials>
<Certificates listed to select>


In our case, Autodiscover was not working correctly via DNS lookups, but the SCP record was pulling settings just fine.

Cause: Check the SSL Settings on the Virtual Directory in the Internet Information Services (IIS) Manager. Example: Expand Server –> Sites –> Default Web Site –> select Autodiscover (or whatever the virtual directory giving you an issue is). In the IIS area, select SSL Settings and make sure your certificate is setup to Ignore. You may want to go a hierarchical level higher and make sure the SSL settings are set correctly on the Default Web Site.

Selecting specific rows from a CSV file to perform Powershell functions/commands against

Scenario: You have a large CSV file that you need to import and perform specific PowerShell commands against. You need the results in a hurry and you want to split up the CSV so you can run multiple PowerShell sessions at once to pull the results in parallel. Instead of creating separate CSV files to import for each PowerShell session, you can tell PowerShell which rows of the import you want to target.

Code Example:   In each PowerShell you can import the CSV file. When calling the variable for the loop you can specify the rows you want to target.  In this example we are going to set customattribute1 to the string “MigrateME” for the first 1000 (well 1001) entries in the csv file in one PowerShell session.  In a second PowerShell session I would import the code but change [0..1000] to [1001..2000],  and repeat the increment for each additional PowerShell session.

$users = Import-csv C:TempAll_Mailboxes.csv

$users[0..1000] | Select -expandproperty alias | %{ set-mailbox $_ -customattribute1 “MigrateMe”}

Find Exchange ActiveSync Devices via ActiveDirectory PowerShell

Scenario:  If you want to list the mobile devices attached to an AD user and want to do it within the AD toolset, run the following  get-ADObject command.

PowerShell Snippit:

$name = “*steve*”

#To view the Devices:

$AD_EAS = Get-AdObject -filter {ObjectClass -like ‘msExchActiveSyncDevice’} | Where-object {$_.DistinguishedName -like $($name)}

$AD_EAS_Container = Get-ADObject -filter { ObjectClass -like ‘msExchActiveSyncDevices’} | Where-Object {$_.DistinguishedName -like $($name)}

Remove an orphaned MSExchDelegateListBL (autodiscover) entry

Scenario:  A user no longer has fullaccess to a shared mailbox BUT the shared mailbox still attempts to reconnect via Autodiscover in the Outlook profile.

Solution: The following scriptlets will detect the autodiscover links associated with the problem mailbox and attempt to remove them.  Note, you can remove all backlinks, or specific backlinks.

  $u = "Steve"
  $u_DN = Get-ADUser $u | select -ExpandProperty DistinguishedName
  $d = Get-ADUser $u -Properties msExchDelegateListBL |  select msExchDelegateListBL
  
  #To remove all backLinks
  $d.msexchdelegatelistBL | %{Set-ADUser $_ -Remove @{msExchDelegateListLink = "$u_dn"}}
  
  #To Remove specific BackLinks
  $SharedMailboxToRemove
  $d | Where msexchdelegatelistBL -like "*$SharedMailboxToRemove*" | Select -ExpandProperty msexchdelegatelistBL | %{Set-ADUser $_ -Remove @{msExchDelegateListLink = "$u_dn"}}

Exchange EWS applications continuously disconnect and reconnect

Scenario:  Users are reporting that their Mac Mail and Outlook for Mac email clients continuously disconnect and then reconnect making their mail client unreliable and unstable.  EWS is the only mail protocol that is affected, all other protocols are fine.

Troubleshooting:  We noticed the following (the timing for each item found was at the same time or really close together):

Event Viewer: We found the following events in the Application logs that tied together errors with ASP.Net and the crashing/restarting of the  MSExchange Web Services app pool:

  • EventID:  1325   –  Source: ASP.NET 4.0.30319.0 – Application ID: /LM/W3SVC/2/ROOT/EWS Message: Missing signing certificate
  • EventID: 2 – The Exchange Web Services started successfully.

Wireshark: We saw connection Resets (RST) being issued from the server to the client, meaning it was the server that was the cause of disconnecting clients to the server. Wireshark Filter:  (ip.dst==10.1.1.2 or ip.src==10.1.1.2) and tcp.flags.reset ==1

AuthConfig: Troubleshooting the ASP.NET error and the message: missing signing certificate, we realized that the certificate currently being used for server authentication was expired.  (ExPowershell: Get-authconfig)

Solution:  ASP.NET was breaking as a result of the certificate used for AuthConfig. When ASP.NET broke, so did EWS. We created/deployed a new certificate and this fixed our issue.

We created a new certificate:

New-ExchangeCertificate -KeySize 2048 -PrivateKeyExportable $true -SubjectName “cn=Microsoft Exchange Server Auth Certificate” -FriendlyName “Microsoft Exchange Server Auth Certificate” -DomainName “contoso.com”

Then we exported the new cert  and imported to each Ex Server:

Export-ExchangeCertificate -Thumbprint E5AAEBA3DCB406331949D3FB5E108FC7EF3B0B62 -FileName “\ExSrv1C$authcert.pfx” -BinaryEncoded -Password (ConvertTo-SecureString -String ‘password’ -AsPlainText -Force)

$Servers = get-exchangeserver
$servers.name | %{
    “$_”
    Import-ExchangeCertificate -Server $_ -FileName “\ExSrv1C$authcert.pfx” -Password (ConvertTo-SecureString -String ‘password’ -AsPlainText -Force)
}

Next we set the AuthConfig to the new certificate:

Set-AuthConfig -NewCertificateThumbprint E5AAEBA3DCB406331949D3FB5E108FC7EF3B0B62 -NewCertificateEffectiveDate (Get-Date)

Next we Published the Cert:

Set-AuthConfig –PublishCertificate

Since this issue was a result of ASP.NET errors, this made the errors go right away.  I followed up with  Restarting the Web App Pools for the following just in case:

Restart-WebAppPool MSExchangeOWAAppPool
Restart-WebAppPool MSExchangeECPAppPool
Restart-WebAppPool MSexchangeServicesAppPool

 

 

 

 

Spider Permission Script – An alternative script to determine mailbox permissions FASTER than Microsoft’s script

Scenario:   We found that using Microsoft’s spider script (the script that determines all mailbox permissions and delegates found here) was slow and would eat RAM (like Cookie Monster eats cookies) causing our Exchange servers to error out.  So we developed a newer, faster, but more raw version of the spider script.

Script: Edit the global variables and then copy and paste in normal Windows Powershell.  You want the scriptlet pretty and easy to read, copy and paste into PowerShell ISE.  This is not meant to run as a .ps1, we like to see everything….

<#Script Notes:
0. Output of the file will display FullAccess, SendAs, SendOnBehalf, and Calendar Permissions (Reviewer,Editor, ect.)
1. Open a normal Windows Powershell with an account with Exchange Permissions (Run-As)
2. Take a list of all Exchange On-Premises Mailboxes (get-mailbox -resultsize unlimited | Select Alias | export-csv C:tempAll_mbx.csv. All we need is the alias column (keep the header alias), nothing else.
3. This script requires the ActiveDirectory Module
4. In the  New-OnPremExchangeSession it will randomly select one of our Exchange servers to process the remote PowerShell Commands.  After 500 mailboxes, it will randomly select another.
5. If you have to start over, open a brand new normal Windows Powershell with an account with Exchange Permission (Run-As)

End_ScriptNotes #>

#Global Variables############################################################################################
$m = import-csv “C:tempAll_Mbx.csv”   #Import a list of all your Mailboxes.  If you have not done this yet, feel free to run the following command inside a Exchange PowerShell:  get-mailbox -resultsize unlimited | Export-csv C:tempAll_mbx.csv
$outfile = “C:tempAll_Mbx_Spider_Results.csv”  #Final Spider Results Export
$report_Final = @()   #Used to capture all spider rights within the script
$count = 0 #The Count starts the counter for each mailbox processed
$CounterSleep = 500 #This offset countersleep allows the script to sleep after 500 Mailboxes and pickup a new Exchange server to connect to to avoid hardware/resource problems
$ExchangeServers = “ExSrv1.domain.com”,”ExSrv2.domain.com”,”ExSrv3.domain.com”   #Exchange server pool that your Powershell session with connect to after the CounterSleep hits
$domainForUsername = “domain”  #Replace the domain with the domain name used for sign ins.  Example: If you login is domainusername: contososteve   make the value  “contoso”
$dom = $env:userdomain;$usr = $env:username   #Just for fun in the script
$DisplayName = ([adsi]”WinNT://$dom/$usr,user”).fullname #Just for fun in the script
#End_Global Variables############################################################################################

#This is where the MAGIC HAPPENS
#Import Module####################################################################################################
#Required for AD Permissions
Import-Module ActiveDirectory
#End_Import Module#####################################################################################################

#Functions required##################################################################################################################################
#Gets nested group members
function Get-DistributionGroupMemberRecursive ($GroupIdentity) {
$member_list = Get-DistributionGroupMember -Identity $GroupIdentity
foreach ($member in $member_list) {
if ($member.RecipientType -like ‘*Group*’) {
Get-DistributionGroupMemberRecursive -GroupIdentity $member.Identity
} else {
$member
}
}
}
#Connects to Exchange remote Powershell on servers randomly
Function New-OnPremExchangeSession(){
#close any old remote session. We don’t need it. Don’t want it.
Get-PSSession | Remove-PSSession -Confirm:$false

For ($i=60; $i -gt 1; $i–-) {
Write-Progress -Activity “$DisplayName made me fall asleep.” -SecondsRemaining $i
Start-Sleep 1
}

Do{
#get-random number for exchange server
$ex_srv = get-random $ExchangeServers
$ex_ps = “http://”+$ex_srv +”/powershell/”
#start a new remote session
“Attempting to connect to Remote Powershell on esgmtwex$ex_i”
$OnPremsession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $ex_ps -Authentication Kerberos
$OnPrem = Import-PSSession $OnPremSession
#check for session
$opensession = Get-PSSession | Where {($_.Configurationname -eq “Microsoft.Exchange”) -and ($_.State -eq “Opened”)}
}While($opensession -eq $null)
}
#End_Functions##############################################################################################

#Connect to Exchange##############################################################################################################################
New-OnPremExchangeSession
#END_ConnecttoExchange##############################################################################################################################

#Loop Each Mailbox#################################################################################################################################################################
$m.alias | sort | %{
#Define InLoop Variables
$u = $_
#write-it so you can see it.
Write-host “$U – $count/$($m.count – 1)” -ForegroundColor green
$count++
If($count -eq $CounterSleep){
New-OnPremExchangeSession $OnPremCredentials
$CounterSleep = $CounterSleep + 500
“CounterSleep now set to $CounterSleep”
}
[int]$percentComplete = [int](($Count/$($M.count * 100)))

Write-Progress -Activity “Connected to $((Get-PSSession | Where {($_.Configurationname -eq “Microsoft.Exchange”) -and ($_.State -eq “Opened”)}).computername)” -PercentComplete “$percentComplete” -Status (“Processing Mailbox: $($U) – $($Count) of $($m.count – 1 )”)
“————————”
#Check Mbx
$error.clear()
$mbx = get-mailbox $u
If($error[0].exception -like “*The I/O operation has been aborted*”){“I/O Error Operation found, sleeping 3 minutes”;sleep 180; $mbx=get-mailbox $u}
If($mbx -ne $null){

#here we go!!!!!
#Collect SendOnBehalf permissions##############################################################################################
”     Checking SendOnBehalf for $U”
$SendOnBehalf =  $mbx.grantsendonbehalfto
If($SendOnBehalf -ne $null){
$SendOnBehalf | %{
$sob_name = $_
$sob_name = ($sob_name -split ‘/’)[-1]
$obj = new-object psObject
$obj | Add-Member -membertype noteproperty -Name Mbx -Value $u
$obj | Add-Member -membertype noteproperty -Name Delegate -Value $sob_name
$obj | Add-Member -membertype noteproperty -Name AccessRight -Value “SendOnBehalf”
$Report_final += $obj
}
}else{
$obj = new-object psObject
$obj | Add-Member -membertype noteproperty -Name Mbx -Value $u
$obj | Add-Member -membertype noteproperty -Name Delegate -Value “None”
$obj | Add-Member -membertype noteproperty -Name AccessRight -Value “SendOnBehalf”
$Report_final += $obj
}
$SendOnBehalf = $null
#End_Calendar##################################################################################################################

#Collect Calendar permissions##############################################################################################
”     Checking Calendar for $U”
$cal_var = ($mbx.alias).tostring() +”:calendar”
$Calendar_Perm = get-mailboxfolderpermission $cal_Var | Where {($_.User -notlike “*Default*”) -and ($_.user -notlike “*anonymous*”)}
If($Calendar_Perm -ne $Null){
$calendar_Perm | %{
$cal_user_name =  $_.user.adrecipient.name
If($cal_user_name -ne $null){

$cal_user_right = $_ | Select -ExpandProperty AccessRights
#”$Cal_user_name – $Cal_user_right”
$obj = new-object psObject
$obj | Add-Member -membertype noteproperty -Name Mbx -Value $u
$obj | Add-Member -membertype noteproperty -Name Delegate -Value $cal_user_name
$obj | Add-Member -membertype noteproperty -Name AccessRight -Value “Calendar:$cal_user_right”
$Report_final += $obj
}
}
}else{
$obj = new-object psObject
$obj | Add-Member -membertype noteproperty -Name Mbx -Value $u
$obj | Add-Member -membertype noteproperty -Name Delegate -Value None
$obj | Add-Member -membertype noteproperty -Name AccessRight -Value “Calendar”
$Report_final += $obj
}
#Clear FullAccess
$Cal_Var = $null
$Calendar_Perm = $null
$Cal_user_name = $null
$Cal_user_right = $null
#End_Calendar##################################################################################################################

#Collect SendAs permissions##############################################################################################
#This method does not perform a get-adpermission because its slow.
#Why does Microsoft want us to run slow commands when the offer faster commands.
”     Checking Sendas for $U”
$SendAs_Perm = (Get-acl -path “AD:$($mbx.distinguishedname)”).access  |where {($_.ActiveDirectoryRights -like “*ExtendedRight*”) -and ($_.IsInherited -like “*false*”) -and ($_.IdentityReference -like “$domainForUsername*”) -and ($_.ObjectType -eq “ab721a54-1e2f-11d0-9819-00aa0040529b”)}
#$SendAs = $mbx | Get-ADPermission | Where extendedrights -like send-as | Where User -notlike “Nt AuthoritySelf”
If($SendAs_Perm -ne $Null){
$SendAs_users = @()
$Sendas_Perm.IdentityReference.Value |%{
#Format User Name
$object = $_
$object = $object -replace “$domainForUsername\”,””

#ADCheck
$AD_Chk = Get-adobject -filter {samaccountname -eq $object}
#Write-host ”      $($AD_Chk | Select name, objectclass)” -ForegroundColor yellow
#ObjectClass Check based off ADObject $AD_CHK
If($AD_Chk.objectclass -eq “User”){$SendAs_users += $AD_CHK | Select -ExpandProperty Name}
If($AD_Chk.objectclass -eq “Group”){$SendAs_users += Get-DistributionGroupMemberRecursive $($AD_Chk | Select -ExpandProperty Name) | Select -ExpandProperty Name}
$Sendas_users | select -Unique | %{
$delegate = $_

$obj = new-object psObject
$obj | Add-Member -membertype noteproperty -Name Mbx -Value $u
$obj | Add-Member -membertype noteproperty -Name Delegate -Value $delegate
$obj | Add-Member -membertype noteproperty -Name AccessRight -Value “SendAs”
$Report_final += $obj
}
}
}else{
$obj = new-object psObject
$obj | Add-Member -membertype noteproperty -Name Mbx -Value $u
$obj | Add-Member -membertype noteproperty -Name Delegate -Value None
$obj | Add-Member -membertype noteproperty -Name AccessRight -Value “SendAs”
$Report_final += $obj
}
#Clear SendAsVariables
$SendAs_Perm = $null
$Sendas_users = $null
$object = $null
$AD_Chk = $null
$delegate = $null

#End_SendAs##################################################################################################################

#Collect MBX permissions##############################################################################################
”     Checking FullAccess for $U”
$FullAccess_Perm = $mbx | get-mailboxpermission | Where {($_.IsInherited -eq $false) -and ($_.User -notlike “NT Auth*”) -and ($_.Deny -eq $false)}
If($FullAccess_Perm -ne $Null){

$fullAccess_Users = @()
$fullAccess_Perm.user | %{
#$fullAccess_Perm.user.securityidentifier | %{
#Format User Name
$object = $_
$object = $object -replace “$domainForUsername\”,””
#ADCheck
#$AD_Chk = Get-adobject -filter {objectsid -eq $object}
$AD_Chk = Get-adobject -filter {samaccountname -eq $object}
#ObjectClass Check based off ADObject $AD_CHK
If($AD_Chk.objectclass -eq “User”){$FullAccess_users += $AD_CHK | Select -ExpandProperty Name}
If($AD_Chk.objectclass -eq “Group”){$FullAccess_users += Get-DistributionGroupMemberRecursive $($AD_Chk | Select -ExpandProperty Name) | Select -ExpandProperty Name}
$FullAccess_users | select -Unique | %{
$delegate = $_

$obj = new-object psObject
$obj | Add-Member -membertype noteproperty -Name Mbx -Value $u
$obj | Add-Member -membertype noteproperty -Name Delegate -Value $delegate
$obj | Add-Member -membertype noteproperty -Name AccessRight -Value “FullAccess”
$Report_final += $obj
}
}
}else{
$obj = new-object psObject
$obj | Add-Member -membertype noteproperty -Name Mbx -Value $u
$obj | Add-Member -membertype noteproperty -Name Delegate -Value None
$obj | Add-Member -membertype noteproperty -Name AccessRight -Value “FullAccess”
$Report_final += $obj
}

#Clear FullAccess
$FullAccess_Perm = $null
$FullAccess_users = $null
$object = $null
$AD_Chk = $null
$delegate = $null

#End_FullAccess##################################################################################################################

}else{
Write-Host “No Mbx for $u” -ForegroundColor Magenta
$obj = new-object psObject
$obj | Add-Member -membertype noteproperty -Name Mbx -Value $u
$obj | Add-Member -membertype noteproperty -Name Delegate -Value None
$obj | Add-Member -membertype noteproperty -Name AccessRight -Value “No_Mbx_Found”
$Report_final += $obj}

#Clear InLoop Variables.
#Wash, Rinse, Repeat
$u = $null
$mbx = $null
}
#END_Loop Each Mailbox#################################################################################################################################################################

#View the Report##################################################################################################################################################################
#$report_Final
#$report_Final | out-gridview
$Report_Final | export-csv $outfile
#View the Report##################################################################################################################################################################