Set-GroupToSecure.ps1


<#PSScriptInfo
 
.VERSION 1.0
 
.GUID 7fafd626-c029-4fcb-93f8-b42652d0635e
 
.AUTHOR Peter Remstad
 
.COMPANYNAME
 
.COPYRIGHT
 
.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.
 
 #>


Param()

############################################################################################
# Script Name: Set-GroupToSecure.ps1
# Current Version: 1.0
# Written By: Peter Remstad
# Date Created: 2020-08-11
#
# Notes: v1.0 - This script modifies the ACL on an AD Group to match AdminSDHolder. This
# will mean that inheritance is blocked and only DA/EA's can modify the
# group membership. Helps secure custom critical RBAC groups.
#
############################################################################################

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

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

# IMPORTS AD MODULE
Import-Module ActiveDirectory

# RECEIVES GROUP INPUT
$GroupName = Read-Host "Input name of group to secure"

# CHECKS WHETHER THE PROVIDED INPUT EXISTS
$ErrorActionPreference = "silentlyContinue"
$GroupCheck = Get-ADGroup -Identity $GroupName -Properties Description -Credential $Creds
$ErrorActionPreference = "Continue"

# 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 Active Directory. Terminating script."
} Else {
    Write-Host -ForegroundColor Cyan "Group $GroupName located! Proceeding with group lockdown..."

    $Domain = Get-ADDomain

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

        # 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:
    })

    $Error.Clear()

    # EXECUTES SCRIPTBLOCK SO THAT GET-ACL AND SET-ACL CAN BE RUN UNDER PROVIDED CREDENTIALS
    Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $GroupCheck,$Domain -ComputerName $env:COMPUTERNAME -Credential $Creds

    # 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!"
    }
}

# 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
}