Secure a Task Sequence with a Password


Introduction

Configuration Manager has very limited built-in functionalities to protect a Task Sequence from being executed. Sure you can define the scope of a certain task sequence deployment with deploying it only to certain collections. You also can set an PXE / Media Password to protect deployed task sequences from being executed.

But there are certain situation where you might have several available Task Sequences deployed to one collection or the Machine is member of a number of collection having Task Sequences deployed. For example, if your process allows to deploy against "unknown computers" and you are having your Prod TS and your Test TS deployed to that Collection.

 

Solution

To get around this problem, I wrote a little Powershell Scripts called OSD_PasswortChecker. This Scripts creates in the WinPE at the begin of the Deployment an Password Prompt.

Entering the correct Password allows to run the rest of the Steps in the Task Sequence.

Script

 

The Function of the OSD_PasswordChecker is simple, it protects your Task Sequence with a specified Password within a Task Sequence.

Here is the code of the Script:

# Script OSD_PasswordChecker.ps1 - Version 1802
# ***** Disclaimer *****
# This file is provided "AS IS" with no warranties, confers no 
# rights, and is not supported by the authors or Microsoft 
# Corporation. Its use is subject to the terms specified in the 
# Terms of Use (http://www.microsoft.com/info/cpyright.mspx).
#

# -----------------------------------------------------------------------------------
# Function Section
# -----------------------------------------------------------------------------------
function ok-button {
 <#
 .SYNOPSIS
 Compares the entered Password with the OSDPassword 
 .DESCRIPTION
 Function to compare the Task Sequence Varibale "OSDPassword" with the entered Password
 #>

if($tsenv.Value("OSDPassword") -eq $MaskedTextBox) {
 $tsenv.Value("OSDPasswordChecked")=$True 
 }
}

# -----------------------------------------------------------------------------------
# Worker Section
# ----------------------------------------------------------------------------------- 
# Construct TSEnv object
try {
 $TSEnv = New-Object -ComObject Microsoft.SMS.TSEnvironment -ErrorAction Stop
}
catch [System.Exception] {
 Write-Warning -Message "Unable to construct Microsoft.SMS.TSEnvironment object" ; exit 1
}

#GUI Creation
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

$objForm = New-Object System.Windows.Forms.Form 
$objForm.Text = "OSD PasswordChecker"
$objForm.Size = New-Object System.Drawing.Size(300,200) 
$objForm.StartPosition = "CenterScreen"
$objForm.KeyPreview = $True

$objForm.Add_KeyDown({
 if ($_.KeyCode -eq "Enter") {
 ok-button;$objForm.Close()
 }
})
$objForm.Add_KeyDown({
 if ($_.KeyCode -eq "Escape") {
 $objForm.Close()
 }
})

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Add_Click({
 ok-button;$objForm.Close()
})
$objForm.Controls.Add($OKButton)

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({
 $objForm.Close()
})
$objForm.Controls.Add($CancelButton)

$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20) 
$objLabel.Size = New-Object System.Drawing.Size(280,20) 
$objLabel.Text = "Please enter the information in the space below:"
$objForm.Controls.Add($objLabel)

$MaskedTextBox = New-Object System.Windows.Forms.MaskedTextBox
$MaskedTextBox.PasswordChar = '*'
$MaskedTextBox.Location = New-Object System.Drawing.Size(10,40) 
$MaskedTextBox.Size = New-Object System.Drawing.Size(260,20) 
$objForm.Controls.Add($MaskedTextBox) 
$objForm.Topmost = $True
$objForm.Add_Shown({$objForm.Activate()})

[void] $objForm.ShowDialog()

You can download the Script + ServiceUI.exe (later described) here

Implementation

Please add the following steps at the beginning of your Task Sequence

 

Step: Set OSDPassword

Create a Step "Sets the Task Sequence Variable" in which you set the Task Sequence Variable "OSDPassword". The Value of this Variable will be used to check against the Input in the OSDPasswordChecker Script.

Step: Run OSDPasswordChecker

This Steps executes a Command Line to run the OSDPasswordChecker Powershell.

To create a GUI with Powershell in WinPE there are two Prerequisites needed:

  • Enable Powershell Feature in the Boot WIM
  • ServiceUI.exe needed to create a GUI in WinPE. By the way, we are using the same technique to launch the well known MDT UDI wizard.

The Command Line you need to run:

ServiceUI.exe -process:TSProgressUI.exe %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File OSDPasswordChecker.ps1

 

Deployment Start Folder

The rest of the Task Sequence should be in a separate Folder Structure. In my case "Deployment Start".

Add on this folder the following Condition:

 

 


Comments (3)

  1. Interesting one!

    Though, this might be more a compliance feature than a security feature. Nevertheless, it will mitigate unallowed installations!

    All the best,
    David

  2. BradleyJL says:

    Great post David!
    This was just what I was looking for to prevent accidental launch of our Windows 10 reimage task sequence. I did have a bit of trouble getting it to work in my environment though. It would not create the TS variable “OSDPasswordChecked” until I changed the IF statement to “if($tsenv.Value(“OSDPassword”) -eq ($MaskedTextBox).text) . Without that it seemed like it was comparing apples to oranges.
    I am kinda new at PowerShell, so I am not sure if it is just my implementation of your script that causes the need for that change.

    John

  3. BradleyJL says:

    Sorry Y.Perrenoud I am giving credit to the wrong person! It’s been a long day!

Skip to main content