Active Directory provisioning script

When writing PowerShell scripts for use in our Active Directory environment, I noticed that I use the same variables and information in every script. That’s all fine, but when something changes I had to update each and every script seperately. And you always forget to update 1 or 2 scripts which is annoying.
At one of my previous employers, they developed something they refered to as a provisioning script. This script not only contained these variables and information, but also a lot of commonly used functions. Among others, this script contained functions to create new user accounts and service accounts. Other scripts, outside of the provisioning script, could then ‘import’ the provisioning script using a technique called dot sourcing and be able to use the variables declared in the provisioning script as well as the functions from the provisioning script.
So when information changes, I only have to update 1 location.

In our environment we have created an Active Directory administration OU (see one of my previous posts) which contain the admin accounts and service accounts.
The provisioning script declares all of the OU locations for items like admin accounts, service accounts, profile groups, role groups, etc. Function GetDomainConfig is used to declare these variables.

Below you can find a basic version of the provisioning script.



    File Name      : ICT-Provisioning.ps1
    Author         : Dennis Kool
    Prerequisites  : PowerShell V3, PSModule ActiveDirectory

# ---------------------------------------------------------------------------------------------------------------

#Region 0 - Global PowerShell settings

$ErrorActionPreference = 'Stop'

#EndRegion 0 -  Global PowerShell settings

# ---------------------------------------------------------------------------------------------------------------

#Region 1 - Generic functions

Function MyLogger {
        [Parameter(Mandatory = $True)]
        [String] $Message

    $TimeStamp = Get-Date -Format "dd-MMM-yyyy HH:mm:ss"

    Write-Host -NoNewline -ForegroundColor White "[$timestamp]"
    Write-Host -ForegroundColor Green " $message"

Function MyLoggerError {
        [Parameter(Mandatory = $True)] [String] $Message

    $TimeStamp = Get-Date -Format "dd-MMM-yyyy HH:mm:ss"

    Write-Host -NoNewline -ForegroundColor White "[$timestamp]"
    Write-Host -ForegroundColor Red -BackgroundColor Yellow " $message"

#EndRegion 1 - Generic functions

# ---------------------------------------------------------------------------------------------------------------

#Region 2 - ActiveDirectory related functions
Function GetDomainConfig {
        [Parameter(Mandatory = $True)]
            '<FQDN of AD domain 1>',
            '<FQDN of AD domain 2>',
            '<FQDN of AD domain 3>'
        [String] $Domain

    BEGIN { } # Begin

        If (-not (Get-Module -Name 'ActiveDirectory' -ErrorAction SilentlyContinue)) {
            Import-Module ActiveDirectory

        # Clear variables in case GetDomainConfig has been used before in the same PowerShell session
        $Global:DomainData = $null
        $Global:DomainDistinguishedName = $null
        $Global:DomainDNSRoot = $null
        $Global:DomainDC = $null
        $Global:DomainNetBIOSName = $null
        $Global:DomainNetlogonDir = $null
        $Global:AdminAccountsOU = $null
        $Global:DisabledAdminAccountsOU = $null
        $Global:ServiceAccountsOU = $null

        # Standard RBAC OU structure
        $Global:DomainData = Get-ADDomain -Server $Domain
        $Global:DomainDistinguishedName = $Global:DomainData.DistinguishedName
        $Global:DomainDNSRoot = $Global:DomainData.DNSRoot
        $Global:DomainDC = $Global:DomainData.PDCEmulator
        $Global:DomainNetBIOSName = $Global:DomainData.NetBIOSName
        $Global:DomainNetlogonDir = "\\" + $Global:DomainDNSRoot + "\NetLogon"
        $Global:AdminAccountsOU = "OU=Admin accounts,OU=Accounts,OU=ICT-Administration," + $Global:DomainDistinguishedName
        $Global:DisabledAdminAccountsOU = "OU=_Disabled," + $Global:AdminAccountsOU
        $Global:ServiceAccountsOU = "OU=Service Accounts," + $Global:DomainDistinguishedName

        # Exceptions to standard RBAC OU structure for e.g. a specific AD domain
        #If ($Domain -eq 'FQDN of AD domain') {
        #$Global:AdminAccountsOU = "OU=Admin accounts,OU=Accounts,OU=ICT-Administration," + $Global:DomainDistinguishedName

        Write-Host -ForegroundColor Green  '$DomainAdminAccountsOU              =' $AdminAccountsOU
        Write-Host -ForegroundColor Green  '$DomainDisabledAdminAccountsOU      =' $DisabledAdminAccountsOU
        Write-Host -ForegroundColor Green  '$DomainDC                           =' $DomainDC
        Write-Host -ForegroundColor Green  '$DomainDistinghuishedName           =' $DomainDistinguishedName
        Write-Host -ForegroundColor Green  '$DomainDNSRoot                      =' $DomainDNSRoot
        Write-Host -ForegroundColor Green  '$DomainNetBIOSName                  =' $DomainNetBIOSName
        Write-Host -ForegroundColor Green  '$DomainNetlogonDir                  =' $DomainNetlogonDir
        Write-Host -ForegroundColor Green  '$LeveranciersAccountsOU             =' $LeveranciersAccountsOU
        Write-Host -ForegroundColor Green  '$DomainServiceAccountsOU            =' $ServiceAccountsOU

    } # Process

    END { } # End
} # Function GetDomainConfig

#EndRegion 2 - Active Directory related functions

# ---------------------------------------------------------------------------------------------------------------

To use the provisioning script, all you have to do is dotsource it from either a PowerShell window or from a script. Notice the dot (.) at the beginning of the line. This is very important but easily overlooked !!

. <script location\script name>

You can now run command GetDomainConfig to show you which variables are now available and what their values are. In my next post I will share with you the function I have written to create new admin accounts, which uses the information provided by function GetDomainConfig.

I hope it’s clear what a provisioning script can do for you and how to use it. If not, please leave a comment and I will try to make this post more clear.

As always, please keep in mind this script is tailored to my environment, but can be used as a template for your environment. I do not pretend to be a PowerShell guru and as such my script may not be perfect. I am open to suggestions  :-). If you found this script useful, I’d appreciate it if you leave a comment.

Leave a Reply

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