Posts

Showing posts from 2017

Microsoft Exchange Server and .Net Framework Compatibility

Microsoft Exchange is a product that relies on the .NET Framework heavily. The Exchange Server Supportability Matrix describes the .NET requirements for each Exchange Server version among other requirements and compatibility with other software.

When updating Exchange, you have to check if your current .NET version is supported and if not upgrade it. Moreover, there might be post installation steps - e.g. security update installation - that you have to take.

In case you're skipping a few CU levels, you might not be able to update directly to the desired CU level. For example, if you are currently on CU 12 and want to update to CU 17, you have to update to CU 15, update the .NET Framework to version 4.6.2 that is supported by CU 15 and CU 16 and later and then update to CU 17.

Another task regarding the .NET Framework is to block the installation of feature versions that are not supported by your Exchange version. This is accomplished by updating the registry, usually using a group…

Active Directory Group Membership Recursively

A few days ago, I published an article on how to use the "Get-ActiveDirectoryGroupMember" function to get all the objects that are members of a group recursively. With this article, I'm going to show you how to use the "Get-ActiveDirectoryMembership" function in order to get all the groups that an object is a member of  recursively.

As always, my user account will be the test subject! When I get the groups that I am a member of, the list contains only the groups that I am a direct member.
PS C:\> $user = Get-ADUser cpolydorou

PS C:\> Get-ActiveDirectoryGroupMembership -Identity $user.DistinguishedName

Name                    DistinguishedName
----                    -----------------
Domain Admins           CN=Domain A…

Creating Self Signed Root and Server Certificates

Image
Certificates are a requirement for almost all communications in order to be secure. The purpose of this article it to describe the process of creating a Root CA certificate and then a Server certificate signed by the first. This is very useful when developing or testing an application and you do not have a CA set up or budget to buy a certificate.

The following command will create a Root CA certificate in the Personal folder of the current user certificate store.
$RootCert = New-SelfSignedCertificate -DnsName "CPolydorou Root CA" ` -CertStoreLocation "Cert:\CurrentUser\My" ` -KeyLength 4096 ` -KeyUsageProperty All ` -KeyUsage CertSign,CRLSign,DigitalSignature ` -KeyExportPolicy Exportable ` -KeyAlgorithm RSA ` -FriendlyName "CPolydorou Root Certification Authority Certificate" …

Updates to the Foreach-Object-Parallel function

One of the most used functions of the CPolydorou.General module is "Foreach-Object-Parallel". This function allows us to execute PowerShell commands in parallel. This is accomplished by using new PowerShell runspaces and the most recent enhancement allows us to feed the runspaces with parameters.

First, a quick example of the ForEach-Object-Parallel function.
PS C:\> (0..5) | ForEach-Object-Parallel -MaxThreads 2 -ScriptBlock {$_; Start-Sleep -s 2}

0
1
2
3
4
5
This does not seem that much but if you execute the above command, you'll notice that the numbers appear in pairs due to the MaxThreads being set to "2".

Each object passing the pipeline is being passed to the scriptblock of the Foreach-Object-Parallel function and can be accessed using the $_ variable.

The issue here is that since the scriptblock is executed on another PowerShell runspace, all the variables of the original runspace are not available.

Let's see how the enhancement allows us to pa…

Get Active Directory Group Members Recursively

A very common scenario when assigning permissions is having nested security groups. Although this is an easier way to manage the permission delegation, is adds complexity when there's the need to determine whether a principal is granted the permission or getting a list with all the principles involved.

The CPolydorou.ActiveDirectory module now includes a function that is the solution to the problem.

The Get-ActiveDirectoryGroupMember function will return all the objects that are members of a specified Active Directory group. The "-Recurse" parameter will query Active Directory and return all the members of the group recursively.

This way, we are able to get a list of all the objects that are granted a permission without having to consider the nested groups.

Let's take a quick look at an example.

We have a group named "NestedGroup" that the user CPolydorou is a member of. This group is also a member of another group named "Group".
PS C:\> Get-Ac…

Restoring Active Directory Attributes with PowerShell - Part 3

Welcome to the third and final article of the Restoring Active Directory Attributes with PowerShell. Today we are going to create a scheduled task in order to execute a PowerShell script that will manage our Active Directory snapshots.

First, we are going to create the script that will manage the snapshots but in order to do that we have to decide on how often and how many snapshots we want to have. Personally, I go for two snapshots per day for a period of three days, nut I have these snapshots spread across multiple Domain Controllers.

The following script will create an Active Directory snapshot and then remove all the older snapshots keeping a total of 3. That way, when it is executed on a daily basis, you will have three snapshots for the last 3 three days.

# Create the new Active Directory snapshotNew-ActiveDirectorySnapshot# Get the current date$now = [DateTime]::Now # Remove snapshots older than three days from nowGet-ActiveDirectorySnapshot | Where-Object {$_.Date -lt$now…

Restoring Active Directory Attributes with PowerShell - Part 2

Image
On the first article of the series, we used the ntdsutil tool to create, mount, dismount and remove Active Directory snapshots and load the Active Directory database using the dsamain tool. Today, we are going to use a set of PowerShell functions I've created for this purpose. These functions are included in my Active Directory module since version 1.4.1.

Let's start by creating an Active Directory snapshot and then mount it on port 33389:


After taking the snapshot, I updated the first name, last name and proxy addresses attributes on my user in order to compare and later on restore them. Using the "Get-ADUser" cmdlet we can get current the values for those attributes and as well as the values from the snapshot:


As you may notice, a proxy address is missing, the first name has been updated to "Christos 1" and the last name have been updated to "Polydorou 2".

This is how easy it is to restore the attributes! First we save the production and the sna…

Restoring Active Directory Attributes with PowerShell - Part 1

Image
Active Directory Recycle Bin. Great Feature. But what happens if instead of deleting the object, some of the attributes are misconfigured? Enter Active Directory snapshot.

In the first article of the Restoring Active Directory Attributes with PowerShell we are going to talk about Active Directory snapshots and later on we are going to see how to restore attributes on objects.

So, what is an Active Directory snapshot? It's actually an VSS snapshot of the volume that the Active Directory database resides on. And how can we use that snapshot? We can use it as a backup, a way to avoid full replication when installing a Domain Controller on a remote site and may other ways but we are going to focus on mounting it and using dsamain in order to load the database and access live.

Let's see some examples on how to create such a snapshot. Of course, you need to have the appropriate rights, like domain or forest administrator. To create a snapshot, we are going to use the ntdsutil execut…

Get Exchange Mailbox Quota Status using PowerShell

Back in the old days of Microsoft Exchange, when quota was applied to a mailbox we had a way to check the status of the quota using the "Get-MailboxStatistics" cmdlet and the property "StorageLimitStatus". On the newer versions of Exchange, this property does not contain a value since it has an impact on the performance against Active Directory (read more here).

In order to overcome this issue - and since I'm often checking for the quota status - I've decided to create a PowerShell function. The function is called "Get-MailboxQuotaStatus" and it's available with my Exchange module since version 2.4.1.

What it actually does is to check if the mailbox follows the database quotas or it's own and then compare the quota values against the size of the mailbox. The objects that this function returns are consisted of the mailbox object that is returned from the "Get-Mailbox" cmdlet and the status of the quota.

The possible values for the…

Active Directory Naming Conversion using Powershell

When dealing with Exchange, most of the object Identities are in the form of CanonicalName which makes searching Active Directory difficult since Canonical Name is a calculated attribute and cannot be used in a query.

For example, the identity of a mailbox is the cn of the user:

[PS] C:\Windows\system32>$cn = (get-mailbox cpolydorou).Identity.ToString()
[PS] C:\Windows\system32>$cn
LAB.local/LAB/Users/Christos Polydorou
The newly released version of my Active Directory module (1.3.0) contains the cmdlet "Convert-ActiveDirectoryNaming" that will help with converting between the different Active Directory naming formats. The following example illustrates the usage of the cmdlet.

First, let's get the user from Active Directory in order to have the DistinguishedName, SamAccountName, CanonicalName and UserPrincipalName values.

PS C:\> $user = Get-ADUser cpolydorou -Properties DistinguishedName, SamAccountName, CanonicalName, UserPrincipalName

PS C:\> $user
Ca…

Active Directory Account Lock Events

A common issue that troubles both helpdesk teams and administrators is account locks on Active Directory. By default, when a number of failed authentication attempts is reached, the account is locked for a time period. Since there may services that depend on Active Directory, the user might have tried to login to a workstation, a web application or even forgotten to update the password on a mobile device connected to Exchange.

In order to troubleshoot the issue, the first step is to find the computer that the failed authentication attempt was performed against. Knowing the computer will most probably lead to the service and in turn the solution of the problem.

Having a user account that is currently locked is not a big deal since only a user is affected. When it comes to service accounts that my perform various tasks, thing are getting more serious.

The newest version of my Active Directory module for Powershell (version 1.2.1) includes an new function called "Get-ActiveDirectory…

Reading Configuration Files with Powershell Part 2

Following the recently published article on reading xml configuration files using PowerShell, we are going to enrich the configuration file and create custom PowerShell objects.

This time the configuration file is a bit different, we have multiple "Company" nodes that have inline properties.

<configuration><CompanyName="Company1"><GroupDN="CN=Group1,OU=Groups,OU=Company1,DC=lab,DC=local"Name="Group1"/><OUDN="OU=Users,OU=Company1,DC=lab,DC=local"/></Company><CompanyName="Company2"><GroupDN="CN=Group2,OU=Groups,OU=Company2,DC=lab,DC=local"Name="Group2"/><OUDN="OU=Users,OU=Company2,DC=lab,DC=local"/></Company></configuration>
There aren't many changes in the script, just in the variable that holds the entire configuration.

Param ( [string]$ConfigurationPath ) # Test if configuration file existsif( (Test-Path$ConfigurationPath) -ne$tr…

Reading Configuration Files with Powershell Part 1

Although there are many tools that are very helpful when it comes to automating tasks, a simple script in most cases may be the fastest and most simple solution. Instead of hardcoding the configuration options for the script within it, wouldn't it be more clean and elegant if you used a configuration file?

As an example I'm going to use the simple task of adding users to a group in Active Directory. The purpose of the script is to add users from a specific OU to a specific distribution group after applying filtering based on the SamAccountName attribute.

Since we want to be able to use the same script for different OU and group combination we have to create some kind of configuration file and what would be better that xml!

With the following xml we are specifying the name of the company, the distinguished name of the group and the OU and two exclusions.

<configuration><Company> Company1 </Company><GroupDN> CN=Group,OU=Groups,OU=Compan…

Exchange Application Impersonation Test

Exchange Application Impersonation. More and more applications are starting to take advantage of this great feature of Exchange and you as the Exchange administrator have to assign the role. Wouldn't be nice if you had a way to verify that the role has been successfully assigned?

The newest version of my Exchange module - that is 2.2.1 - includes the "Test-ExchangeImpersonation" cmdlet which will allow you to test the application impersonation role assignment.

Before diving into the examples, a few words on the impersonation. Impersonation is used when we need to give access to an account in order to perform actions on mailboxes. When the application impersonation role is assigned to a principal, that principal can act on the mailbox and perform many actions such as reading and sending mail, managing calendar and contacts, etc.

On the examples below, the principal with the impersonation permission is test.impersonation and the mailbox that is going to be impersonated wil…

Exchange Server Mailbox Auto Mapping Cmdlets

A new version of my Exchange module has been published on the PowerShell Gallery. This new version contains cmdlets to Get, Enable and Disable the mailbox auto mapping feature for a user on a shared mailbox.

A few words about auto mapping. When an exchange administrator grants permissions on a mailbox (doesn't matter if the mailbox is a user mailbox or a shared mailbox) to another recipient, the shared mailbox will be automatically added to the users Outlook client. This is the mailbox auto mapping feature which is also enabled by default.

When granting permission on a user you can disable the auto mapping by using the "-AutoMapping:$false" switch with the "Add-MailboxPermission" cmdlet, but what if the permission is already granted? Of course you could remove and re-add the permission with the switch I just mentioned but let's see a more elegant way of configuring it!

When a user is granted permission on another mailbox - let's call it shared mailbox, …

CPolydorou.Exchange PowerShell Module

Another one of my PowerShell modules has just been published. This time its the CPolydorou.Exchange module.

This module contains cmdlets that have been very useful when dealing with Microsoft Exchange. Let's go through the cmdlets very quickly.

Start-ExchangeServerMaintenanceMode
Start maintenance mode on an Exchange server.

Stop-ExchangeServerMaintenanceMode
Stop maintenance mode on an Exchange server.

Get-ExchangeServerMaintenanceMode
Get the maintenance mode status of an Exchange server.

Get-MailboxesPerServer
Get the mailbox distribution per mailbox server.

Get-MailboxesPerDatabase
Get the mailbox distribution per database.

Get-RecipientAddress
Get the proxy addresses of a recipient.

New-RecipientAddress
Add a proxy address to a recipient.

Remove-RecipientAddress
Remove a proxy address from a recipient.

Get-OWAUsers
Get the number of OWA users.

Get-RPCUsers
Get the number of RPC users.

Get-ActiveSyncUsers
Get the number of ActiveSync users.

Get-ExchangeUsers
Get the connected user statist…

Windows Server Audit Policy Reset

I run across a very strange issue a few days ago and I feel that I should share it with you since it took me some time to figure it out!

Some Exchange servers had stopped recording events in the Security log. The first thing that crossed my mind was to check the latest event in the Security log that would probably be the event regarding the audit policy change. I was correct, there were many events with id 4719 that showed that the policy had been changed. The next step would be to update the policy in order to enable auditing.

There were servers that had auditing configured according the security baseline so I backed up the auditing configuration from one of them using the command:

auditpol /backup /file:C:\Temp\Audit.txt
Next I copied the file to the server with the issue and used the command:

auditpol /restore /file:C:\Temp\Audit.txt
to restore the settings. The command completed successfully and it was time to check the new auditing settings. For this I used the command:

auditpol …

Powershell Strings and Expressions

Image
Today's topic? PowerShell, Strings, Variable Expansion and Quotes!

Let's start with the difference between the single and double quotes. When using single quotes, the dollar sign within a string doesn't get treated as a special character so the text following it does not get resolved to the corresponding variable as opposed to the double quotes. The "file" variable in the following examples holds the output object of the Get-Item cmdlet.


Variable expansion within strings... Let me start with an example. We have an object that has multiple properties and we want to create a string using the value of one of those properties. We have to use double quotes since we want the variable to be resolved but the result isn't the desired one.

This is because PowerShell will replace the variable with it's string representation and the property will be interpreted as text.


This is where the PowerShell expressions come into play. Enclosing the variable and the property …