Cody White's Tech Blog
OSD Cloud - Repository Build
OS Deployment

OSD Cloud - Repository Build

Cody White
Cody White

April 02, 2020 · 1 min

Repository Build Project

Building an OSD Cloud deployment that is dynamic to a Git repository. What we are going to do is setup a OSD Cloud image that pulls all of its “Task Sequences” from a GitHub or GitLab repository. Building the image in this way allows us to build a single WIM/ISO and load it into our PXE or USB devices once for our labs. We are then able to control how our labs interact with the deployment tasks that we create. This allows a much more dynamic experience for zero touch deployments. As I would say set it and forget it.

Setting up our work environment

First thing we need to do is setup our work environment. We will be following the basic setup that was documented and provided in the OSD Cloud Documentation. Be sure to check OSDCloud Setup for the most up to date instructions.

Prerequisites

Before we can start using OSDCloud we need to download and install the ADK and the ADK PE Image from Microsoft. The latest versions can be located here. There are some cavitates that need to be stated here and now. Running the windows 11 WinRE vs Windows 10 WinPE image have some differences around VM Support. Be sure that you are using the image that best suits your needs. More details at [TBD]

Install.ps1
$VerbosePreference = "Continue"
$DebugPreference = "Continue"

$appID = $args[0]

$logPath = "$env:ProgramData\Microsoft\IntuneManagementExtension\CustomLogging\Install"
$logSettingsPath = "$env:ProgramData\Microsoft\IntuneManagementExtension\CustomLogging"

$logFile = "$($(Get-Date -Format "yyyy-MM-dd hh.mm.ssK").Replace(":",".")) - $appID.log"
$settingsFile = "settings.json"

$errorVar = $null
$installResult = $null

$debug = $false

IF (Test-Path -Path $logSettingsPath\$settingsFile) {
	$intuneSettings = Get-Content -Raw -Path $logSettingsPath\$settingsFile | ConvertFrom-Json
	$debug = [bool]$intuneSettings.Settings.InstallDebug
}
ELSE {
	$BaseSettings = '{
		"Settings":
		{
			"DetectionDebug": 0,
			"InstallDebug": 0,
			"UninstallDebug": 0
		}
	}'
	New-Item -Path $logSettingsPath\$settingsFile -Force
	Set-Content -Path $logSettingsPath\$settingsFile -Value $BaseSettings
}

IF ($debug) {
	IF (!(Test-Path -Path $logPath)) {
		New-Item -Path $logPath -ItemType Directory -Force
	}
	Start-Transcript -Path "$logPath\$logFile"
}

try {
	IF ([System.Environment]::Is64BitOperatingSystem) {
		$ProgramFiles = "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe"
	}
	ELSE {
		$ProgramFiles = "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x86__8wekyb3d8bbwe"		
	}

	IF ($([Security.Principal.WindowsIdentity]::GetCurrent().IsSystem) -eq $True) {
		Write-Verbose "Starting install for $appID in System Context"
		Push-Location $ProgramFiles -ErrorAction SilentlyContinue
		$AppInstallerPath = "$(Get-Location)\AppInstallerCLI.exe"
		$WinGetPath = "$(Get-Location)\winget.exe"		
		$AppFilePath = (Resolve-Path $AppInstallerPath, $WinGetPath -ErrorAction SilentlyContinue).Path
		IF ($AppFilePath) {
			$argumentList = [System.Collections.ArrayList]@("install", "--silent", "--accept-package-agreements", "--accept-source-agreements", "--scope machine", "--exact $appID")  
			$cliCommand = '& "' + $($appFilePath) + '" ' + $argumentList
			$installResult = Invoke-Expression $cliCommand | Out-String
			Write-Verbose $installResult
		}
		else {
			Write-Verbose "WinGet not Installed"
			Exit 1
		}
	}
	ELSE {
		IF ($([Security.Principal.WindowsIdentity]::GetCurrent().Groups) -match "S-1-5-32-544") {
			#Running as Admin
			Write-Error  "Script is running in Administrator Context not System or User Context - Unsupported configuration"
			Exit 1 
		}
		ELSE {
			#Running as Users
			Write-Verbose "Starting install for $appID in User Context"
			$WinGetVer = Invoke-Expression '& WinGet -v'
			IF ($WinGetVer -ge "V1.0.0") {
				$argumentList = [System.Collections.ArrayList]@("install", "--silent", "--accept-package-agreements", "--accept-source-agreements", "--scope user", "--exact $appID")  
				$cliCommand = '& "WinGet" ' + $argumentList
				$installResult = Invoke-Expression $cliCommand | Out-String
				Write-Verbose $installResult
			}
			else {
				Write-Verbose "WinGet not Installed"
				Exit 1
			}
		}
	}	
}
Catch {
	$errorVar = $_.Exception.Message
}
Finally {
	IF ($errorVar) {
		Write-Verbose "Script Errored"
		Write-Error  $errorVar
	}
	else {
		Write-Verbose "Script Completed"
	}   

	IF ($debug) { Stop-Transcript }
	$VerbosePreference = "SilentlyContinue"
	$DebugPreference = "SilentlyContinue"

	IF ($errorVar) {
		throw $errorVar 
	}
}

To Be Continued…

Cody White

IT Supervisor & Security Specialist

Expertise

  • Networking
  • Security
  • Infrastructure Development