GPOs in PowerShell

As more and more companies are taking the serverless route to running their business, GPOs are becoming a thing of the past. While Intune can do a lot to replace GPOs, your company may not be moving to Azure AD with Intune. It might be necessary to just have a totally custom solution to run scripts to perform GPO like actions.

In this post, I'm going to go through an option to build GPO like functionality using scripts and scheduled tasks. We're going to use two types of scheduled tasks to emulate the two options for GPOs, Computer Configuration that controls computer level features and typically runs on startup and User Configuration that controls user level features and typically runs on login.

The Computer Configuration

A good use for GPOs is to install software needed by the business. Thanks to Chocolatey, it can be incredible easy. So let's create a file called ComputerConfig.ps1:

# Install Chocolatey. Literally just copied from their website
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

$cinst = Join-Path -Path $env:ProgramData -ChildPath "chocolatey\bin\cinst.exe"

if (Test-Path $cinst) {
	@("microsoft-teams", "office365proplus") `
    	| ForEach-Object { & $cinst --yes $_ }
}

The User Configuration

One of my common User Configuration GPOs is to deploy a VPN configuration to computers so that if they need to leave the office and work from home, they can tap back in. Even with clients who've gone serverless, we continue to route traffic through the office for security purposes. So here's UserConfig.ps1:

if(Get-VpnConnection -Name "Contoso" -ErrorAction SilentlyContinue) { exit }
Add-VpnConnection -Name "Contoso" -ServerAddress "vpn.contoso.com" -TunnelType L2tp -L2tpPsk "SuperSecret" -EncryptionLevel Required -AuthenticationMethod Pap -RememberCredential -DnsSuffix contoso.local

Setting up our "GPOs"

Now that we have our Computer Config and User Config, let's put them into effect. First you'll need to store the files somewhere. If you have SharePoint, they can be in a SharePoint document library. Create links for them and add them into the following script:

$ComputerConfigUrl = "https://contoso.sharepoint.com/.../ComputerConfig.ps1"
$UserConfigUrl = "https://contoso.sharepoint.com/.../UserConfig.ps1"

$ConfigPath = Join-Path $env:SystemDrive "Config"
New-Item -ItemType Directory -Path $ConfigPath

Invoke-WebRequest -Uri $ComputerConfigUrl -OutFile "$ConfigPath/ComputerConfig.ps1"
Invoke-WebRequest -Uri $UserConfigUrl -OutFile "$ConfigPath/UserConfig.ps1"

This script can be loaded into your RMM and run on a scheduled basis to update the config on computers as you make changes.

Now for the scheduled tasks that will actually run the configurations.

# Setup the Computer Config
$Action = New-ScheduledTaskAction -Execute "Powershell.exe" -Argument '-NoProfile -WindowStyle Hidden -Command "C:\Config\ComputerConfig.ps1"'
$Trigger = New-ScheduledTaskTrigger -AtStartup

Register-ScheduledTask -Action $Action -Trigger $Trigger -TaskName "GPO Computer Configuration"

# Setup the User Config
$Action = New-ScheduledTaskAction -Execute "Powershell.exe" -Argument '-NoProfile -WindowStyle Hidden -Command "C:\Config\UserConfig.ps1"'
$Trigger = New-ScheduledTaskTrigger -AtLogOn

Register-ScheduledTask -Action $Action -Trigger $Trigger -TaskName "GPO Computer Configuration"

Putting it together

So here's the script to load into your RMM to deploy everything. Run it on a regular basis and it will update your User and Computer configs.

###
# Deploy/Update the Configuration Scripts
###
$ComputerConfigUrl = "https://contoso.sharepoint.com/.../ComputerConfig.ps1"
$UserConfigUrl = "https://contoso.sharepoint.com/.../UserConfig.ps1"

$ConfigPath = Join-Path $env:SystemDrive "Config"
New-Item -ItemType Directory -Path $ConfigPath

Invoke-WebRequest -Uri $ComputerConfigUrl -OutFile "$ConfigPath/ComputerConfig.ps1"
Invoke-WebRequest -Uri $UserConfigUrl -OutFile "$ConfigPath/UserConfig.ps1"

###
# Deploy the Scheduled Tasks
###
# Setup the Computer Config
$Action = New-ScheduledTaskAction -Execute "Powershell.exe" -Argument '-NoProfile -WindowStyle Hidden -Command "C:\Config\ComputerConfig.ps1"'
$Trigger = New-ScheduledTaskTrigger -AtStartup

Register-ScheduledTask -Action $Action -Trigger $Trigger -TaskName "GPO Computer Configuration"

# Setup the User Config
$Action = New-ScheduledTaskAction -Execute "Powershell.exe" -Argument '-NoProfile -WindowStyle Hidden -Command "C:\Config\UserConfig.ps1"'
$Trigger = New-ScheduledTaskTrigger -AtLogOn

Register-ScheduledTask -Action $Action -Trigger $Trigger -TaskName "GPO Computer Configuration"