Private/New-AGLowPrivUser.ps1

function New-AGLowPrivUser {
    <#
    .SYNOPSIS
        Creates the low privileged lab user in the Users container.
 
    .DESCRIPTION
        Internal helper. Creates an enabled, plain domain user (Domain Users
        only) and tags its description with the ADCSGoat marker so
        Uninstall-ADCSGoat can tell it apart from a pre-existing account.
        An existing account is left untouched: its password is never reset.
 
    .PARAMETER UserName
        The sAMAccountName of the user.
 
    .PARAMETER Password
        The initial password.
 
    .PARAMETER Server
        The domain controller to write to.
 
    .OUTPUTS
        System.Boolean. $true when the user was created, $false when it already existed.
 
    .EXAMPLE
        New-AGLowPrivUser -UserName user -Password $securePassword -Server dc.adcs.goat
    #>

    [CmdletBinding(SupportsShouldProcess)]
    [OutputType([bool])]
    param (
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$UserName,

        [Parameter(Mandatory)]
        [securestring]$Password,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$Server
    )

    Add-Type -AssemblyName System.DirectoryServices

    $serverPrefix = if ($Server) { "LDAP://$Server/" } else { 'LDAP://' }
    $rootDSE = New-Object System.DirectoryServices.DirectoryEntry("${serverPrefix}RootDSE")
    $defaultNC = "$($rootDSE.defaultNamingContext)"
    $domainDnsName = ($defaultNC -replace ',?DC=', '.').TrimStart('.')

    $searcher = New-Object System.DirectoryServices.DirectorySearcher
    $searcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry("$serverPrefix$defaultNC")
    $searcher.Filter = "(&(objectCategory=person)(objectClass=user)(sAMAccountName=$UserName))"
    if ($null -ne $searcher.FindOne()) {
        Write-Warning "User '$UserName' already exists; leaving it unchanged."
        return $false
    }

    if (-not $PSCmdlet.ShouldProcess($UserName, 'Create low privileged domain user')) { return $false }

    $container = New-Object System.DirectoryServices.DirectoryEntry("${serverPrefix}CN=Users,$defaultNC")
    $user = $container.Children.Add("CN=$UserName", 'user')
    $user.Properties['sAMAccountName'].Value = $UserName
    $user.Properties['userPrincipalName'].Value = "$UserName@$domainDnsName"
    $user.Properties['description'].Value = 'Generated by ADCSGoat'
    $user.CommitChanges()

    try {
        $plainPassword = [System.Net.NetworkCredential]::new('', $Password).Password
        $null = $user.Invoke('SetPassword', $plainPassword)
        # NORMAL_ACCOUNT, enabled; the account is created disabled until a password is set.
        $user.Properties['userAccountControl'].Value = 512
        $user.CommitChanges()
    } catch {
        $user.DeleteTree()
        throw
    }

    $true
}