Set-GroupToSecure.ps1


<#PSScriptInfo
 
.VERSION 2.0
 
.GUID cb08b379-374f-4ee7-8f88-3c0f57fc7c52
 
.AUTHOR Peter Remstad
 
.COMPANYNAME
 
.COPYRIGHT All rights reserved.
 
.TAGS
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
#>


<#
 
.DESCRIPTION
 Modifies an Active Directory Group's ACL to match 'ADMINSDHOLDER' to effectively lockdown the group, disabling inheritance, so only Domain Admins and Enterprise Admins can modify membership. This helps secure high risk custom RBAC groups such as a 'Server Admins' group.

NOTE - Requires ActiveDirectory module to be installed on the system executing the script. Also requires the executer of the script to have Domain Admin credentials available.
 
#>
 

Param()


# RESETS SCRIPT VARIABLES
$GroupName = $null
$TemplateACL = $null
$DomainCheck = $null
$GroupCheck = $null

# RECEIVES USER INPUTS
$DomainName = Read-Host "Input full domain name"
$GroupName = Read-Host "Input name of group to secure"

# GETS DA CREDENTIALS
$Creds = Get-Credential -Message "Input Domain Admin credentials for $DomainName."

# IMPORTS AD MODULE
If (Get-Module -ListAvailable | Where {$_.Name -eq "ActiveDirectory"}) {
    Import-Module ActiveDirectory
} Else {
    Write-Error -Message "ActiveDirectory PowerShell module not found."
    Break
}

# CHECKS WHETHER THE PROVIDED DOMAIN NAME IS REACHABLE AND IF GROUP EXISTS
$ErrorActionPreference = "silentlyContinue"
$DomainCheck = Get-ADDomain -Server $DomainName
$GroupCheck = Get-ADGroup -Identity $GroupName -Properties Description -Credential $Creds
$ErrorActionPreference = "Continue"

# THROWS ERROR IF DOMAIN IS UNREACHABLE
If ($DomainCheck -eq $null) {
    Write-Error -Message "Domain $DomainName could not be found. Please check spelling and try again."
} Else {
    Write-Host -ForegroundColor Cyan "Domain $DomainName found!"
}

# THROWS ERROR IF GROUP DOESN'T EXIST, OTHERWISE EXECUTES GROUP ACL CHANGE
If ($GroupCheck -eq $null) {
    Write-Error -Message "Group $GroupName could not be found in $DomainName. Terminating script."
} Else {
    Write-Host -ForegroundColor Cyan "Group $GroupName located in $DomainName!"
    Write-Host -ForegroundColor Cyan "Proceeding with group lockdown..."
}

# CREATES SCRIPTBLOCK FOR USE WITH INVOKE-COMMAND SO CREDENTIALS CAN BE PASSED FOR ALL INTERNAL COMMANDS
$ScriptBlock = [scriptblock]::Create({
    param (
        $Group,
        $DomainInfo
    )

    $Error.Clear()

    # IMPORTS AD MODULE AND CHANGES TO AD DRIVE
    Import-Module ActiveDirectory
    Set-Location -Path AD:

    # GETS ADMINSDHOLDER ACL
    $TemplateACL = Get-Acl -Path "CN=AdminSDHolder,CN=System,$($DomainInfo.DistinguishedName)"

    # APPLIES ACL TO TARGET GROUP AND CHANGES BACK TO C DRIVE
    Set-Acl -Path $Group.DistinguishedName -AclObject $TemplateACL -Confirm:$false
    Set-Location -Path C:

    # SETS ADMINCOUNT AND APPENDS DESCRIPTION TO GROUP
    Set-ADObject -Identity $GroupCheck.DistinguishedName -Add @{AdminCount=1} -Description "$($GroupCheck.Description)-GroupLockedDown" -Credential $Creds

    If ($Error.count -ne 0) {
        Write-Host -ForegroundColor Red "Lockdown commands returned errors. Manually validate group."
    } Else {
        Write-Host -ForegroundColor Cyan "Group lockdown completed!"
    }
})

# EXECUTES SCRIPTBLOCK SO THAT GET-ACL AND SET-ACL CAN BE RUN UNDER PROVIDED CREDENTIALS
Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $GroupCheck,$DomainCheck -ComputerName $DomainCheck.PDCEmulator -Credential $Creds

# WAITS TO CLOSE WINDOW UNTIL A KEY PRESS
If ($Host.Name -eq "ConsoleHost") {
    Write-Host ""
    Write-Host "Press any key to continue..."
    $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp") > $null
}