22 December 2015

Enable Exchange 2013 Remote PowerShell over SSL

I ran in to this super clear explanation from Damian Scoles on how to configure remote PowerShell over SSL when my remote PowerShell wasn't working.

I covered the same subject once before here - remote-powershell-sessions-for-ad

This goes on step further in securing the session:

For Office365 an SSL connection to remote PowerShell is default.
$LiveCred = Get-Credential
$Session = New-PSSession -name ExchangeOnline -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $LiveCred -Authentication Basic -AllowRedirection
Import-PSSession $Session
Also note that the authentication type is BASIC.

If you try to force the PowerShell virtual directory to only accept SSL, you break local PowerShell access:
Set-PowerShellVirtualDirectory -Server ex01 -RequireSSL $true

Now that PowerShell access is broken we cannot run PowerShell commands to fix the PowerShell Virtual Directory? So switch to IIS Manager. At the PowerShell virtual directory ‘Require SSL’ is checked:


Uncheck the box and click apply.

Local Exchange PowerShell is working again.
Now how do we enable SSL remote PowerShell?
Lets make sure we can do PowerShell remoting over HTTP:

Verify it’s enabled:
Enter-PSSession -ComputerName localhost
If you receive an error, then PowerShell remoting can be enabled with this command:
Enable-PSRemoting
Choose ‘A’ for the answer to the two questions:



Now that we have PowerShell enabled, verify the user account you want to connect with has access:
Get-User <alias> |ft displayname,*power*,
If the result is True, then the user has permission to connect remotely via PowerShell.

What about SSL? Let’s see what happens by default:
New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://<exchange server FQDN>/PowerShell/ -Credential (Get-credential) -Authentication Kerberos
** Note ** Using Basic for Authentication method will cause the connection to fail. Either have no

Authentication defined, or choose something like kerberos in our example.

You will be prompted for credentials and allowed to connect. If however the connectionURI contains HTTPS and not HTTP, it will fail.
New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://<exchange server FQDN>/PowerShell/ -Credential (Get-credential) -Authentication Kerberos

So what is the fix? IIS Authentication. The PowerShell virtual directory has no authentication settings configured
Get-PowerShellVirtualDirectory -Server <Exchange Server> | fl *auth*


Notice that no authentication is configured by default. Let’s enable Basic Authentication as this will allow us to use an SSL connection to remotely connect via Powershell.
Get-PowerShellVirtualDirectory -Server <exchange server> | Set-PowerShellVirtualDirectory -BasicAuthentication $true

Now that we have verified PowerShell Remoting is enabled, that our user account has access and that Basic Authentication is enabled, we should be able to connect via HTTPS:







We now have a successful connection to our remote Exchange 2013 server over HTTPS.

Source

16 December 2015

Export email addresses, username and displayname from AD group to text file

Sometimes I get asked to export certain properties from AD or Exchange because I tend to do things with Powershell for ease of use.

Same goes for this request, retrieve the members from an AD group and display the username, displayname and emailaddress and export it to a file:

$groupname = "AD group name"

 Get-ADGroupmember $groupname | %{get-aduser $_.samaccountname -properties cn,samaccountname,emailaddress | select cn,samaccountname,emailaddress | Out-File c:\temp\output.txt

07 December 2015

Add Private computer and Lite version options back to OWA

When searching how to brand the OWA page with a server name, i came across this post by  Arjan Mensch.

It describes how to add the Lite OWA version and the Private computer options back in to OWA 2013 (and maybe even 2016, but i'm not able to test this).

As you may remember from Exchange 2010, there was an option to choose your privacy mode for the session:

  • This is a public or shared computer
  • This is a private computer
  • Use Outlook Web App Light























Choosing between public or shared means different timeout values for the OWA session.

To bring the public private option back to OWA run in the Exchange powerShell:
Get-OwaVirtualDirectory | Set-OwaVirtualDirectory -LogonPagePublicPrivateSelectionEnabled $true

To bring back the Light version of OWA:
Get-OwaVirtualDirectory | Set-OwaVirtualDirectory -LogonPageLightSelectionEnabled $true

To enable both the "private public" and "Lite" option for several servers in a nice onliner:
Get-OwaVirtualDirectory | Where-Object {$_.owaversion -eq "Exchange2013"} | Set-OwaVirtualDirectory -LogonPagePublicPrivateSelectionEnabled $true -LogonPageLightSelectionEnabled $true


After running these command-lets you need to restart IIS.
To do this for all servers you can run this:
$servers = "server1","server2","server3","server4","server5","server6"
foreach ($server in $servers) 
{
restart-service -servicename "w3svc"
}

Brand OWA 2013 logon page

Just like in Exchange 2007 and 2010, the Outlook web app page can be customized to your needs.

See my previous post about this here.

In my organization we use 6 multi role Exchange 2013 servers, and when logging on to OWA you can't quickly see on which server you ended up.

This can be edited fairly quickly, but keep in mind that all these changes are undone when updating the Exchange systems with a cumulative update (CU).

First you need to go to the following location:
C:\Program Files\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy\owa\auth
In there you will find a file called "logon.aspx", open it in your editor of choice.

For me that's Notepad++, and on line 272 add the following line:

<p><span style="color: #FFFFFF;">SERVERNAME</span></p>

This will add your servername in white text. So if you want to see it you'll have to select the entire logon page by pressing CTRL + a, then you will see the servername.



Important Note: These edits are overwritten anytime an Exchange Server update is applied to the CAS servers.
This is because every update includes a complete reinstallation of the Exchange binaries, and the logon.aspx file you edited will be overwritten.


Typically, the logon.aspx page rarely changes, so you can usually make a copy of it after you've made your edits and copy it back after the update. However, there are no guarantees that the file will not be changed by an update. If so, you will need to re-edit the logon.aspx file.

After each installation of a cumulative update for Exchange 2013, remember to execute both the UpdateCas.ps1 and UpdateConfigFiles.ps1 Windows PowerShell scripts.
It will save you a lot of trouble, troubleshooting errors with OWA and ECP.

11 November 2015

Skype for Business 2015, Lync 2010 and Lync 2013 IM integration into Exchange 2013 OWA

Update - 27-10-2016 - Added step 3.

We're migrating to Exchange 2013 at my company, and one of the things on my todo list was get Lync integrated into Exchange 2013 OWA.

After finding this great blog post from Oliver Moazzezi it worked at the first try.
I found this article at Technet and thought it was even more clear, especially for Skype for Business 2015.

There were a couple of things that could use some clarification so here is a little rewrite:

Exchange 2013 has two roles. The Front End proxy, and the Back End. The Back End co-locates all roles which are: Mailbox, Client Access, Hub Transport and Unified Messaging.
In Exchange 2010 you configured the IM integration entirely on the server that had the Client Access role. This could be a standalone server all co-located role server depending on the infrastructure needed. This was a config file at Exchange 2010 RTM and later moved to Powershell and settings on OWA virtual directories with SP1+.
In Exchange 2013 configuration is necessary on both the Front End and Back End roles. Again this can be co-located or standalone. I will treat them as separated for ease of understanding here.
Exchange 2013 Front Ends

1.    Perform in Powershell “Get-OWAVirtualDirectory”, you can use “Get-OWAVirtualDirectory –identity “servername\owa (default web site)” | select inst*” to immediately get the necessary information.



2. You will, if familiar with IM integration in Exchange 2010, be immediately at home here. However for IM integration in Exchange 2013 we only set two of the above four values. The values are ‘InstantMessagingEnabled’ and ‘InstantMessagingType’. We leave both ‘InstantMessagingCertificateThumbprint’ and ‘InstantMessagingServerName’ blank. This is very important as it actually does break the integration between Lync 2010 and Exchange 2013.

We can set these values with the following command:  
“Set-OwaVirtualDirectory –identity “servername\owa (default web site)” –InstantMessagingEnabled $true –InstantMessagingType OCS”
(Ignore the yellow text in my example below – I’m running the command to show you but as I’ve already set these attributes it’s telling me no settings have been modified)


3. Set the default mailbox policy to allow IM:

Set-OwaMailboxPolicy -Identity "Default" -InstantMessagingEnabled $True -InstantMessagingType "OCS"

4 . Perform the above command against ALL your Exchange 2013 Front End servers in your associated sites that need IM integration.

Exchange 2013 Back ends

5. Once this has been set we need to configure certificates. But the certificate configuration is on our Back End Exchange 2013 Servers. Browse to your Back End Servers and generate a new Certificate using New-ExchangeCertificate against the internal CA that Lync uses. I recommend this TechNet article for Cert creation: http://technet.microsoft.com/en-us/library/aa998327.aspx

Use the following two commands:
$Data = New-ExchangeCertificate –GenerateRequest –SubjectName “CN=servername.domain.lan” –DomainName “servername.domain.lan” –PrivateKeyExportable $true –FriendlyName “Easy title to see the purpose of this certififcate”

Then:

Set-Content –Path “C:\Temp\Servername.req” –Value $Data


6. Once this is done we need to complete the signing request against your internal certificate authority. I have used the web request of our SubOrdinate for this example. Use the same internal CA as what you used for SSL procurement for your Lync platform!



Save the signing request.
7. We now need to complete the signing request using Import-ExchangeCertificate. Information on this cmdlet is available here: http://technet.microsoft.com/en-us/library/bb124424.aspx


“Import-ExchangeCertificate -FileData ([Byte[]]$(Get-Content -Path ‘C:\Temp\Servername.cer’ -Encoding byte -ReadCount 0))




The certificate is now installed.
After importing the certificate you will see the thumbprint in the result screen as seen above.

--Copy this thumbprint now, you need it later in the web.config file--
Ensure you do this for all Exchange 2013 Back End Servers.
  

8. We are now in a place where all our Exchange 2013 Front End Servers have had the necessary configuration via Powershell and ‘Set-OWAVirtualDirectory’, and we have installed Certificates on all our Exchange 2013 Back End servers. We now need to edit a web config file on each Exchange 2013 Back End.The file we want to modify is the web.config file in the following location “x:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\Owa”. Where x is the drive you installed too.


9.     Open the Web Config file and perform a search for “</appsettings>”. This takes you to the end of all App Settings configuration. Add these three lines in:

    <!-- Lync IM -->

    <add key="IMCertificateThumbprint" value="Enter Thumbprint here!" />
      <add key="IMServerName" value="FQDN of Lync Pool or Director Pool" />

To get the Lync FQDN Pool name:

Get-CsPool | fl fqdn
   You can see I have commented this out to explain the change I am making.


It is important to note that the thumbprint you enter in each web.config file is the thumbprint of the Certificate you have created on each Back End server.

10. Once you have performed this on all Back Ends we need to open the Lync Topology Builder and enter each Back End as a Trusted Application

Add each Exchange 2013 Back End server separately, matching the FQDN of the server and the certificate published for the Back End as the Trusted Application. Add all required Exchange 2013 Back Ends. You can also do this in a Lync PowerShell:

New-CsTrustedApplicationPool -Identity Mailboxserver.domain.com -Registrar lyncpoolname.domain.com -Site 1 -RequiresReplication $False


11.   Once created you can edit them and remove ‘Enable replication of configuration data to this pool’ as this is not needed for Lync IM integration.

12. Once all have been added Publish the Topology.
13.   We now need to open a Lync Powershell session and perform the following:

New-CsTrustedApplication –ApplicationID “Server Name” –TrustedApplicationPoolFqdn “FQDN of Exchange 2013 Back End server” –Port ‘desired port number’

Set the ApplicationID as the server name for easy reference. Set the TrustedApplicationPoolFQDN as the FQDN of the Exchange 2013 Back End you are adding. Add a port number that isn’t in use. I used 5199.



14. Once this is done ensure you repeat it for every Exchange 2013 Back End server that you need and indeed published in the Topology Builder in step 11. and 12.
15. And the last thing: Enable-CsTopology
In case it's not working as expected we may need to do the following two things to get Lync IM integration working.

The first is to recycle the MSExchangeOWAAppPool on each Exchange 2013 Back End.

This needs to be done only if IM integration is not working in OWA.

The second is to restart IIS on each Exchange 2013 Front End server.
This needs to be done only if IM integration is not working in OWA.

16. Open OWA. You should now be able to sign in and see this:




The first thing you’ll notice over Exchange 2010 OWA integration is that the contact list is not shown on the left pane anymore. You have to get it from the People Hub.



If you aren't seeing the above then you may have an OWA Mailbox Policy that isn't allowing IM. Perform in Powershell: Get-OWAMailboxPolicy to confirm against the affected users.

In the event this is the issue, use:

"Set-OWAMailboxPolicy -identity 'OWAMailboxPolicy' -InstantMessagingType OCS"

29 October 2015

Move Exchange log file directories to an other drive

There are several log files in Exchange 2013 by default that help aid in diagnostics, transport troubleshooting, OWA, etc. But all these log files consume a lot of disk space, 30GB according to Microsoft.
To free up some space or to prevent your system drive from filling up and taking down your entire server, you can move some of these fairly easy to an other disk.

Stop all Exchange services to be safe:
Stop-Service MSExchangeADTopology

Get the current (default) locations for the log files:
get-TransportService sr-xxxxx | fl *logpath*

ConnectivityLogPath         : C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Logs\Hub\Connectivity
MessageTrackingLogPath      : C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Logs\MessageTracking
IrmLogPath                  : C:\Program Files\Microsoft\Exchange Server\V15\Logging\IRMLogs
ActiveUserStatisticsLogPath : C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Logs\Hub\ActiveUsersStats
ServerStatisticsLogPath     : C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Logs\Hub\ServerStats
ReceiveProtocolLogPath      : C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Logs\Hub\ProtocolLog\SmtpRe
                              ceive
RoutingTableLogPath         : C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Logs\Hub\Routing
SendProtocolLogPath         : C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Logs\Hub\ProtocolLog\SmtpSe
                              nd
QueueLogPath                : C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Logs\Hub\QueueViewer
WlmLogPath                  : C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Logs\Hub\WLM
AgentLogPath                : C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Logs\Hub\AgentLog
FlowControlLogPath          :
ProcessingSchedulerLogPath  :
ResourceLogPath             :
DnsLogPath                  :
JournalLogPath              : C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Logs\JournalLog
TransportMaintenanceLogPath :
Set the log files to the new location:

Get-TransportService | foreach {
Set-TransportService -MessageTrackingLogPath “D:\Logs\MessageTracking”
Set-TransportService -ConnectivityLogPath “D:\Logs\Connectivity”
Set-TransportService -IrmLogPath “D:\Logs\IRMLogs”
Set-TransportService -ActiveUserStatisticsLogPath “D:\Logs\ActiveUserStats”
Set-TransportService -ServerStatisticsLogPath “D:\Logs\ServerStats”
Set-TransportService -ReceiveProtocolLogPath “D:\Logs\ProtocolLog\SmtpReceive”
Set-TransportService -RoutingTableLogPath “D:\Logs\Routing”
Set-TransportService -SendProtocolLogPath “D:\Logs\ProtocolLog\SmtpSend”
}

Start-Service MSExchangeADTopology
Check if the default folders are empty other wise stop the services again and move all files to the new folder and restart the services.

Install Exchange server productkey with PowerShell

This also works in Exchange 2010:
Set-ExchangeServer -Identity SR-XXXXX -ProductKey ABCDE-FGHIJ-KLMNO-PQRST-UVWXY
Or set all your servers at once: (This only works if all your Exchange server are the same version)
Get-ExchangeServer | Set-ExchangeServer -ProductKey ABCDE-FGHIJ-KLMNO-PQRST-UVWXY
After restarting the "Microsoft Exchange Information Store" the Activation will be effective. So to restart all Exchange Information Store services run:
Get-Service -Name "Microsoft Exchange Information Store" -ComputerName SR-XXXXX | Restart-Service

Move Exchange 2013 Transport Queue to other location

How to move the Transport Queue to a different location than the default or to an other drive.


Log in as an (local) Administrator

Create the folders where you want to keep the queue database and transaction logs. Make sure that the correct permissions are applied to the folders.

Network Service: Full Control
System: Full Control
Administrators: Full Control

In an elevated Command prompt window, open the EdgeTransport.exe.config file in Notepad by running the following command:

Copy Notepad %ExchangeInstallPath%Bin\EdgeTransport.exe.config

Modify the following keys in the <appSettings> section:

<add key="QueueDatabasePath" value="<LocalPath>" />
<add key="QueueDatabaseLoggingPath" value="<LocalPath>" />

To change the location of the queue database to D:\TransportQueue\QueueDB and the transaction logs to D:\TransportQueue\QueueLogs, use the following values:

<add key="QueueDatabasePath" value="D:\Queue\QueueDB" />
<add key="QueueDatabaseLoggingPath" value="D:\Queue\QueueLogs" />

When you are finished, save and close the EdgeTransport.exe.config file.

Stop the Microsoft Exchange Transport service by running the following command:

net stop MSExchangeTransport

Move the existing database files Mail.que and Trn.chk from the original location to the newlocation.
(
D:\TransportQueue\QueueDB)

Move the existing transaction log files Trn.log, Trntmp.log, Trnnnnnn.log, Trnres00001.jrs,Trnres00002.jrs, and Temp.edb from the old location to the new location.(D:\TransportQueue\QueueLogs)

Start the Microsoft Exchange Transport service by running the following command:

net start MSExchangeTransport

If the Transport service doesn't start, chances are you didn't add the "Network Service" with Full Control to the directories.

To verify that you successfully moved the existing queue database and transaction logs to the new location, do the following:
  1. Verify the queue database files Mail.que and Trn.chk exist at the new location.
  2. Verify the transaction log files Trn.log, Trntmp.log, Trnres00001.jrs, Trnres00002.jrs, and Temp.edb files exist at the new location.
  3. Verify there are no queue database or transaction log files at the original location.

27 October 2015

Exchange 2013 Tips of the day - so far...

Tip of the day #1:

Did you know that the Identity parameter is a "positional parameter"? That means you can use:

 Get-Mailbox "user" instead of: Get-Mailbox -Identity "user"

It's a neat usability shortcut!


Tip of the day #2:

Did you know that the Identity parameter is a "positional parameter"? That means you can use:

 Get-Mailbox "user" instead of: Get-Mailbox -Identity "user"

It's a neat usability shortcut!


Tip of the day #3:

Did you know that the Identity parameter is a "positional parameter"? That means you can use:

 Get-Mailbox "user" instead of: Get-Mailbox -Identity "user"

It's a neat usability shortcut!


Tip of the day #4:

Did you know that the Identity parameter is a "positional parameter"? That means you can use:

 Get-Mailbox "user" instead of: Get-Mailbox -Identity "user"

It's a neat usability shortcut!


Tip of the day #5:

Tired of typing a long command every time that you want to do something? Alias it! Type:

 Set-Alias GetMre Get-ManagementRoleEntry

For all the current aliases, type:

 Get-Alias


Tip of the day #6:

Want to see the members of a dynamic distribution group that has a custom filter? Just use the Get-Recipient cmdlet. Type:

 $DDG = Get-DynamicDistributionGroup "Contoso Marketing Managers"
 Get-Recipient -RecipientPreviewFilter $DDG.RecipientFilter


Tip of the day #7:

The Exchange Management Shell is a calculator, too! Try it directly at a command prompt:

 1.2343+3123 or (23/435)*2


Tip of the day #8:

Command line SOS! Do you need help? Type:

 Help <cmdlet-name>  or  <cmdlet-name> -?

You can choose what information to return when you view Help by using the Detailed, Full, and Examples switches:

 Help Get-Mailbox -Detailed


Tip of the day #9:

Want to look at Help for a cmdlet but don't want to read through pages and pages of text in the Shell window? Just use t
he Online switch with the Get-Help cmdlet. The Online switch tells the Shell to open the online version of the cmdlet's
Help topic in your default browser. Type:

 Get-Help <cmdlet> -Online


Tip of the day #10:

The tilde character (~) should be familiar to Unix users. It represents the shortcut to your root directory. To see what
 it's evaluated to by default, type:

 Dir ~

You can use it as a useful shortcut:

 Cp SomeFile "~\My Documents"


Tip of the day #11:

CTRL+C is the equivalent of the hard-break command in the Exchange Management Shell. If a command is taking too long to
run or you want to cancel an operation quickly, press CTRL+C to stop execution.


Tip of the day #12:

Pushd and Popd work the same way in the Exchange Management Shell as they do in cmd.exe. Type:

 Pushd <location>


Tip of the day #13:

XML over everything! The Exchange Management Shell treats XML as a native type, so that you can do interesting things li
ke:

 $Sample = [XML](Get-Content SomeXMLFile.xml)

This command assigns $Sample to the actual XML object. To see it, type:

 $Sample

To navigate, type:

 $Sample.Prop1.Prop2

No need for text parsing when you want to load XML data!


Tip of the day #14:

Cmdlets that end in "Config" manage singleton configuration, either one per server or organization. For these tasks, you
 don't have to specify an identity because there is only one instance of the configuration. You may have to specify the
Server parameter if the configuration is per server.


Tip of the day #15:

To get a list of all users on an Exchange 2013 server who aren't Unified Messaging-enabled, type:

 $Mailboxes = Get-Mailbox
 $Mailboxes | ForEach { If($_.UmEnabled -Eq $False){$_.Name}}


Tip of the day #16:

To get a list of all users on an Exchange 2013 server who are Unified Messaging-enabled, type:

 $Mailboxes = Get-Mailbox
 $Mailboxes = | ForEach { If($_.UmEnabled -Eq $True){$_.Name}}


Tip of the day #17:

To display the user's alias formatted in a table together with the user's Exchange 2013 server name and telephone extens
ion, type:

 Get-Mailbox | Format-Table ServerName,@{e={$_.SamAccountName};Label="User Alias"},@{Expression="Extensions";Label="Tele
phone numbers"}


Tip of the day #18:

To display the list of UM IP gateway server names disabled for outbound calling and hunt groups associated with a UM IP
gateway server, type:

 $Gateways = Get-UMIPGateway
 $Gateways | ForEach {If($_.OutCallsAllowed -Eq $False){ "Gateway Name = " +$_.Name;ForEach ($HuntGroup In $_.Huntgroups
){"Huntgroups " + $Huntgroup}}}


Tip of the day #19:

If you want to test all IP Block List providers, you just have to pipe the Get-IpBlockListProvider cmdlet to the Test-Ip
BlockListProvider cmdlet:

 Get-IpBlockListProvider | Test-IpBlockListProvider -IpAddress 192.168.0.1


Tip of the day #20:

Before you remove an object by using the Remove verb, use the WhatIf parameter to verify the results are what you expect
.


Tip of the day #21:

Sometimes it's useful to convert the output of a cmdlet to a string to interoperate with native cmdlets. For example, ty
pe:

 Get-Mailbox | Out-String | Findstr "Administrator"


Tip of the day #22:

Get all Win32 WMI information, such as Perfmon counters and local computer configurations. For example, type:

 Get-WMIObject Win32_PerfRawData_PerfOS_Memory


Tip of the day #23:

Who isn't tired of spam? You can configure real-time block list (RBL) providers with the Exchange Management Shell by ru
nning the following two commands:

 Set-IPBlockListProvidersConfig -Enabled $True -ExternalMailEnabled $True

and then

 Add-IPBlockListProvider -Name <Name of RBL Provider> -LookupDomain <FQDN of RBL Provider> -AnyMatch $True


Tip of the day #24:

Access the event log from the Exchange Management Shell. To retrieve the whole event log, type:

 Get-EventLog Application | Format-List

To retrieve all Exchange-related events, type:

 Get-EventLog Application | Where { $_.Source -Ilike "*Exchange*" }


Tip of the day #25:

One benefit of the Exchange Management Shell is that cmdlets can output objects to the console. You can then manipulate
this output and organize it in interesting ways. For example, to get a quick view in tabular format, use Format-Table:

 Get-Mailbox | Format-Table Name,Database,RulesQuota


Tip of the day #26:

Forget a property name? Not a problem because you can use wildcard characters to retrieve all properties that match the
part of the name that you specify:

 Get-Mailbox | Format-Table Name,*SMTP*


Tip of the day #27:

Want to work with data contained in a CSV file? Use Import-CSV to assign the data to an object. For example, type:

 $MyCSV = Import-CSV TestFile.CSV

You can then manipulate the data easily in the Exchange Management Shell. For example, if there is a column called Mailb
oxes in the CSV data, you can use the following commands to sort or group the data by the Mailboxes column:

To sort: $MyCSV | Sort Mailboxes
To group: $MyCSV | Group Mailboxes


Tip of the day #28:

This command spins through all your mailbox servers and reconnects all the uniquely identified but disconnected mailboxes in any one of the mailbox stores:

 $Servers = Get-ExchangeServer
 $Servers | `
  Where { $_.IsMailboxServer -Eq '$True' } `
  | ForEach { Get-MailboxStatistics -Server $_.Name `
  | Where { $_.DisconnectDate -NotLike '' } `
  | ForEach { Connect-Mailbox -Identity `
    $_.DisplayName -Database $_.DatabaseName} }


Tip of the day #29:

Tab completion reduces the number of keystrokes required to complete a cmdlet. Just press the TAB key to complete the cm
dlet you're typing. Tab completion kicks in whenever there is a hyphen (-) in the input. For example:

 Get-Send<tab>

should complete to Get-SendConnector. You can even use wildcards, such as:

 Get-U*P*<tab>

Pressing the TAB key when you enter this command cycles through all cmdlets that match the expression, such as the Unifi
ed Messaging Mailbox policy cmdlets.


Tip of the day #30:

Tab completion reduces the number of keystrokes required to complete a cmdlet. Just press the TAB key to complete the cm
dlet you're typing. Tab completion kicks in whenever there is a hyphen (-) in the input. For example:

 Get-Send<tab>

should complete to Get-SendConnector. You can even use wildcards, such as:

 Get-U*P*<tab>

Pressing the TAB key when you enter this command cycles through all cmdlets that match the expression, such as the Unifi
ed Messaging Mailbox policy cmdlets.


Tip of the day #31:

Tab completion reduces the number of keystrokes required to complete a cmdlet. Just press the TAB key to complete the cm
dlet you're typing. Tab completion kicks in whenever there is a hyphen (-) in the input. For example:

 Get-Send<tab>

should complete to Get-SendConnector. You can even use wildcards, such as:

 Get-U*P*<tab>

Pressing the TAB key when you enter this command cycles through all cmdlets that match the expression, such as the Unifi
ed Messaging Mailbox policy cmdlets.


Tip of the day #32:

Tab completion reduces the number of keystrokes required to complete a cmdlet. Just press the TAB key to complete the cm
dlet you're typing. Tab completion kicks in whenever there is a hyphen (-) in the input. For example:

 Get-Send<tab>

should complete to Get-SendConnector. You can even use wildcards, such as:

 Get-U*P*<tab>

Pressing the TAB key when you enter this command cycles through all cmdlets that match the expression, such as the Unifi
ed Messaging Mailbox policy cmdlets.


Tip of the day #33:

Want to create a group of test users in your lab? Use this command:

 1..100 | ForEach { Net User "User$_" MyPassword=01 /ADD /Domain; Enable-Mailbox "User$_" }


Tip of the day #34:

Like the Exchange Management Shell Tip of the Day? Try this:

 Get-Tip


Tip of the day #35:

Want to set the properties on all or some Outlook Web Access virtual directories? Pipe the output of Get-OwaVirtualDirec
tory to the Set-OwaVirtualDirectory cmdlet. For example, the following command sets the Gzip level for all Outlook Web A
ccess virtual directories:

 Get-OwaVirtualDirectory | Set-OwaVirtualDirectory -GzipLevel High


Tip of the day #36:

Want to move your database path to another location? Type:

 Move-DatabasePath -EdbFilePath DestFileName

To change the file path setting without moving data, use this command together with the ConfigurationOnly parameter. Thi
s command is especially useful for disaster recovery. Caution: Misuse of this cmdlet will cause data loss.


Tip of the day #37:

Need an easy way to add a new primary SMTP address to a group of mailboxes? The following command creates a new email ad
dress policy that assigns the @contoso.com domain to the primary SMTP address of all mailboxes with Contoso in the compa
ny field:

 New-EmailAddressPolicy -Name Contoso -RecipientFilter {Company -Eq "Contoso"} -EnabledPrimarySMTPAddressTemplate "@cont
oso.com"


Tip of the day #38:

Want to retrieve a group of objects that have similar identities? You can use wildcard characters with the Identity para
meter to match multiple objects. Type:

 Get-Mailbox *John*
 Get-ReceiveConnector *toso.com
 Get-JournalRule *discovery*


Tip of the day #39:

Want to configure a group of objects that have similar identities? You can use wildcard characters with the Identity par
ameter when you use a Get cmdlet and pipe the output to a Set cmdlet. Type:

 $Mailboxes = Get-Mailbox *John*
 $Mailboxes | Set-Mailbox -ProhibitSendQuota 100MB -UseDatabaseQuotaDefaults $False

This command matches all mailboxes with the name John in the mailbox's identity and sets the ProhibitSendQuota parameter
 to 100MB. It also sets the UseDatabaseQuotaDefaults parameter to $False so that the server uses the new quota you speci
fied instead of the database default quota limits.


Tip of the day #40:

Forgot what the available parameters are on a cmdlet? Just use tab completion! Type:

 Set-Mailbox -<tab>

When you type a hyphen (-) and then press the TAB key, you cycle through all the available parameters on the cmdlet. Wan
t to narrow your search? Type part of the parameter's name and then press the TAB key. Type:

 Set-Mailbox -Prohibit<tab>


Tip of the day #41:

Want to add an alias to multiple distribution groups that have a similar name? Type:

 $Groups = Get-DistributionGroup *Exchange*
 $Groups | Add-DistributionGroupMember -Member kim

This command adds the alias kim to all distribution groups that contain the word Exchange.


Tip of the day #42:

Want to record exactly what happens when you're using the Exchange Management Shell? Use the Start-Transcript cmdlet. An
ything that you do after you run this cmdlet will be recorded to a text file that you specify. To stop recording your se
ssion, use the Stop-Transcript cmdlet.

Notice that the Start-Transcript cmdlet overwrites the destination text file by default. If you want to append your sess
ion to an existing file, use the Append parameter:

 Start-Transcript c:\MySession.txt -Append


Tip of the day #43:

Do you have a user who has network access but maintains an external mail account outside your Exchange organization? Wit
h Exchange 2013, you can now create mail-enabled users that are regular Active Directory accounts, but also behave like
mail-enabled contacts. By using the Enable-MailUser cmdlet, you can add email contact attributes to any existing Active
Directory user who doesn't already have a mailbox on an Exchange server. Users in your Exchange organization will then b
e able to send email messages to that user's external mail account. Type:

 Enable-MailUser -Identity <Active Directory Alias> -ExternalEmailAddress <Destination SMTP Address>


Tip of the day #44:

Want to change the default prohibit send quota for a mailbox database? Type:

 Set-MailboxDatabase <Mailbox Database Name> -ProhibitSendQuota <New Quota Size>

You can specify a bytes qualifier when you use the ProhibitSendQuota parameter. For example, if you want to set the proh
ibit send quota to 200 megabytes, type:

 Set-MailboxDatabase <Mailbox Database Name> ProhibitSendQuota 200MB

You can also configure the IssueWarningQuota parameter and the ProhibitSendReceiveQuota parameter in the same way.


Tip of the day #45:

Want to know what version of Exchange Server each of your servers is running? Type:

 Get-ExchangeServer | Format-Table Name, *Version*


Tip of the day #46:

Want to determine whether a server is running Exchange Server 2013 Standard, Enterprise or Hybrid Edition? Type:

 Get-ExchangeServer <Server Name> | Format-Table Name, Edition

If you want to view which edition all your Exchange servers are running, omit the <Server Name> parameter.


Tip of the day #47:

Want to create a new resource mailbox that can be used to book a meeting room? Type:

 New-Mailbox -Name <Conference Room Name> -UserPrincipalName <SMTP Address> -OrganizationalUnit <Organizational Unit> -Room

This command creates a disabled Active Directory user who has a mailbox that accepts meeting requests from users.


Tip of the day #48:

Want to control the properties of email messages sent to a specific domain? Use the RemoteDomain cmdlets. Create a new r
emote domain by using the New-RemoteDomain cmdlet. Type:

 New-RemoteDomain -Name "Contoso.com Configuration" -DomainName contoso.com

Then modify the properties that you want for this remote domain by using the Set-RemoteDomain cmdlet:

 Set-RemoteDomain "Contoso.com Configuration" -AutoReplyEnabled $True -AutoForwardEnabled $True


Tip of the day #49:

Booleans are parameters that can be evaluated as either $True or $False. Booleans are typically used as a flag on an obj
ect that modifies the behavior of that object. In the Exchange Management Shell, you must supply a Boolean parameter wit
h either a $True, $False, 1, or 0. No other values are accepted, including True or False. For example, both of the follo
wing commands set the enabled state of the ExampleAssignment management role assignment to $True:

 Set-ManagementRoleAssignment ExampleAssignment -Enabled $True
 Set-ManagementRoleAssignment ExampleAssignment -Enabled 1


Tip of the day #50:

Want an easy way to apply deleted item retention limits across multiple databases and servers? Try the following command
 to configure deleted item retention across all databases on a specified server:

 Get-MailboxDatabase -Server <Server Name> | Set-MailboxDatabase -DeletedItemRetention 45.00:00:00

You can also apply the same deleted item retention limits or mailbox retention limits across all servers in your organiz
ation:

 Get-MailboxDatabase | Set-MailboxDatabase -DeletedItemRetention 45.00:00:00 -MailboxRetention 120.00:00:00


Tip of the day #51:

Want to know what permissions an Active Directory user account has on a specific mailbox? Use:

 Get-Mailbox <Mailbox to Check> | Get-MailboxPermission -User <Active Directory User>


Tip of the day #52:

Want to know which mailboxes a specific Active Directory user has permissions to? Type:

 $Mailboxes = Get-Mailbox -ResultSize Unlimited
 $Mailboxes | Get-MailboxPermission -User <Active Directory User> | Format-Table Identity, AccessRights, Deny

Caution: This command enumerates all the mailboxes in your organization. If you have lots of mailboxes, you may want to
target specific mailboxes.


Tip of the day #53:

Want to get a list of the backup status of all mailbox databases in your organization? Type:

 Get-MailboxDatabase -Status | Format-Table Name, Server, *Backup*

How about just the mailbox databases on a specific server? Type:

 $Databases = Get-MailboxDatabase -Server <Server Name> -Status
 $Databases | Format-Table Name, *Backup*


Tip of the day #54:

To retrieve the current status of an Exchange server or database, use the Status parameter. For example:

 Get-ExchangeServer -Status | Format-List
 Get-MailboxDatabase -Server <Server Name> -Status | Format-List


Tip of the day #55:

Want to view the mounted status of all mailbox databases? Type:

 Get-MailboxDatabase -Status | Format-Table Name, Server, Mounted


Tip of the day #56:

What's the difference between server-side filtering and client-side filtering? Server-side filtering is used with the re
cipient and queue cmdlets, which support the Filter parameter, because these cmdlets can return large result sets. The s
erver filters the results by using the criteria you specify and then sends you the filtered results. Client-side filteri
ng can be used with any cmdlet. The entire result set is sent to the client computer, which then filters the data and pr
ovides a filtered result set. Client-side filtering uses the Where-Object cmdlet, which can be shortened to Where.


Tip of the day #57:

With Exchange 2013 Unified Messaging, you can redirect unauthenticated callers to certain telephone extensions to an ope
rator instead of to the extension that was dialed. To list users for whom Unified Messaging transfers unauthenticated ca
llers to the operator, instead of to the user, type:

 $Mailboxes = Get-UMMailbox
 $Mailboxes | Where-Object { $_.AllowUMCallsFromNonUsers -eq `
 [Microsoft.Exchange.Data.Directory.Recipient.AllowUMCallsFromNonUsersFlags] "None" }


Tip of the day #58:

You can use client-side filtering to return only the data that you want to see or work with. The following example retri
eves all Active Directory user accounts in the Engineering department and puts the results in a table with two columns,
Name and Department. By using the ResultSize parameter, the Get-User cmdlet limits the result set to 2,000 users.

 $Users = Get-User -ResultSize 2000
 $Users | Where { $_.Department -Eq "Engineering" } | Format-Table Name, Department


Tip of the day #59:

The special variable $_ represents the objects being passed from one cmdlet to another cmdlet in the pipeline. The $_ va
riable is automatically initiated by the Shell and is bound to the current pipeline object. You can access the propertie
s of the object assigned to the $_ variable as you would any other object. The following example shows how you can view
the Name property of each mailbox object that is passed through the pipeline:

 Get-Mailbox | ForEach { $_.Name }


Tip of the day #60:

You can import CSV files and treat them as objects by using the Import-Csv cmdlet. Each row in a CSV file becomes an ele
ment in an array, and each column becomes a property. You can assign the CSV file to a variable, or you can pipe its con
tents directly to another cmdlet. In the following example, there are three columns in the CSV file, Name, Alias, and Em
ailAddress, with several rows that the ForEach cmdlet will cycle through. The data in each row is used to create a new m
ail contact.

 $CSV = Import-Csv
 $CSV | ForEach { New-MailContact -Name $_.Name -Alias $_.Alias -  ExternalEmailAddress $_.EmailAddress -OrganizationalUnit Users }


Tip of the day #61:

Want to customize your Exchange Management Shell profile? Run the following command to determine the location of your Mi
crosoft.PowerShell_profile.ps1 file:

 $Profile

You may have to create the PSConfiguration folder and Microsoft.PowerShell_profile.ps1 file. After you've done that, you
 can add your favorite functions and aliases, which will be loaded every time that the Exchange Management Shell is open
ed.


Tip of the day #62:

Want to see everything that occurs when you run a command? Include the Verbose parameter with the command. This paramete
r instructs the Exchange Management Shell to display detailed information about each action that the server takes to com
plete the command. This information can be useful in troubleshooting.


Tip of the day #63:

Any cmdlet that accepts a size value lets you specify whether the integer value is in kilobytes (KB), megabytes (MB), gi
gabytes (GB), or terabytes (TB). For example:

 Set-Mailbox "Kim Akers" -ProhibitSendQuota 200MB -UseDatabaseQuotaDefaults $False


Tip of the day #64:

Want to create a new role group for your administrators? Use the New-RoleGroup cmdlet. The New-RoleGroup cmdlet lets you
 add management roles and specify the members to add to the new role group. Those members will be granted the permission
s provided by the management roles. Type:

 New-RoleGroup <role group name> -Roles <role 1>, <role 2>, <role 3...> -Members <member 1>, <member 2>, <member3...>

Remember, role groups are used to grant permissions to groups of administrators or specialist end users who require spec
ial permissions. If you want to manage permissions for end users, use management role assignment policies.


Tip of the day #65:

Do you want to create a new management role assignment policy that's based on an existing policy, but you don't want to
include all the management roles? Use the Get-ManagementRoleAssignment cmdlet and pipe the results to the Where cmdlet.
The Where cmdlet excludes any role assignments that contain the roles you specify. The remaining role assignments are pi
ped to the New-ManagementRoleAssignment cmdlet. Type:

New-RoleAssignmentPolicy <new role assignment policy name>
Get-ManagementRoleAssignment -RoleAssignee <old role assignment policy name> | Where { ($_.Role -NE "<role name 1>") -An
d ($_.Role -NE "<role name 2>") } | New-ManagementRoleAssignment -Policy <new role assignment policy name>
The Where statement is case-sensitive.

Then you can apply the new policy to a mailbox using the Set-Mailbox cmdlet:

Set-Mailbox <mailbox name> -RoleAssignmentPolicy <new role assignment policy name>


Tip of the day #66:

Do you want to remove a management role from a role group, role assignment policy, USG, or user but don't know the name
of the management role assignment? Just find the role assignment with the Get-ManagementRoleAssignment cmdlet and pipe t
he results to the Remove-ManagementRoleAssignment cmdlet. Type:

Get-ManagementRoleAssignment -RoleAssignee <role assignee name> -Role <role name> | Remove-ManagementRoleAssignment


Tip of the day #67:

Exchange 2013 uses management role groups and management role assignment policies to manage permissions.
Role groups enable you to grant permissions to groups of administrators and specialist end users. These are people who m
anage your organization or perform special tasks, like mailbox searches for compliance reasons.
Role assignment policies enable you to grant permissions to your end users. These permissions include whether users can
manage their own distribution groups, edit their own profile information, access voice mail, and more.


Tip of the day #68:

Exchange 2013 uses management role groups and management role assignment policies to manage permissions.
Role groups enable you to grant permissions to groups of administrators and specialist end users. These are people who m
anage your organization or perform special tasks, like mailbox searches for compliance reasons.
Role assignment policies enable you to grant permissions to your end users. These permissions include whether users can
manage their own distribution groups, edit their own profile information, access voice mail, and more.


Tip of the day #69:

Exchange 2013 uses management role groups and management role assignment policies to manage permissions.
Role groups enable you to grant permissions to groups of administrators and specialist end users. These are people who m
anage your organization or perform special tasks, like mailbox searches for compliance reasons.
Role assignment policies enable you to grant permissions to your end users. These permissions include whether users can
manage their own distribution groups, edit their own profile information, access voice mail, and more.


Tip of the day #70:

Exchange 2013 uses management role groups and management role assignment policies to manage permissions.
Role groups enable you to grant permissions to groups of administrators and specialist end users. These are people who m
anage your organization or perform special tasks, like mailbox searches for compliance reasons.
Role assignment policies enable you to grant permissions to your end users. These permissions include whether users can
manage their own distribution groups, edit their own profile information, access voice mail, and more.


Tip of the day #71:

Management role groups enable you to grant permissions to groups of administrators and specialist end users. These are p
eople who manage your organization or perform special tasks, like mailbox searches for compliance reasons.
If you want to manage permissions for end users, use management role assignment policies.


Tip of the day #72:

Management role assignment policies enable you to grant permissions to your end users. These permissions include whether
 users can manage their own distribution groups, edit their own profile information, access voice mail, and more.
If you want to manage permissions for administrators and specialist users, use management role groups.


Tip of the day #73:

Management role assignments determine what management roles are associated with management role groups and management ro
le assignment policies. Role assignments also control what objects users who are members of role groups or assignment po
licies can modify using the cmdlets available on the associated management roles.


Tip of the day #74:

The Get-RoleGroupMember cmdlet lists all the members on a management role group. But if you want to get more details abo
ut the members of the role group, use the Get-ManagementRoleAssignment cmdlet. The Get-ManagementRoleAssignment cmdlet e
nables you to view the members of universal security groups that are members of role groups, view the management scope t
hat applies, and more.


Tip of the day #75:

Do you need to store a value in a variable in a script and make sure it never changes? If so, make the variable a consta
nt using the New-Variable cmdlet. Constants can be set once and don't allow their values to be changed. For example, the
 following creates the $IPAddress constant with the value 10.0.0.2.

New-Variable -Option Constant -Name IPAddress -Value "10.0.0.2"


Tip of the day #76:

To get a list of all parameters available for a cmdlet, type:

(Get-Command <Cmdlet Name>).Parameters | ft key

For example, to get all parameters for the New-TransportRule cmdlet, type:

(Get-Command New-TransportRule).Parameters | ft key


Tip of the day #77:

Did you know that you need to use the AssembleMessage script when exporting messages from a queue? For example, if you w
ant to export the message with message ID 1234 from the contoso.com queue on server Mailbox1, you need to run the follow
ing command:

Export-Message -Identity Mailbox1\contoso.com\1234 | AssembleMessage -Path "C:\ExportedMessages\Message1234.eml"


Tip of the day #78:

Wondering how many log files are generated per server every minute? Quickly find out by typing:

Get-MailboxDatabase -Server <Mailbox Server Name> | ?{ %{$_.DatabaseCopies | ?{$_.ReplayLagTime -ne [TimeSpan]::Zero -An
d $_.HostServerName -eq $env:ComputerName} } } | %{ $count = 0; $MinT = [DateTime]::MaxValue; $MaxT = [DateTime]::MinVal
ue; Get-ChildItem -Path $_.LogFolderPath -Filter "*????.log" | %{ $count = $count + 1; if($_.LastWriteTime -gt $MaxT){ $
MaxT = $_.LastWriteTime}; if($_.LastWriteTime -lt $MinT){ $MinT= $_.LastWriteTime} }; ($count / ($MaxT.Subtract($MinT)).
TotalMinutes) } | Measure-Object -Min -Max -Ave


Tip of the day #79:

Wondering how many log files are generated per database every minute? Quickly find out by typing:

Get-MailboxDatabase -Server <Mailbox Server Name> | %{ Get-ChildItem -Path $_.LogFolderPath -Filter "*????.log" | Group-
Object -Property {$_.LastWriteTime.Day,$_.LastWriteTime.Hour,$_.LastWriteTime.minute} | ?{$_.Count -gt 1} | Measure-Obje
ct -Property Count -Min -Max -Ave }


Tip of the day #80:

Get quick health and status information for your mailbox database copies by typing:

Get-DatabaseAvailabilityGroup DAG1 | %{ $_.Servers | %{ Get-MailboxDatabaseCopyStatus -Server $_ } }


Tip of the day #81:

Did you know that you can share your calendar and contacts folders with other federated Exchange 2013 organizations by f
irst creating a federation trust with the Microsoft Federation Gateway with a valid digital certificate? Just use the Ne
w-FederationTrust cmdlet and the certificate thumbprint to get started. Type:

New-FederationTrust -Name "Microsoft Federation Gateway" -Thumbprint <cetificate thumbprint>

Finish by setting up an organization relationship with another federated Exchange organization to share limited calendar
 free/busy information. Type:

Get-FederationInformation -DomainName <other domain name> | New-OrganizationRelationship -Name "<name of relationship>"
-FreeBusyAccessEnabled $true -FreeBusyAccessLevel -LimitedDetails


Tip of the day #82:

Need to quickly get a list of your Exchange certificates and their thumbprints? Just use the Get-ExchangeCertificate cmd
let. Type:

Get-ExchangeCertificate | fl

Want to filter the list and include just the self-signed certificates? No problem! Type:

Get-ExchangeCertificate | where {$_.IsSelfSigned -eq $true} | fl


Tip of the day #83:

Not sure your federation trust with the Microsoft Federation Gateway is working correctly? To test if a security token c
an be retrieved, just type:

Test-FederationTrust


Tip of the day #84:

Need a report on the status of each Exchange certificate installed on all Mailbox and Client Access servers? Try this:

Test-FederationTrustCertificate


Tip of the day #85:

Need to verify that an organization relationship is correctly configured and functioning as expected for a user in an ex
ternal Exchange organization? Just type:

Test-OrganizationRelationship -UserIdentity <user email address> -Identity <external domain> -Confirm


Tip of the day #86:

Use this command to get all active mailbox move requests on a mailbox server:

$(Get-MailboxDatabaseCopyStatus -Server MBX | ?{ $_.status -eq "Mounted" }) | %{ Get-MoveRequest -TargetDatabase $_.Data
baseName } | ?{ $_.Status -ne "Completed" -and $_.Status -ne "CompletedWithWarning" }


Tip of the day #87:

Use this command to find all non-completed move requests and group them by target database:

Get-MoveRequest | ?{ $_.Status -ne "Completed" -and $_.Status -ne "CompletedWithWarning" } | group targetdatabase | sort
 Count -Descending


Tip of the day #88:

Use this command to find failure messages for all failed moves:

Get-MoveRequest -MoveStatus Failed | Get-MoveRequestStatistics | ft Alias, percentcomplete, message -auto


Tip of the day #89:

Use these commands to get a snapshot of the move throughput for completed moves.

$stats = Get-MoveRequest -MoveStatus Completed | Get-MoveRequestStatistics
$stats | sort totalmailboxsize | ft Alias,{$_.totalmailboxsize.ToMB()},totalinprogressduration -auto


Tip of the day #90:

Use this command to view how many move requests are in the queue to be moved:

(Get-MoveRequest -MoveStatus Queued).count


Tip of the day #91:

Use this command to find all mailbox move requests for mailboxes on the active mailbox database copies that are hosted o
n the specified mailbox server. This command returns the display name, status of the move request, and the database to w
hich the mailbox is being moved.

$(Get-MailboxDatabaseCopyStatus -Server MBX01 | ?{ $_.status -eq "Mounted" }) | %{ Get-MoveRequest -TargetDatabase $_.Da
tabaseName }


Tip of the day #92:

Need to see a list of the URLs for a user's calendar that has been published for Internet access? Just type:

Get-MailboxCalendarFolder -Identity <user alias>:\calendar | fl


Tip of the day #93:

Did you know that you can download and integrate the latest version of Help for all cmdlets on the local Exchange server
? Type:

Update-ExchangeHelp

You need to run this command on each Exchange server to get updated Help.

22 October 2015

How to Microsoft LAPS Local Administrator Password Solution

This is something I implemented at our company.
It's pretty straight forward, if you get the access rights right.

Microsoft is offering the Local Administrator Password Solution (LAPS) that provides a solution to the issue of using a common local account with an identical password on every computer in a domain. LAPS resolves this issue by setting a different, random password for the common local administrator account on every computer in the domain. Domain administrators using the solution can determine which users, such as help-desk administrators, are authorized to read passwords.
Compromised identical local account credentials could allow elevation of privilege if an attacker uses them to elevate from a local user/administrator to a domain/enterprise administrator. Local administrator credentials are needed for occasions when logon is required without domain access. In large environments, password management can become complex, leading to poor security practices, and such environments greatly increase the risk of a Pass-the-Hash (PtH) credential replay attack.
LAPS simplifies password management while helping customers implement recommended defenses against cyber-attacks. In particular, the solution mitigates the risk of lateral escalation that results when customers use the same administrative local account and password combination on their computers.

This part came from PeteNetLive, and worked like a charm:

Download LAPS from here


Install Laps on a DC with all the options. (if you apply the defaults it will only install the GPO Extensions), which is what you would want on the 'controlled machines'.


Install the LAPS software to the target machines, in fact it's just a copy of some files.

msiexec /i \\Server\Share\laps.x64.msi /quiet

or
msiexec /i c:\laps.x64.msi /quiet

Extend Active Directory Schema:

On the management machine run the following two PowerShell commands, to add the two new attributes to Active Directory.

Import-Module AdmPwd.PS
Update-AdmPwdADSchema 




Check/Set Permissions to Read Local Admin Passwords

grant the rights to the computers themselves to be able to update the password in Active Directory. (If you have nested OU's, simply apply on the top level OU). Change the value in red to suit your own OU/OU's.

Set-AdmPwdComputerSelfPermissions -OrgUnit 'Domain Computers'




To see who has rights to view the passwords in AD (for a given OU), use the following command. Below you can see the default of SYSTEM and Domain Admins is displayed.

Find-AdmPwdExtendedRights -Identity 'Domain Computers'



To grant read password permissions to a particular group, use the following syntax, below I have an AD group called HelpDesk setup and I'm adding them into the AD ACL to be able to read local administrator passwords for the Domain Computers OU.

Set-AdmPwdReadPasswordPermissions -Orgunit 'Domain Computers' -AllowedPrinciples PeteNetLive\HelpDesk

Note: If you have multiple groups you can separate/delimit them with a comma.

Deploy the GPO Extensions to 'Controlled' Machines

On the management machine, create a new GPO object, and link it to the OU containing the computers/servers you want to apply the password settings to.


Edit the GPO.



Navigate to:
      
Computer Configuration > Policies > Administrative Templates > LAPS


The policy that turns LAPS on is the last one 'Enable local admin password management' > Enable it.



The actual complexity and age of the password is set in the 'Password Settings' policy, > Enable it and accept the defaults.
Note: the other two policies are;
Name of the administrator account to manage: Use if you you have manually created another common admin account on all your machines NOT if you have renamed the local administrator account.
Do not allow password expiration time longer than required by policy: Set to Enabled.


View the Local Admin Passwords for Controlled Machines.

1. You can do this from PowerShell with the following command;
Get-AdmPwdPassword -ComputerName hostname


Or if you have installed the Fat client, you can launch that from;
C:\Program Files\LAPS\AdmPwdUI.exe



Or as it's an AD object attribute, you can view it on the Computers AD object.




Source 1
Source 2