mirror of
https://github.com/Grace-Solutions/Invoke-OpenSSHConfiguration.git
synced 2026-07-26 11:38:14 +00:00
Detection, Download, and Installation Framework Completed
This commit is contained in:
@@ -0,0 +1,344 @@
|
||||
#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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user