mirror of
https://github.com/Grace-Solutions/Invoke-OpenSSHConfiguration.git
synced 2026-07-26 11:38:14 +00:00
344 lines
20 KiB
PowerShell
344 lines
20 KiB
PowerShell
#Requires -Version 5
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
A short synopsis of of what the script does
|
|
|
|
.DESCRIPTION
|
|
A meaningful description of what the script does
|
|
|
|
.PARAMETER TaskSequenceVariables
|
|
One or more task sequence variable(s) to retrieve during task sequence execution.
|
|
If this parameter is not specified, all task sequence variable(s) will be stored into the variable 'TSVariableTable'.
|
|
Any task sequence variables that are new or have been updated will be saved back to the task sequence engine for futher usage.
|
|
|
|
$TSVariable.MyCustomVariableName = "MyCustomVariableValue"
|
|
$TSVariable.Make = "MyDeviceModel"
|
|
|
|
.PARAMETER LogDir
|
|
A valid folder path. If the folder does not exist, it will be created. This parameter can also be specified by the alias "LogPath".
|
|
|
|
.PARAMETER ContinueOnError
|
|
Ignore failures.
|
|
|
|
.EXAMPLE
|
|
Use this command to execute a VBSCript that will launch this powershell script automatically with the specified parameters. This is useful to avoid powershell execution complexities.
|
|
|
|
cscript.exe /nologo "%FolderPathContainingScript%\%ScriptName%.vbs" /SwitchParameter /ScriptParameter:"%ScriptParameterValue%" /ScriptParameterArray:"%ScriptParameterValue1%,%ScriptParameterValue2%"
|
|
|
|
wscript.exe /nologo "%FolderPathContainingScript%\%ScriptName%.vbs" /SwitchParameter /ScriptParameter:"%ScriptParameterValue%" /ScriptParameterArray:"%ScriptParameterValue1%,%ScriptParameterValue2%"
|
|
|
|
.EXAMPLE
|
|
powershell.exe -ExecutionPolicy Bypass -NoProfile -NoLogo -File "%FolderPathContainingScript%\%ScriptName%.ps1" -SwitchParameter -ScriptParameter "%ScriptParameterValue%"
|
|
|
|
.EXAMPLE
|
|
powershell.exe -ExecutionPolicy Bypass -NonInteractive -NoProfile -NoLogo -WindowStyle Hidden -Command "& '%FolderPathContainingScript%\%ScriptName%.ps1' -ScriptParameter1 '%ScriptParameter1Value%' -ScriptParameter2 %ScriptParameter2Value% -SwitchParameter"
|
|
|
|
.NOTES
|
|
Any useful tidbits
|
|
|
|
.LINK
|
|
A useful link
|
|
#>
|
|
|
|
[CmdletBinding(SupportsShouldProcess=$True)]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$False)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Alias('TSVars', 'TSVs')]
|
|
[String[]]$TaskSequenceVariables,
|
|
|
|
[Parameter(Mandatory=$False)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Alias('TSVD', 'TSVDL')]
|
|
[String[]]$TSVariableDecodeList,
|
|
|
|
[Parameter(Mandatory=$False)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Alias('LogDir', 'LogPath')]
|
|
[System.IO.DirectoryInfo]$LogDirectory,
|
|
|
|
[Parameter(Mandatory=$False)]
|
|
[Switch]$ContinueOnError
|
|
)
|
|
|
|
Function Test-ProcessElevationStatus
|
|
{
|
|
$Identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
|
|
$Principal = New-Object -TypeName 'System.Security.Principal.WindowsPrincipal' -ArgumentList ($Identity)
|
|
$Result = $Principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
|
|
|
|
Write-Output -InputObject ($Result)
|
|
}
|
|
|
|
Switch (Test-ProcessElevationStatus)
|
|
{
|
|
Default
|
|
{
|
|
Try
|
|
{
|
|
#region Define Default Action Preferences
|
|
$Script:InformationPreference = 'Continue'
|
|
$Script:DebugPreference = 'SilentlyContinue'
|
|
$Script:ErrorActionPreference = 'Stop'
|
|
$Script:VerbosePreference = 'SilentlyContinue'
|
|
$Script:WarningPreference = 'Continue'
|
|
$Script:ConfirmPreference = 'None'
|
|
$Script:WhatIfPreference = $False
|
|
#endregion
|
|
|
|
#region Set the default exit code for the script (By default, the script will exit with an exit code of 0)
|
|
[System.Environment]::ExitCode = 0
|
|
#endregion
|
|
|
|
#region Initialize Toolkit (This operation loads functions, modules, and variables into the current session, so if you do not see a variable defined below, it is because it is defined in the Toolkit)
|
|
Try
|
|
{
|
|
[System.IO.FileInfo]$ToolkitScriptPath = "$([System.IO.Path]::GetDirectoryName($MyInvocation.MyCommand.Definition))\Toolkit\Toolkit.ps1"
|
|
|
|
. "$($ToolkitScriptPath.FullName)" -CallingScriptInvocationInfo ($MyInvocation) -CallingScriptParameterSetName ($PSCmdlet.ParameterSetName)
|
|
}
|
|
Catch
|
|
{
|
|
[System.Environment]::ExitCode = 6000
|
|
|
|
Throw
|
|
}
|
|
#endregion
|
|
|
|
#region Set default parameter values
|
|
Switch ($True)
|
|
{
|
|
{([System.String]::IsNullOrEmpty($ExampleVariable) -eq $True) -or ([System.String]::IsNullOrWhiteSpace($ExampleVariable) -eq $True)}
|
|
{
|
|
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Perform Script Actions
|
|
$WindowsCapabilityInclusionExpression = 'OpenSSH.*'
|
|
|
|
$WriteLogMessage.Invoke(0, @("Attempting to retreive the list of Windows capabilities matching expression `"$($WindowsCapabilityInclusionExpression)`". Please Wait..."))
|
|
|
|
$WindowsCapabilityList = Get-WindowsCapability -Online -Name ($WindowsCapabilityInclusionExpression)
|
|
|
|
$WindowsCapabilityListCount = ($WindowsCapabilityList | Measure-Object).Count
|
|
|
|
$WriteLogMessage.Invoke(0, @("Located $($WindowsCapabilityListCount) Windows capabilities matching the specified expression."))
|
|
|
|
Switch ($WindowsCapabilityListCount -gt 0)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$WindowsCapabilityListCounter = 1
|
|
|
|
For ($WindowsCapabilityListIndex = 0; $WindowsCapabilityListIndex -lt $WindowsCapabilityListCount; $WindowsCapabilityListIndex++)
|
|
{
|
|
$WindowsCapabilityListItem = $WindowsCapabilityList[$WindowsCapabilityListIndex]
|
|
|
|
$WriteLogMessage.Invoke(0, @("Attempting to process windows capability $($WindowsCapabilityListCounter) of $($WindowsCapabilityListCount). Please Wait..."))
|
|
|
|
$WriteLogMessage.Invoke(0, @("DisplayName: $($WindowsCapabilityListItem.DisplayName)", "Name: $($WindowsCapabilityListItem.Name)", "State: $($WindowsCapabilityListItem.State)", "Description: $($WindowsCapabilityListItem.Description)"))
|
|
|
|
Switch ($WindowsCapabilityListItem.State -iin @('Installed'))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
Try
|
|
{
|
|
$WriteLogMessage.Invoke(0, @("Attempting to remove windows capability $($WindowsCapabilityListCounter) of $($WindowsCapabilityListCount). Please Wait..."))
|
|
|
|
$Null = Remove-WindowsCapability -Online -Name ($WindowsCapabilityListItem.Name)
|
|
|
|
$WriteLogMessage.Invoke(0, @("Successfully removed windows capability $($WindowsCapabilityListCounter) of $($WindowsCapabilityListCount). Please Wait..."))
|
|
}
|
|
Catch
|
|
{
|
|
$WriteLogMessage.Invoke(2, @("Failed to remove windows capability $($WindowsCapabilityListCounter) of $($WindowsCapabilityListCount)."))
|
|
}
|
|
Finally
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
Default
|
|
{
|
|
$WriteLogMessage.Invoke(0, @("Skipping operations on windows capability $($WindowsCapabilityListCounter) of $($WindowsCapabilityListCount). Please Wait..."))
|
|
}
|
|
}
|
|
|
|
$WindowsCapabilityListCounter++
|
|
}
|
|
}
|
|
}
|
|
|
|
$GetInstalledSoftwareList = {Get-InstalledSoftware -FilterExpression {($_.DisplayName -imatch '(.*Open.*SSH.*)') -and ($_.DisplayName -inotmatch '(^.{0,0}$)')} -AllProperties -AllUserProfiles}
|
|
|
|
$InstalledSoftwareList = $GetInstalledSoftwareList.Invoke()
|
|
|
|
$InstalledSoftwareListCount = ($InstalledSoftwareList | Measure-Object).Count
|
|
|
|
Switch ($InstalledSoftwareListCount -eq 0)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
#Determine the OS architecture for asset filtering (Win32, Win64, ARM64)
|
|
$OSArchitectureMap = @{
|
|
'AMD64' = 'Win64'
|
|
'x86' = 'Win32'
|
|
'ARM64' = 'ARM64'
|
|
'ARM' = 'ARM'
|
|
}
|
|
|
|
$ProcessorArchitecture = [System.Environment]::GetEnvironmentVariable('PROCESSOR_ARCHITECTURE')
|
|
|
|
$OSArchitectureFilter = $OSArchitectureMap[$ProcessorArchitecture]
|
|
|
|
#Build regex pattern to match MSI for the current architecture (e.g., "OpenSSH-Win64.*\.msi$")
|
|
$AssetPattern = "OpenSSH-$($OSArchitectureFilter).*\.msi$"
|
|
|
|
$GetGitRepositoryReleaseParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$GetGitRepositoryReleaseParameters.BaseURI = 'https://api.github.com'
|
|
$GetGitRepositoryReleaseParameters.RepositoryOwner = "PowerShell"
|
|
$GetGitRepositoryReleaseParameters.RepositoryName = "Win32-OpenSSH"
|
|
$GetGitRepositoryReleaseParameters.ReleaseTag = "latest"
|
|
$GetGitRepositoryReleaseParameters.AssetInclusionExpression = $AssetPattern
|
|
$GetGitRepositoryReleaseParameters.DestinationDirectory = [System.IO.Path]::Combine($Env:Windir, 'Temp', $CallingScriptPath.BaseName, 'Downloads')
|
|
$GetGitRepositoryReleaseParameters.Download = $True
|
|
$GetGitRepositoryReleaseParameters.Force = $False
|
|
$GetGitRepositoryReleaseParameters.ContinueOnError = $False
|
|
$GetGitRepositoryReleaseParameters.Verbose = $True
|
|
|
|
$GetGitRepositoryReleaseResult = Get-GitRepositoryRelease @GetGitRepositoryReleaseParameters
|
|
|
|
$GitRepositoryRelease = $GetGitRepositoryReleaseResult | Select-Object -First 1
|
|
|
|
$GitRepositoryReleaseAssetList = $GitRepositoryRelease.ReleaseInfo.AssetList | Where-Object {($_.DestinationPath.Extension -iin @('.msi')) -and ($_.DestinationPath.Exists -eq $True)}
|
|
|
|
$GitRepositoryReleaseAssetListCount = ($GitRepositoryReleaseAssetList | Measure-Object).Count
|
|
|
|
$GitRepositoryReleaseAssetListCounter = 1
|
|
|
|
For ($GitRepositoryReleaseAssetListIndex = 0; $GitRepositoryReleaseAssetListIndex -lt $GitRepositoryReleaseAssetListCount; $GitRepositoryReleaseAssetListIndex++)
|
|
{
|
|
$GitRepositoryReleaseAssetListItem = $GitRepositoryReleaseAssetList[$GitRepositoryReleaseAssetListIndex]
|
|
|
|
$ExecutionLogPath = [System.IO.FileInfo][System.IO.Path]::Combine($LogDirectory.FullName, "$($GitRepositoryReleaseAssetListItem.DestinationPath.BaseName).log")
|
|
|
|
$StartProcessWithOutputParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$StartProcessWithOutputParameters.FilePath = 'msiexec.exe'
|
|
#$StartProcessWithOutputParameters.WorkingDirectory = "$($Env:SystemDrive)\Users\Public\Documents"
|
|
$StartProcessWithOutputParameters.ArgumentList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
|
|
$StartProcessWithOutputParameters.ArgumentList.Add('/i')
|
|
$StartProcessWithOutputParameters.ArgumentList.Add("`"$($GitRepositoryReleaseAssetListItem.DestinationPath.FullName)`"")
|
|
$StartProcessWithOutputParameters.ArgumentList.Add('/qn')
|
|
$StartProcessWithOutputParameters.ArgumentList.Add('/norestart')
|
|
$StartProcessWithOutputParameters.ArgumentList.Add("/l*v `"$($ExecutionLogPath.FullName)`"")
|
|
$StartProcessWithOutputParameters.AcceptableExitCodeList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
|
|
$StartProcessWithOutputParameters.AcceptableExitCodeList.Add('0')
|
|
$StartProcessWithOutputParameters.AcceptableExitCodeList.Add('3010')
|
|
$StartProcessWithOutputParameters.CreateNoWindow = $True
|
|
$StartProcessWithOutputParameters.ExecutionTimeout = [System.Timespan]::FromMinutes(15)
|
|
$StartProcessWithOutputParameters.ExecutionTimeoutInterval = [System.Timespan]::FromSeconds(5)
|
|
$StartProcessWithOutputParameters.SecureArgumentList = $False
|
|
$StartProcessWithOutputParameters.LogOutput = $True
|
|
$StartProcessWithOutputParameters.ContinueOnError = $False
|
|
$StartProcessWithOutputParameters.Verbose = $True
|
|
$StartProcessWithOutputParameters.ErrorAction = [System.Management.Automation.Actionpreference]::Stop
|
|
|
|
$MSIProductInfo = Get-MSIPropertyList -Path ($GitRepositoryReleaseAssetListItem.DestinationPath.FullName)
|
|
|
|
$WriteLogMessage.Invoke(0, @("Attempting to release binary $($GitRepositoryReleaseAssetListCounter) of $($GitRepositoryReleaseAssetListCount). Please Wait...", "Manufacturer: $($MSIProductInfo.Manufacturer)", "ProductName: $($MSIProductInfo.ProductName)", "ProductVersion: $($MSIProductInfo.ProductVersion)", "Product Language: $($MSIProductInfo.ProductLanguage)"))
|
|
|
|
$StartProcessWithOutputResult = Start-ProcessWithOutput @StartProcessWithOutputParameters
|
|
|
|
$GitRepositoryReleaseAssetListCounter++
|
|
}
|
|
}
|
|
}
|
|
|
|
$InstalledSoftwareList = $GetInstalledSoftwareList.Invoke()
|
|
|
|
$InstalledSoftwareListCount = ($InstalledSoftwareList | Measure-Object).Count
|
|
|
|
Switch ($InstalledSoftwareListCount -gt 0)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
###Do configuration stuff here
|
|
#PublicKeys - New and from list idepotent
|
|
#Certs - From windows store to PEM
|
|
#Options etc
|
|
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
Catch
|
|
{
|
|
#region Perform error handling actions
|
|
$ErrorHandlingDefinition.Invoke($Error[0], 2, $ContinueOnError.IsPresent)
|
|
#endregion
|
|
}
|
|
Finally
|
|
{
|
|
#region Perform finalization actions
|
|
$FinalizationActions.Invoke()
|
|
#endregion
|
|
}
|
|
}
|
|
|
|
{($_ -eq $False)}
|
|
{
|
|
[System.IO.FileInfo]$ScriptPath = "$($MyInvocation.MyCommand.Definition)"
|
|
|
|
#$CurrentExecutionPolicy = Get-ExecutionPolicy -Scope Process
|
|
|
|
$CurrentExecutionPolicy = 'Bypass'
|
|
|
|
$ArgumentList = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
|
$ArgumentList.Add("-ExecutionPolicy $($CurrentExecutionPolicy)")
|
|
$ArgumentList.Add('-NonInteractive')
|
|
$ArgumentList.Add('-NoProfile')
|
|
$ArgumentList.Add('-NoLogo')
|
|
$ArgumentList.Add('-NoExit')
|
|
$ArgumentList.Add('-Command')
|
|
$ArgumentList.Add("`"`& {. `"$($ScriptPath.FullName)`"")
|
|
|
|
$MyInvocation.UnboundArguments.GetEnumerator() | ForEach-Object {$ArgumentList.Add("-$($_.Key) @($($_.Value | ForEach-Object {`"$($_)`"}))")}
|
|
|
|
$PSBoundParameters.GetEnumerator() | ForEach-Object {$ArgumentList.Add("-$($_.Key) @($($_.Value | ForEach-Object {`"$($_)`"}))")}
|
|
|
|
$ArgumentListTargetIndex = $ArgumentList.Count - 1
|
|
|
|
$ArgumentListIndexItem = $ArgumentList[$ArgumentListTargetIndex]
|
|
|
|
$Null = $ArgumentList.RemoveAt($ArgumentListTargetIndex)
|
|
|
|
$Null = $ArgumentList.Insert($ArgumentListTargetIndex, ($ArgumentListIndexItem + ';'))
|
|
|
|
$ArgumentList.Add("[System.Environment]::Exit((`$LASTEXITCODE -Bor [Int](-Not `$? -And -Not `$LASTEXITCODE)))}`"")
|
|
|
|
$ScriptInterpreterList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
|
|
$ScriptInterpreterList.Add('powershell.exe')
|
|
$ScriptInterpreterList.Add('pwsh.exe')
|
|
|
|
:ScriptInterpreterListLoop ForEach ($ScriptInterpreter In $ScriptInterpreterList)
|
|
{
|
|
$ScriptInterpreterObject = Try {Get-Command -Name ($ScriptInterpreter) -ErrorAction SilentlyContinue} Catch {$Null}
|
|
|
|
Switch ($Null -ine $ScriptInterpreterObject)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$Null = Start-Process -FilePath ($ScriptInterpreterObject.Path) -WorkingDirectory "$($Env:Temp.TrimEnd('\'))" -ArgumentList ($ArgumentList.ToArray()) -WindowStyle Normal -Verb RunAs -PassThru
|
|
|
|
Break ScriptInterpreterListLoop
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |