Building Highly-Available Windows Infrastructure: Command-line Style. AD DS. Part 3 — Management Infrastructure

Previous part — Building Highly-Available Windows Infrastructure: Command-line Style. AD DS. Part 2 — Post-Config


Sorry it took me so long — a lot has happened in the last six months, including moving into another country and changing jobs. Also, as you can see from several previous posts, I got a little bit carried away with PowerShell.
Another thing with which I got carried away is this post: I even had to split it, eventually. That’s why today, I present you not one, but two blogs at once! Find the next one here: Building Highly-Available Windows Infrastructure: Command-line Style. AD DS. Part 4 — AGPM

Up to this point, we were working on our servers interactively, locally. This is considered not the best practice because you consume server resources to support an interactive logon session. Also it might be inconvenient when you manage a fleet of servers.
In this article we will setup remote management administrative stations, which we will use to manage servers in the lab from then on.

Variables used in the article:

As we discussed in the previous article, proper privilege separation is very important — this is why you should use separate administrative accounts and administrative workstations for infrastructure management.

We shall create 3 administrative accounts — at least one for each security tier. We also need administrative workstations, by the number of the security tiers as well. You should not mix privileged credentials between tiers, that’s why we will be using a separate workstation to manage each of the tiers.


Administrative workstation is a computer which is used purely for system administration tasks. For security reasons, you should NOT browse the Internet / read mail at the same machine, from which you manage your systems. Otherwise, if you catch a malware while browsing, it may affect your servers and steal privileged credentials, such as Domain Admin password.


Administrative accounts should not be shared among the administrators: Each administrator must have their own account for each tier he/she manages. But it is completely normal to have shared administrative workstations within a single tier. Some companies prefer server-hosted virtual machines (VDI) for that purpose.



Writing this part, I found my previous statement, that Tier 0 OU does not need sub-OUs, premature. Given the number of objects we are about to create in this part and the next one, it would be better to create sub-OU structure in Tier 0 as well. Here’s the code for it:

Also note, that the structure of $TierOU hashtable has slightly changed: CompOUName property has been renamed to ComputerOUName, UserOUName to AccountOUName and I added a new property — OUPath.

Creating administrative accounts

First, we shall create user accounts. The name of an administrative account usually is built by a template which consists of an identifier shared by all administrative accounts + personal identifier which points to an administrator, using that account, + a tier identifier. Example account name might look like this: DA-admin-kf — this is an administrative account in a Tier 0 (that tier has “DA” as an identifier (variable $TierIds.Tier0)), used by me (“kf” is my personal identifier/nickname).
Since the “-admin-“ part of the account name is the same across all administrative accounts, we can store it into a variable, so you would not need to change it multiple times, should you choose a different name convention. The name of that variable is $AdminUserNameTemplate.


Since I am the only administrator in my test infrastructure, my $AdminUserNameTemplate does not include the personal identifier part. You, on the contrary, should include it if there are several IT administrators in your company.


We pass a user name to the -Name parameter and tier’s OU full distinguished name to the -Path parameter.
We talked about string templates in the previous part. Here we use the template slightly differently: in the -Name parameters above, you cannot see any placeholders. That’s because those placeholders are in the template itself: $AdminUserNameTemplate = '{0}-admin'. Yes, you can use placeholders in strings, represented by variables — it works!


Why do we create user accounts in Tier 0? To prevent an account hijacking. Say, you assigned some other account, which not a member of a role group, a permission to manage user accounts in a tier. Should administrative accounts for this tier reside in tier’s Accounts OU, that user could’ve reset password to any of those administrative accounts, therefore escalating their privileges.

Those account, which we’ve just created, are in a disabled state, because we haven’t set any password for them yet. Therefore, we have to reset their passwords. Here’s how you do it with PowerShell:

Repeat this for other accounts.

OK, we’ve set the passwords, now we are allowed to enable the accounts:

Creating administrative groups and assigning permissions

It’s not enough just to create users, since it is unwise to assign permissions to accounts directly: we must use groups to assign permissions whenever is possible. We have 4 security tiers, therefore we need at least 4 groups. But there already is a group for the Tier 0 — Domain Admins! For other tiers, we should create separate groups. I shall call these groups “role groups”, since they describe the whole set of privileges assigned to a single account.
Role group name will look like this: ADM-Administrator-SE, where “ADM” is an identifier of administrative group objects ($AdminGroupId), “-Administrator-” — role group name template ($RoleGroupNameTemplate) and “SE” is a tier identifier.

Then, we should add administrative accounts into appropriate role groups:

The first row in the code snippet above adds our Tier 0 administrative account into the “Domain Admins” group. Why do I do it in so obscure way? Why using DomainSID and what does that “512” means anyway?
The answer is — localization. In localized operating systems, default groups might have non-English names, but their relative identifiers stay the same, rendering RID as the only reliable way to target one of the default groups. Domain Admins’ RID is always 512. To get its SID, we must take the SID of a domain and join RID of the group at the end.

Right, now we have role groups, we have populated them with admin accounts, but what good would it do if those groups have no permissions in the AD DS and, therefore, admin accounts in them have no permissions either? So let’s assign them some! Here’s how permissions should be assigned: each role group (except for Tier 0) should have the following permissions for organizational units inside its tier:

  • Computers OU – Create/Delete Computer objects, Descendant Computer objects – Full control
  • Groups OU – Create/Delete Group objects, Descendant Group objects – Full control
  • Accounts OU – Create/Delete User objects, Descendant User objects – Full control,
    Create/Delete Contact objects, Descendant Contact objects – Full control,
    Create/Delete msDS-GroupManagedServiceAccount objects, Descendant msDS-GroupManagedServiceAccount objects – Full control

Why did I chose this set of permissions for the Accounts OU? From the personal experience, I see that User and Contact objects often go together and, for msDS-GroupManagedServiceAccount — well, we will need objects of that type soon and we have to store them somewhere, right?

The best way to assign permissions to role groups is NOT to directly add those groups into DACLs, but to add them into OTHER administrative groups to which the permissions are assigned. Why? Suppose you need to delegate a part of role group permissions to an account which is not a member of the said group. Therefore, instead of modifying DACLs, you could just add that the account into an appropriate administrative group.

As you can see from the list above, there are 9 permission scopes: 3 scopes for each tier (Tier 0 permission scope is the whole domain). Each security scope should have its own security group to which we assign the permissions.


Universal group scope here is just a personal preference, because I’ve been working with multi-domain forests too long. You can use Global, if you wish, since we, in accordance to modern best practices, use single-domain AD forests.

We have already discussed how to assign Active Directory permissions with PowerShell in the previous part. Here I’m just to tell you what each GUID stands for:

  • bf967a86-0de6-11d0-a285-00aa003049e2 – Computer object class
  • bf967a9c-0de6-11d0-a285-00aa003049e2 – Group object class
  • bf967aba-0de6-11d0-a285-00aa003049e2 – User object class
  • 5cb41ed0-0e4c-11d0-a286-00aa003049e2 – Contact object class
  • 7b8b558a-93a5-4af7-adca-c017e67f1057 – Group-Managed Service Account object class

The first AddAccessRule() method in each pair, assigns a group with Create/Delete permission for a given type of objects. The second one — Full control on all descendant objects of the chosen type.

We’ve assigned permissions to Tier1-3 role groups. There is no need to assign permissions to the Tier 0, Domain Admins, group since it is done by default during AD DS installation.
The last task with the groups is to finally add role groups into security groups:

Installing administrative workstations

The name of each administrative computer consists of a workstation prefix, which helps to separate workstation accounts from the server ones, an identifier which is used to distinguish administrative workstations from common workstations and a tier identifier. Example account name may look like this: WSADMSE — this is an administrative workstation in a Tier 1, that tier’s identifier is “SE”.
As with accounts, the non-variative part of an administrative workstation name is stored into the $AdminWSNameTemplate variable.

Next, at each workstation perform the following:

  1. Install an OS. I leave the installation to you: you may use either Windows Server 2016 or Windows 10. Use the latest available ISO-image.
  2. Rename the computer using the naming scheme.
  3. Install all available updates.
  4. Install RSAT:
    • For Windows 10
      1. Download an appropriate RSAT package (You DO NOT need the one for Windows 1709). Currently, the link is
      2. Install RSAT:
        1. Copy RSAT to the machine into a temporary folder:
          $TempDirectory = New-Item -Type Directory -Name $TempDirectoryName -Path (Join-Path -Path $TempDirectoryPath -ChildPath '\')
        2. Apply the RSAT package:
          Start-Process -FilePath 'wusa.exe' -ArgumentList ('{0} /quiet' -f $(Join-Path -Path ($TempDirectory.FullName) -ChildPath 'WindowsTH-RSAT_WS2016-x64.msu')) -Wait
    • For Windows Server 2016:
      Install-WindowsFeature -Name RSAT, GPMC
  5. And remove SMB1:
    • Windows 10:
      Start-Process -FilePath 'dism.exe' -ArgumentList '/Online /Disable-Feature /FeatureName:SMB1Protocol' -Wait; Restart-Computer
    • Windows Server 2016:
      Uninstall-WindowsFeature -Name FS-SMB1 -Restart
  6. Parameter -Restart at Uninstall-WindowsFeature cmdlet means that the target computer will restart automatically, if feature un-installation requires so.

  7. Join the workstation to the domain:
    1. Use IP addresses of DC1 and DC2 to set them as DNS servers @ the network of a workstation:
      Set-DnsClientServerAddress -InterfaceAlias 'Ethernet' -ServerAddresses @($DC1IPAddress, $DC2IPAddress)
    2. Then join the computer to the domain:
      Add-Computer -DomainName $Domain.DNSRoot -Credential (Get-Credential) -Restart

You should NEVER, EVER set at network interfaces DNS servers which are not authoritative for your AD DS domain zone. Usually it means usage of domain controllers addresses only.
In some networks, domain controllers do not host DNS service and separate UNIX-servers process all requests for the zone — in this case, you should use only those UNIX-servers as DNS servers.


In this article we created four administrative accounts which we will be using later to manage the infrastructure (yes, it is time to abandon the build-in Administrator account).
We assigned permissions to those accounts and installed a separate administrative workstation for each of them. But those accounts are still do not have any special permissions on the workstations: they cannot even login via RDP. What’s worse, an account from a higher-privileged tier can login to a workstation in lower-privileged tier, which is unacceptable.

To enforce security restrictions and protocols, IT administrators often use Group Policies. By default, changes in Group Policies are not logged, which makes it troublesome to audit who, when, and why changed one or another setting. Also, Group Policies is a very powerful, if not dangerous, tool: one miss-click can disrupt your entire infrastructure.
There is a solution which helps us to manage those issues better — please continue to the next part in the series where we talk about Advanced Group Policy Management.

One thought on “Building Highly-Available Windows Infrastructure: Command-line Style. AD DS. Part 3 — Management Infrastructure”

Leave a Reply

Your email address will not be published. Required fields are marked *