Alan's sysadmin Blog

Working smarter not harder

Archive for the ‘Exchange 2010’ Category

Script: Checking for Expired Certificates in Exchange

Posted by Alan McBurney on August 27, 2014

I was working with a customer that had unintentionally let their Exchange certificates expire.

This resulted in a bit of a headache for the team as users were now getting certificate warnings and mobility services were down until the certificate was replaced.

I decided to put together a script that will check and warn about expired or soon to expire certificates.
The script gets the certificates which have services bound to them on all Exchange 2010 client access and hub transport servers.
It checks for certificates that have expired or that will expire within the next 60 days and optionally emails the report and creates a schedule task.
An email will only be generated if expired\expiring certificates have been detected


<#
.SYNOPSIS
Detects expired certificates on Exchange 2010 Client Access & Hub Transport servers
 
.Author
Alan.McBurney
 
THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE
RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
 
Version 1.0, August 27th, 2014
 
.DESCRIPTION
This script will get the certificates which have services bound to them on all Exchange 2010
client access and hub transport servers.
It checks the expiration for any certificates that are due to expire within 60 days and optionally
emails the report and creates a schedule task
An email will only be generated if expired\expiring certificates have been detected
 
.REFERENCES
Parameters, checks and scheduled tasks stolen from Steve Goodman's Exchange Environmental Reports script
 
http://gallery.technet.microsoft.com/exchange/Generate-Exchange-2388e7c9
 
.Notes
To Do list: Enable Autnetication for SMTP
Support for Exchange 2007 & 2013
 
.PARAMETER SendMail
Send Mail after completion. Set to $True to enable. If enabled, -MailFrom, -MailTo, -MailServer are mandatory
 
.PARAMETER MailFrom
Email address to send from. Passed directly to Send-MailMessage as -From
 
.PARAMETER MailTo
Email address to send to. Passed directly to Send-MailMessage as -To
 
.PARAMETER MailServer
SMTP Mail server to attempt to send through. Passed directly to Send-MailMessage as -SmtpServer
 
.PARAMETER ScheduleAs
Attempt to schedule the command just executed weekly. Specify the username here, schtasks (under the hood) will ask for a password later.
 
.EXAMPLE
Get-ExpiringEx2K10Certs
#>
 
param(
[parameter(Position=1,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Send Mail ($True/$False)')][bool]$SendMail=$false,
[parameter(Position=2,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Mail From')][string]$MailFrom,
[parameter(Position=3,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Mail To')]$MailTo,
[parameter(Position=4,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Mail Server')][string]$MailServer,
[parameter(Position=5,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Schedule as user')][string]$ScheduleAs
)
 
#Check Powershell Version
if ((Get-Host).Version.Major -eq 1)
{
  throw "Powershell Version 1 not supported";
}
 
#Check Exchange Management Shell, attempt to load
if (!(Get-Command Get-ExchangeServer -ErrorAction SilentlyContinue))
{
  if (Test-Path "C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1")
  {
    .'C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1'
    Connect-ExchangeServer -auto
  } elseif (Test-Path "C:\Program Files\Microsoft\Exchange Server\bin\Exchange.ps1") {
    Add-PSSnapIn Microsoft.Exchange.Management.PowerShell.Admin
    .'C:\Program Files\Microsoft\Exchange Server\bin\Exchange.ps1'
    } else {
    throw "Exchange Management Shell cannot be loaded"
  }
}
 
# Check if -SendMail parameter set and if so check -MailFrom, -MailTo and -MailServer are set
if ($SendMail)
{
  if (!$MailFrom -or !$MailTo -or !$MailServer)
  {
    throw "If -SendMail specified, you must also specify -MailFrom, -MailTo and -MailServer"
  }
}
 
$Path=Get-Location
$Dir=$Path.ToString()
$HTMLReport = $Dir + "\ExpiredCerts.html"
$CASServers = Get-ExchangeServer | Where-Object {$_.AdminDisplayVersion -match "Version 14" -and $_.ServerRole -match [regex] 'Hub|Client'}
$Certs = Foreach ($srv in $CASServers) {Get-ExchangeCertificate -Server $srv| Where-Object {$_.NotAfter -le (Get-Date).AddDays(60) -and $_.Services -ne "None"} | Select @{n="Server";e={$srv.name}}, @{n="Expiry Date";e={$_.NotAfter}}, Thumbprint, Services, Issuer, Subject}
$Certs | ConvertTo-Html | Out-File $HTMLReport
 

if ($SendMail)
{
  if ($Certs.count -gt 0)
  { 
    Send-MailMessage -Attachments $HTMLReport -To $MailTo -From $MailFrom -Subject "Warning - Expired Exchange Certificates Detected" -Body "Expired or soon to be expired certificates have been detected on Exchange Servers. Please see attached file for certificates affected" -SmtpServer $MailServer
  }
}
 
if ($ScheduleAs)
{
  if ($SendMail)
  {
    $params+=' -SendMail:$true'
    $params+=" -MailFrom:$MailFrom -MailTo:$MailTo -MailServer:$MailServer"
  }
  $task = "powershell -c \""pushd $dir; $($myinvocation.mycommand.definition) $params\"""
  schtasks /Create /RU $ScheduleAs /RP /SC WEEKLY /ST 22:00 /TN ExpiredCerts /TR $task
}

Advertisements

Posted in Certificates, Exchange 2010, PowerShell, Windows 2008 R2, Windows Server 2012, Windows Servers | Tagged: , , | Leave a Comment »

Script: Fixing Orphaned AdminSDHolder Accounts

Posted by Alan McBurney on August 27, 2014

This is intended as a follow up to Detecting members of Protected Groups within AD

It seems that no matter how many Exchange or Lync projects I do I always come across the issue of orphaned AdminSDHolders.

To overcome the tedium of detecting and fixing orphaned users I decided to put together a script to automate the task.

This script gets all users that are members of protected groups within AD and compares membership with users that have the AD Attribute AdminCount=1 set. If the user has the AdminCount=1 enabled but is not a member of a protected group within AD then the user is considered orphaned, the AdminCount is reset to 0 and inheritable permissions are enabled.

<#
.SYNOPSIS
Detects Orphaned SD Admin users, resets admin count attribute and enables inheritable permissions

.Author
Alan.McBurney

THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE
RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.

Version 1.0, July 10th, 2014

.DESCRIPTION
This script gets all users that are members of protected groups within AD and compares
membership with users that have the AD Attribute AdminCount=1 set.
If the user has the AdminCount=1 enabled but is not a member of a protected group then the user
is considered an orphaned admin user and the AdminCount is reset to 0 and inheritable permissions
are reset

.REFERENCES
"http://blogs.technet.com/b/heyscriptingguy/archive/2010/07/11/hey-scripting-guy-weekend-scripter-checking-for-module-dependencies-in-windows-powershell.aspx">http://blogs.technet.com/b/heyscriptingguy/archive/2010/07/11/hey-scripting-guy-weekend-scripter-checking-for-module-dependencies-in-windows-powershell.aspx</a>
"http://blogs.msdn.com/b/muaddib/archive/2013/12/30/how-to-modify-security-inheritance-on-active-directory-objects.aspx">http://blogs.msdn.com/b/muaddib/archive/2013/12/30/how-to-modify-security-inheritance-on-active-directory-objects.aspx</a>

.EXAMPLE
Reset-OrphanSDUsers

.Notes
To Do list: Enable logging
#>

#Check to Ensure Active Directory PowerShell Module is available within the system
Function Get-MyModule
{
Param([string]$name)
if(-not(Get-Module -name $name))
  {
    if(Get-Module -ListAvailable |Where-Object { $_.name -eq $name })
    {
      Import-Module -Name $name
      $True | Out-Null
    }
    else
    {
      Write-Host ActiveDirectory PowerShell Module Not Available -ForegroundColor Red
    }
  } # end if not module
  else
  {
    $True | Out-Null
  }   #module already loaded
} #end function get-MyModule

Get-MyModule -name "ActiveDirectory"

Function Set-Inheritance
{
Param($ObjectPath)
$Acl = Get-ACL -path "AD:\$ObjectPath"
  If ($Acl.AreAccessRulesProtected -eq $True)
  {
    $Acl.SetAccessRuleProtection($False, $True)
    Set-ACL -AclObject $ACL -path "AD:\$ObjectPath"
  }
}

#Get List of Proected Groups
$AdminGrp = Get-ADGroup -LDAPFilter "(adminCount=1)"

#Get List of Admin Users (Past and Present)
$AdminUsers = Get-ADUser -LDAPFilter "(adminCount=1)"

$Admins = ForEach ($Grp in $AdminGrp) {Get-ADGroupMember $Grp | Where-Object {$_.ObjectClass -eq "User"}}

#Create Empty Hash
$PGUSers = @{}
$OrphanUsers = @{}

#Compare $AdminUsers to $Admins and place in appropriate hash table
ForEach ($User in $AdminUsers)
{
If ($Admins -Match $User.Name)
  {
    $PGUsers.Add($User.Name, "Present")
  }
  Else
  {
    $OrphanUsers.Add($User.SamAccountName, "NotPresent")
  }
}

If ($OrphanUsers.Keys.Count.Equals(0))
{
  $True | Out-Null
}
Else
{
  #Clear AdminCount Attribute
  ForEach ($Orphan in $OrphanUsers.Keys)
  {
    $Orphan
    $ADUser = Get-ADUser $Orphan
    Set-ADUser $Orphan -Clear {AdminCount}
    Set-Inheritance $ADUser
  }
}

Posted in Active Directory, Exchange 2010, Exchange 2013, Lync, Lync 2013, PowerShell | Tagged: , | 1 Comment »

Detecting members of Protected Groups within AD

Posted by Alan McBurney on July 16, 2013

I do a lot Exchange and Lync work and typically post project I get calls from customers that things aren’t working quite as expected.

Some typical issues include insufficient rights to modify users within Lync, ActiveSync not working or send as permissions being stripped out for users within Exchange.

What all these issues have in common is that users affected are members of what’s termed as Protected Groups within AD and security inheritance is being stripped from the user object.

If you need a primer or a deep dive for that matter into Protected Groups see John Policelli’s article here

The following Active Directory PowerShell commands can be used detect which users and groups are affected by Protected Group status.

To get the list of protected users:
     Get-ADUser -LDAPFilter "(admincount=1)" | select name

To get the list of protected groups:
     Get-ADGroup -LDAPFilter "(admincount=1)" | select name

Once the users have been removed from the Protected Groups its just a matter of enabling security inheritance for the user object from within AD and the issues should be resolved. 

Posted in Active Directory, Exchange 2010, Exchange 2013, Lync, PowerShell, Windows 2008 R2, Windows Server 2012 | Tagged: , | 2 Comments »

Error Adding Members to a DAG on Server 2012

Posted by Alan McBurney on April 8, 2013

Ran into an error this morning trying to add members to a DAG running on Server 2012

When I try to add the nodes to the DAG I got the error

“You must provide an value for this property”

image

Decided I better do some reading on TechNet regarding 2010 DAGs and Server 2012 and it turns out that you must pre-stage the CNO (Cluster Named Object)

The documentation states

Pre-staging the CNO is required for Windows Server 2012 DAG members due to permissions changes in Windows Server 2012 for computer objects.

There are 2 methods to achieve the pre-staging.

  1. Add the “Exchange Trusted Subsystem” group with Full Control to the CNO
  2. Add the first DAG member with Full Control to the CNO

For me I choose to add the “Exchange Trusted Subsystem

Adding the Nodes to the DAG after making the necessary changes worked without issue

image

Posted in Database Availability Group, Exchange 2010, Windows Server 2012 | Tagged: , , , , , , | Leave a Comment »

Unable to Connect to Exchange Management Shell after SP2 installation

Posted by Alan McBurney on September 12, 2012

After patching a number DAG nodes with SP2 I was unable to open the EMC from any of the mailbox servers.

The follow error was displayed

SNAGHTML737be47

To resolve this issue I downloaded the Exchange Management Console Troubleshooter Tool EMTShooter

After running the tool it found an error and displayed the following

image

After reading through the possible solutions I discounted options 2 & 3 as these had already been investigated and the settings were correct.

So with that I settled on option 1.

After examining the GlobalModules of C:\Windows\System32\Inetsrv\config\ApplicationHost.config I could see that the entry for WSMan was indeed missing

image

I added the entry and closed the file

image

Refresh the EMC and viola, good as new.

image

Posted in EMC, Exchange 2010, PowerShell | Tagged: , , , , , | Leave a Comment »

Add Database Copy to Exchange 2010 Database

Posted by Alan McBurney on September 3, 2012

This is a simple scripts that will create a database copy for existing databases on a specific server

#Begin Script
$MainDBServer = Read-Host “Enter Mailbox Server where Databases are located”
$ReplicaServer = Read-Host “Enter Mailbox Server where existing DBs are to be replicated to”
$DBs = Get-MailboxDatabase -Server $MainDBServer
foreach ($DB in $DBs) {Add-MailboxDatabaseCopy $DB -MailboxServer $ReplicaServer -ActivationPreference “2”}
#End Script

Posted in Exchange 2010 | Leave a Comment »

Rebuilding an Exchange DAG

Posted by Alan McBurney on April 10, 2012

Recently I’ve been working with a customer where their DAG has been misbehaving.

The DAG was stretched between 2 AD sites. There were multiple issues with cluster resources in addition to the PAM (Primary Active Manager) not failing over properly

After looking at it for a few hours I decided that the best course of action would be to rebuild the DAG

The following are the steps required in order to remove the DAG and rebuild it

  • Remove All Database Copies from the DAG

Remove-MailboxDatabaseCopy “DBName\ServerToRemove” –Confirm:$False

  • Turn off DataCenter Activation Mode

Set-DatabaseAvailabilityGroup -Identity DAG1 -DatacenterActivationMode Off

  • Remove the MailboxServers from the DAG

Remove-MailboxDatabaseAvailabilityServer DAG1 –MailboxServer ServerToRemove

Be sure to allow time for replication to occur between executing commands

  • Recreate the DAG

New-DatabaseAvailabilityGroup -Name DAG1 –WitnessServer “WitnessServer” -WitnessDirectory D:\DAG1  -DatabaseAvailabilityGroupIpAddresses 192.168.100.100,192.168.101.100

  • Add the servers back into the DAG

Add-DatabaseAvailabilityGroupServer -Identity DAG1 –MailboxServer “SourceMBXServer”
repeat this command for all servers that you wish to add

  • Enable Database Activation Mode

Set-DatabaseAvailabilityGroup -Identity DAG1 -DatacenterActivationMode DAGOnly

  • Finally Add the mailboxdatabase copy server

Add-MailboxDatabaseCopy –Identity DBName -MailboxServer MBXServerToAdd -ActivationPreference 2

  • Finally we can test the Primary Active Manager Failover

Cluster.exe DAG1.DOMAIN.LOCAL Group “Cluster Group” /MoveTo:PassiveServerNode

Posted in Exchange 2010, PowerShell | Tagged: , , , , , , , | Leave a Comment »

Error 0x800706D9 deploying Exchange 2010 Client Access Servers

Posted by Alan McBurney on March 14, 2012

As part of a large scale migration from Exchange 2007 to Exchange 2010 I’ve been installing  a number of Client Access Server using the SP2 binaries of Exchange 2010

The servers displayed the error below when installing the Client Access Server role complaining about End Point mappings

image 

After digging around the ExchangeSetup.log file located in the C:\ExchangeSetupLogs folder I noticed that setup was trying to configure some firewall rules

image

I checked the status of the Firewall and sure enough it was disabled.

All servers were deployed from a template which has the firewall disabled.

I uninstalled Exchange from the server, set the firewall to Automatic and rebooted.

After the reboot the Exchange Client Access role installed on all servers without issue.

Posted in Exchange 2010, Windows 2008 R2 | Tagged: , , , | Leave a Comment »

Reseed failed DAG database copies

Posted by Alan McBurney on September 16, 2011

I have been working with a customer that has a large number of Exchange databases and wishing to to protect these with a DAG solution.

A multi node DAG had been built for the customer and one of the nodes was being problematic when it came to the initial seeding of the database.
The databases would initially seed fine, however as soon as they finished the DB’s momentarily reported “Healthy” before changing status to “FailedandSuspended”

I tried a number of fixes for this including manually copying log and catalog files, however nothing seemed to work. Then in true Microsoft fashion a reboot of the server resolved the issues and the databases seeded properly. After running an update against a DB it’s status remained “Healthy”

As previously stated the customer had a large number of DB’s that were being replicated so I resorted to the Shell to fix the remainder of the DB’s that were “FailedandSuspended”

The following command was used to bring the remainder of the DB’s back to a healthy state

Get-MailboxDatabaseCopyStatus –Server (MBXServerName) | Where-Object {$_.Status –eq “FailedandSuspended”} | Update-MailboxDatabaseCopy –DeleteExistingFiles –SourceServer (SourceMBXServerName)


Job done 🙂

Posted in Exchange 2010, PowerShell | Tagged: , , , | Leave a Comment »

Configuring Exchange 2010 Archive Mailboxes

Posted by Alan McBurney on September 13, 2011

I’ve been doing a large migration lately which has involved configuring all users with an Archive mailbox, setting the retention policy and moving items past retention into the Archive databases.

The users primary mailbox would reside on SAS disk while the archive databases were being stored on cheaper SATA disk.

The “Default Archive Policy”  of moving items older than 2 years into the Online Archive would be used

The high level steps for this were as follows.

  1. Enable the users for archive
  2. Setting the archive database and enabling the retention policy
  3. Testing move of mail items past retention into the Archive database

As there were several thousand users on the system the only sensible way to achieve this was through the shell.

The users were already broken in 14 databases so naturally I approached this on a per database.

The following shell commands were used

Get-MailboxDatabase (DBName) | Get-Mailbox | Enable-Mailbox –Archive

Get-MailboxDatabase (DBName) | Get-Mailbox | Set-Mailbox –ArchiveDatabase (ArchiveDBName) –RetentionPolicy “Default Archive Policy”

Get-MailboxDatabase (DBName) | Get-Mailbox | Start-ManagedFolderAssistant

The Managed Folder Assistant runs nightly, however I used the above command to kick the process off immediately and verify that data was indeed moving to the new Archive DB

Posted in Exchange 2010, PowerShell | Leave a Comment »