AWS.Tools.Installer.psm1
using namespace System using namespace System.Collections.Generic using namespace System.IO using namespace System.IO.Compression using namespace System.Management.Automation using namespace System.Net using namespace System.Net.Http using namespace System.Threading.Tasks Microsoft.PowerShell.Core\Set-StrictMode -Version 3 $script:AWSToolsSignatureAmazonSubject = 'CN="Amazon.com, Inc.", O="Amazon.com, Inc.", L=Seattle, S=Washington, C=US' $script:AWSToolsSignatureAwsSubject = 'CN="Amazon Web Services, Inc.", OU=AWS, O="Amazon Web Services, Inc.", L=Seattle, S=Washington, C=US' $script:AWSToolsSignatureSDKSubject = 'CN="Amazon Web Services, Inc.", OU=SDKs and Tools, O="Amazon Web Services, Inc.", L=Seattle, S=Washington, C=US' $script:AWSToolsTempRepoName = 'AWSToolsTemp' $script:CurrentMinAWSToolsInstallerVersion = '0.0.0.0' $script:ExpectedModuleCompanyName = 'aws-dotnet-sdk-team' $script:MaxModulesToFindIndividually = 3 $script:ParallelDownloaderClassCode = @" using System; using System.IO; using System.Net.Http; using System.Threading; using System.Threading.Tasks; public class ParallelDownloader { private readonly HttpClient Client; private readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource(); public ParallelDownloader(HttpClient client) { Client = client; } public async Task DownloadToFile(string uri, string filePath) { using (var httpResponseMessage = await Client.GetAsync(uri, CancellationTokenSource.Token)) using (var stream = await httpResponseMessage.EnsureSuccessStatusCode().Content.ReadAsStreamAsync()) using (var fileStream = new FileStream(filePath, FileMode.Create)) { await stream.CopyToAsync(fileStream, 81920, CancellationTokenSource.Token); } } public void Cancel() { CancellationTokenSource.Cancel(); } } "@ function Get-CleanVersion { Param( [Parameter(ValueFromPipelineByPropertyName, ValueFromPipeline, Mandatory, Position = 0)] [AllowNull()] [Version] $Version ) Process { if ($null -eq $Version) { $Version } else { [int]$major = $Version.Major [int]$minor = $Version.Minor [int]$build = $Version.Build [int]$revision = $Version.Revision #PowerShell modules version numbers can have missing fields, that would create problems with #matching and sorting versions. Replacing missing fields with 0s if ($major -lt 0) { $major = 0 } if ($minor -lt 0) { $minor = 0 } if ($build -lt 0) { $build = 0 } if ($revision -lt 0) { $revision = 0 } [Version]::new($major, $minor, $build, $revision) } } } function Get-AWSToolsModule { Param( [Parameter()] [Switch] $SkipIfInvalidSignature ) Process { #Windows Powershell 5.1 has inconistent behavior where Get-Module could return nothing in %USERPROFILE%\Documents\WindowsPowerShell\Modules. [PSModuleInfo[]]$installedAwsToolsModules = Microsoft.PowerShell.Core\Get-Module -Name 'AWS.Tools.*' -ListAvailable -Verbose:$false if ($installedAwsToolsModules -and ($PSVersionTable.PSVersion.Major -lt 6 -or $IsWindows)) { $installedAwsToolsModules = $installedAwsToolsModules | Where-Object { [Signature]$signature = Microsoft.PowerShell.Security\Get-AuthenticodeSignature -FilePath $_.Path ($signature.Status -eq 'Valid' -or $SkipIfInvalidSignature) -and ($signature.SignerCertificate.Subject -eq $script:AWSToolsSignatureAmazonSubject -or $signature.SignerCertificate.Subject -eq $script:AWSToolsSignatureAwsSubject -or $signature.SignerCertificate.Subject.StartsWith($script:AWSToolsSignatureSDKSubject)) } } if($installedAwsToolsModules) { $installedAwsToolsModules = $installedAwsToolsModules | Where-Object { $_.Name -ne 'AWS.Tools.Installer' } } $installedAwsToolsModules } } <# .Synopsis Uninstalls all currently installed AWS.Tools modules. .Description This cmdlet uses Uninstall-Module to uninstall all currently installed AWS.Tools modules. .Notes .Example Uninstall-AWSToolsModule -ExceptVersion 4.0.0.0 This example uninstalls all versions of all AWS.Tools modules except for version 4.0.0.0. #> function Uninstall-AWSToolsModule { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] Param( ## Specifies the minimum version of the modules to uninstall. [Parameter(ValueFromPipelineByPropertyName)] [Version] $MinimumVersion, ## Specifies exact version number of the module to uninstall. [Parameter(ValueFromPipelineByPropertyName)] [Version] $RequiredVersion, ## Specifies the maximum version of the modules to uninstall. [Parameter(ValueFromPipelineByPropertyName)] [Version] $MaximumVersion, ## Specifies that you want to uninstall all of the other available versions of AWS Tools except this one. [Parameter(ValueFromPipelineByPropertyName)] [Version] $ExceptVersion, ## Forces Uninstall-AWSToolsModule to run without asking for user confirmation [Parameter(ValueFromPipelineByPropertyName)] [Switch] $Force ) Begin { $MinimumVersion = Get-CleanVersion $MinimumVersion $RequiredVersion = Get-CleanVersion $RequiredVersion $MaximumVersion = Get-CleanVersion $MaximumVersion $ExceptVersion = Get-CleanVersion $ExceptVersion Write-Verbose "[$($MyInvocation.MyCommand)] ConfirmPreference=$ConfirmPreference WhatIfPreference=$WhatIfPreference VerbosePreference=$VerbosePreference Force=$Force" } Process { $ErrorActionPreference = 'Stop' Write-Verbose "[$($MyInvocation.MyCommand)] Searching installed modules" [PSModuleInfo[]]$InstalledAwsToolsModules = Get-AWSToolsModule if ($MinimumVersion -and $InstalledAwsToolsModules) { $InstalledAwsToolsModules = $InstalledAwsToolsModules | Where-Object { $_.Version -ge $MinimumVersion } } if ($MaximumVersion -and $InstalledAwsToolsModules) { $InstalledAwsToolsModules = $InstalledAwsToolsModules | Where-Object { $_.Version -le $MaximumVersion } } if ($RequiredVersion -and $InstalledAwsToolsModules) { $InstalledAwsToolsModules = $InstalledAwsToolsModules | Where-Object { $_.Version -eq $RequiredVersion } } if ($ExceptVersion -and $InstalledAwsToolsModules) { $InstalledAwsToolsModules = $InstalledAwsToolsModules | Where-Object { $_.Version -ne $ExceptVersion } } if ($InstalledAwsToolsModules) { $versions = $InstalledAwsToolsModules | Group-Object Version if ($versions -and ($Force -or $WhatIfPreference -or $PSCmdlet.ShouldProcess("AWS Tools version $([string]::Join(', ', $versions.Name))"))) { $ConfirmPreference = 'None' $versions | ForEach-Object { Write-Host "Uninstalling AWS.Tools version $($_.Name)" [PSModuleInfo[]]$versionModules = $_.Group while ($versionModules) { [string[]]$dependencyNames = $versionModules | Select-Object -ExpandProperty RequiredModules | Select-Object -ExpandProperty Name | Sort-Object -Unique if ($dependencyNames) { [PSModuleInfo[]]$removableModules = $versionModules | Where-Object { -not $dependencyNames.Contains($_.Name) } } else { [PSModuleInfo[]]$removableModules = $versionModules } if (-not $removableModules) { Write-Error "Remaining modules for version $($_.Name) cannot be removed" break } $removableModules | ForEach-Object { if ($WhatIfPreference) { Write-Host "What if: Uninstalling module $($_.Name)" } else { Write-Host "Uninstalling module $($_.Name)" #We need to use -Force to work around https://github.com/PowerShell/PowerShellGet/issues/542 $uninstallModuleParams = @{ Name = $_.Name RequiredVersion = $_.Version Force = $true Confirm = $false ErrorAction = 'Continue' } PowerShellGet\Uninstall-Module @uninstallModuleParams } } $versionModules = $versionModules | Where-Object { $_.Name -notin ($removableModules | Select-Object -ExpandProperty Name) } } } } } } End { Write-Verbose "[$($MyInvocation.MyCommand)] End" } } function Find-AWSToolsModule { Param( ## Specifies a proxy server for the request, rather than connecting directly to an internet resource. [Parameter(ValueFromPipelineByPropertyName, ValueFromPipeline, Mandatory, Position = 0)] [string[]] $Name, ## Specifies a proxy server for the request, rather than connecting directly to an internet resource. [Parameter(ValueFromPipelineByPropertyName)] [Uri] $Proxy, ## Specifies a user account that has permission to use the proxy server specified by the Proxy parameter. [Parameter(ValueFromPipelineByPropertyName)] [PSCredential] $ProxyCredential ) Begin { $RequiredVersion = Get-CleanVersion $RequiredVersion $MaximumVersion = Get-CleanVersion $MaximumVersion Write-Verbose "[$($MyInvocation.MyCommand)] ConfirmPreference=$ConfirmPreference WhatIfPreference=$WhatIfPreference VerbosePreference=$VerbosePreference Name=($Name)" } Process { $proxyParams = @{ } if ($Proxy) { $proxyParams['Proxy'] = $Proxy } if ($ProxyCredential) { $proxyParams['ProxyCredential'] = $ProxyCredential } [PSObject[]]$availableModules = @() [string[]]$missingModules = $Name #'Find-Module AWS.Tools.*' is only slightly slower than Find-Module for a single module if ($Name.Count -gt $script:MaxModulesToFindIndividually) { $availableModules += PowerShellGet\Find-Module -Name 'AWS.Tools.*' -Repository 'PSGallery' @proxyParams -ErrorAction 'Stop' | Where-Object { $_.Name -in $Name -and $_.CompanyName -ceq $script:ExpectedModuleCompanyName } $missingModules = $Name | Where-Object { $_ -notin ($availableModules | Select-Object -ExpandProperty Name) } if ($missingModules) { Write-Verbose "[$($MyInvocation.MyCommand)] Retrying Find-Module on ($missingModules)" } } if ($missingModules) { #'Find-Module AWS.Tools.*' doesn't always return all modules, so we have to retry missing ones $missingModules | ForEach-Object { $availableModules += PowerShellGet\Find-Module -Name $_ -Repository 'PSGallery' @proxyParams -ErrorAction 'Ignore' | Where-Object { $_.Name -in $Name -and $_.CompanyName -ceq $script:ExpectedModuleCompanyName } } $missingModules = $Name | Where-Object { $_ -notin ($availableModules | Select-Object -ExpandProperty Name) } if ($missingModules) { throw "Could not find AWS.Tools module on PSGallery: $([string]::Join(', ', $missingModules))." } } $availableModules } End { Write-Verbose "[$($MyInvocation.MyCommand)] End" } } function Get-AWSToolsModuleDependenciesAndValidate { Param( ## Path of the manifest file to validate [Parameter(ValueFromPipelineByPropertyName, Mandatory)] [string] $Path, ## Name of the module to validate [Parameter(ValueFromPipelineByPropertyName, Mandatory)] [string] $Name ) Begin { Write-Verbose "[$($MyInvocation.MyCommand)] ConfirmPreference=$ConfirmPreference WhatIfPreference=$WhatIfPreference VerbosePreference=$VerbosePreference Name=$Name Path=$Path" } Process { $ErrorActionPreference = 'Stop' Add-Type -AssemblyName System.IO.Compression.FileSystem -ErrorAction Stop Add-Type -AssemblyName System.IO.Compression -ErrorAction Stop [Stream]$manifestFileStream = $null [Stream]$entryStream = $null [ZipArchive]$zipArchive = $null [string]$temporaryManifestFilePath = $null try { $zipArchive = [ZipFile]::OpenRead($Path) [ZipArchiveEntry]$entry = $zipArchive.GetEntry("$($Name).psd1") $entryStream = $entry.Open() $temporaryManifestFilePath = Join-Path ([Path]::GetTempPath()) "$([Path]::GetRandomFileName()).psd1" $manifestFileStream = [File]::OpenWrite($temporaryManifestFilePath) $entryStream.CopyTo($manifestFileStream) $manifestFileStream.Close(); if ($PSVersionTable.PSVersion.Major -lt 6 -or $IsWindows) { [Signature]$manifestSignature = Microsoft.PowerShell.Security\Get-AuthenticodeSignature -FilePath $temporaryManifestFilePath if ($manifestSignature.Status -eq 'Valid' -and ($manifestSignature.SignerCertificate.Subject -eq $script:AWSToolsSignatureAmazonSubject -or $manifestSignature.SignerCertificate.Subject -eq $script:AWSToolsSignatureAwsSubject -or $manifestSignature.SignerCertificate.Subject.StartsWith($script:AWSToolsSignatureSDKSubject))) { Write-Verbose "[$($MyInvocation.MyCommand)] Manifest signature correctly validated" } else { throw "Error validating manifest signature for $($Name)" } } else { Write-Verbose "[$($MyInvocation.MyCommand)] Authenticode signature can only be verified on Windows, skipping" } [PSObject]$manifestData = Microsoft.PowerShell.Utility\Import-PowerShellDataFile $temporaryManifestFilePath if ($manifestData.PrivateData.ContainsKey('MinAWSToolsInstallerVersion')) { [Version]$minVersion = Get-CleanVersion $manifestData.PrivateData.MinAWSToolsInstallerVersion if ($minVersion -gt $script:CurrentMinAWSToolsInstallerVersion) { throw "$Name version $($manifestData.ModuleVersion) requires at least AWS.Tools.Installer version $minVersion. Run 'Update-Module AWS.Tools.Installer'." } } $manifestData.RequiredModules | ForEach-Object { Write-Verbose "[$($MyInvocation.MyCommand)] Found dependency $($_.ModuleName)" $_.ModuleName } } finally { if ($manifestFileStream) { $manifestFileStream.Dispose() } if ($entryStream) { $entryStream.Dispose() } if ($zipArchive) { $zipArchive.Dispose() } if ($temporaryManifestFilePath) { Microsoft.PowerShell.Management\Remove-Item -Path $temporaryManifestFilePath -WhatIf:$false } } } End { Write-Verbose "[$($MyInvocation.MyCommand)] End" } } <# .Synopsis Install AWS.Tools modules. .Description This cmdlet uses Install-Module to install AWS.Tools modules. Unless -SkipUpdate is specified, this cmdlet also updates all other currently installed AWS.Tools modules to the version being installed. .Notes This cmdlet uses the PSRepository named PSGallery as source. Use 'Get-PSRepository -Name PSGallery' for information on the PSRepository used by Update-AWSToolsModule. This cmdlet downloads all modules from https://www.powershellgallery.com/api/v2/package/ and considers it a trusted source. .Example Install-AWSToolsModule EC2,S3 -RequiredVersion 4.0.0.0 This example installs version 4.0.0.0 of AWS.Tools.EC2, AWS.Tools.S3 and their dependencies. #> function Install-AWSToolsModule { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] Param( ## Specifies names of the AWS.Tools modules to install. ## The names can be listed either with or without the "AWS.Tools." prefix (i.e. "AWS.Tools.Common" or simply "Common"). [Parameter(ValueFromPipelineByPropertyName, ValueFromPipeline, Mandatory, Position = 0)] [string[]] $Name, ## Specifies exact version number of the module to install. [Parameter(ValueFromPipelineByPropertyName, Position = 1)] [Version] $RequiredVersion, ## Specifies the minimum version of the modules to install. [Parameter(ValueFromPipelineByPropertyName)] [Version] $MinimumVersion, ## Specifies the maximum version of the modules to install. [Parameter(ValueFromPipelineByPropertyName)] [Version] $MaximumVersion, ## Specifies that, after a successful install, all other versions of the AWS Tools modules should be uninstalled. [Parameter(ValueFromPipelineByPropertyName)] [Switch] $CleanUp, ## Install-AWSToolsModule by default also updates all currently installed AWS.Tools modules. -SkipUpdate disables the update. [Parameter(ValueFromPipelineByPropertyName)] [Switch] $SkipUpdate, ## Allows skipping the publisher validation check. [Parameter(ValueFromPipelineByPropertyName)] [Switch] $SkipPublisherCheck, ## Specifies the installation scope of the module. The acceptable values for this parameter are AllUsers and CurrentUser. ## The AllUsers scope installs modules in a location that is accessible to all users of the computer: ## $env:ProgramFiles\PowerShell\Modules ## The CurrentUser installs modules in a location that is accessible only to the current user of the computer: ## $home\Documents\PowerShell\Modules ## When no Scope is defined, the default is CurrentUser. [Parameter(ValueFromPipelineByPropertyName)] [ValidateSet('CurrentUser', 'AllUsers')] [string] $Scope = 'CurrentUser', ## Overrides warning messages about installation conflicts about existing commands on a computer. [Parameter(ValueFromPipelineByPropertyName)] [Switch] $AllowClobber, ## Specifies a proxy server for the request, rather than connecting directly to an internet resource. [Parameter(ValueFromPipelineByPropertyName)] [Uri] $Proxy, ## Specifies a user account that has permission to use the proxy server specified by the Proxy parameter. [Parameter(ValueFromPipelineByPropertyName)] [PSCredential] $ProxyCredential, ## Forces an install of each specified module without a prompt to request confirmation [Parameter(ValueFromPipelineByPropertyName)] [Switch] $Force ) Begin { $RequiredVersion = Get-CleanVersion $RequiredVersion $MaximumVersion = Get-CleanVersion $MaximumVersion Write-Verbose "[$($MyInvocation.MyCommand)] ConfirmPreference=$ConfirmPreference WhatIfPreference=$WhatIfPreference VerbosePreference=$VerbosePreference Force=$Force Name=($Name) RequiredVersion=$RequiredVersion SkipUpdate=$SkipUpdate CleanUp=$CleanUp" } Process { $ErrorActionPreference = 'Stop' $Name = $Name | ForEach-Object { if ($_.Contains('.')) { $_ } else { "AWS.Tools.$_" } } | Sort-Object -Unique if ($Name -notlike 'AWS.Tools.*') { throw "The Name parameter must contain only AWS.Tools modules." } if ($Name -eq 'AWS.Tools.Installer') { throw "AWS.Tools.Installer cannot be used to install AWS.Tools.Installer. Use Update-Module instead." } [PSObject[]]$availableModulesToInstall = Find-AWSToolsModule -Name $Name -Proxy $Proxy -ProxyCredential $ProxyCredential [Version]$availableVersion = [Version[]]$availableModulesToInstall.Version | Measure-Object -Minimum | Select-Object -Expand Minimum if ($MinimumVersion -and $MinimumVersion -gt $availableVersion) { throw "The maximum version available is $availableVersion." } if ($RequiredVersion -and $RequiredVersion -gt $availableVersion) { throw "The maximum version available is $availableVersion." } if ($MinimumVersion -and $RequiredVersion -and $MinimumVersion -gt $RequiredVersion) { throw 'Parameter MinimumVersion is greater than RequiredVersion.' } if ($MaximumVersion -and $RequiredVersion -and $MaximumVersion -lt $RequiredVersion) { throw 'Parameter MaximumVersion is less than RequiredVersion.' } if ($MaximumVersion -and -not $RequiredVersion -and $MaximumVersion -lt $availableVersion) { $RequiredVersion = Find-Module -Name 'AWS.Tools.Common' -MaximumVersion $MaximumVersion | Select-Object -Expand Version } if (-not $RequiredVersion) { $RequiredVersion = $availableVersion } Write-Verbose "[$($MyInvocation.MyCommand)] Installing AWS Tools version $RequiredVersion" [string[]]$modulesToInstall = $availableModulesToInstall.Name if (-not $SkipUpdate) { Write-Verbose "[$($MyInvocation.MyCommand)] Searching installed modules" [PSModuleInfo[]]$installedAwsToolsModules = Get-AWSToolsModule -SkipIfInvalidSignature if ($installedAwsToolsModules) { $modulesToInstall = ($modulesToInstall + ($installedAwsToolsModules | Select-Object -Expand Name)) | Sort-Object -Unique Write-Verbose "[$($MyInvocation.MyCommand)] Merging existing modules into the list of modules to install: ($modulesToInstall)" } } $modulesToInstall = $modulesToInstall | Where-Object { -not (Get-Module $_ -ListAvailable -Verbose:$false | Where-Object { $_.Version -eq $RequiredVersion }) } Write-Verbose "[$($MyInvocation.MyCommand)] Removing already installed modules from the. Final list of modules to install: ($modulesToInstall)" if ($modulesToInstall) { if ($Force -or $WhatIfPreference -or $PSCmdlet.ShouldProcess("AWS Tools version $RequiredVersion")) { $ConfirmPreference = 'None' [string]$temporaryRepoDirectory = Join-Path ([Path]::GetTempPath()) ([Path]::GetRandomFileName()) Write-Verbose "[$($MyInvocation.MyCommand)] Create folder for temporary repository $temporaryRepoDirectory" Microsoft.PowerShell.Management\New-Item -ItemType Directory -Path $temporaryRepoDirectory -WhatIf:$false | Out-Null try { if (-not $WhatIfPreference) { PowerShellGet\Unregister-PSRepository -Name $script:AWSToolsTempRepoName -ErrorAction 'SilentlyContinue' Write-Verbose "[$($MyInvocation.MyCommand)] Registering temporary repository $script:AWSToolsTempRepoName" PowerShellGet\Register-PSRepository -Name $script:AWSToolsTempRepoName -SourceLocation $temporaryRepoDirectory -ErrorAction 'Stop' PowerShellGet\Set-PSRepository -Name $script:AWSToolsTempRepoName -InstallationPolicy Trusted } Add-Type -AssemblyName System.Net.Http -ErrorAction Stop [HttpClient]$httpClient = $null [HttpClientHandler]$httpClientHandler = $null [List[PSCustomObject]]$tasks = @() Write-Verbose "[$($MyInvocation.MyCommand)] Downloading modules to temporary repository" try { $httpClientHandler = [HttpClientHandler]::new() if ($Proxy) { $httpClientHandler.Proxy = [WebProxy]::new($Proxy) if ($ProxyCredential) { $httpClientHandler.Proxy.Credentials = $ProxyCredential.GetNetworkCredential() } } $httpClient = [HttpClient]::new($httpClientHandler); Add-Type $script:ParallelDownloaderClassCode -ReferencedAssemblies System.Net.Http,System.Threading.Tasks [ParallelDownloader]$parallelDownloader = [ParallelDownloader]::new($httpClient) [string[]]$modulesToDownload = $modulesToInstall [HashSet[string]]$savedModules = New-Object -TypeName System.Collections.Generic.HashSet[string] Write-Verbose "[$($MyInvocation.MyCommand)] Downloading modules ($modulesToDownload)" while ($modulesToDownload) { [string[]]$dependencies = @() $tasks = $modulesToDownload | Where-Object { $savedModules.Add($_) } | ForEach-Object { [string]$nupkgFilePath = Join-Path $temporaryRepoDirectory "$_.$($RequiredVersion).nupkg" Write-Verbose "[$($MyInvocation.MyCommand)] Downloading module $_ to $TemporaryRepoDirectory" [PSCustomObject]@{ Task = $parallelDownloader.DownloadToFile("https://www.powershellgallery.com/api/v2/package/$_/$RequiredVersion", $nupkgFilePath) ModuleName = $_ Path = $nupkgFilePath } } while ($tasks) { [int]$taskIndex = [Task]::WaitAny($tasks.Task) [PSObject]$task = $tasks[$taskIndex] $tasks.RemoveAt($taskIndex) if ($task.Task.IsCompleted) { $dependencies += Get-AWSToolsModuleDependenciesAndValidate -Path $task.Path -Name $task.ModuleName } else { throw "Error downloading $($task.ModuleName): $($task.Task.Exception)" } } $modulesToDownload = $dependencies | Sort-Object -Unique } } finally { if ($tasks) { Write-Verbose "[$($MyInvocation.MyCommand)] Cancelling $($tasks.Count) tasks" $parallelDownloader.Cancel() try { [Task]::WaitAll($tasks.Task) } catch { } } if ($httpClient) { $httpClient.Dispose() } if ($httpClientHandler) { $httpClientHandler.Dispose() } } Write-Verbose "[$($MyInvocation.MyCommand)] Installing modules ($modulesToInstall)" $installModuleParams = @{ RequiredVersion = $RequiredVersion Scope = $Scope Repository = $script:AWSToolsTempRepoName AllowClobber = $AllowClobber Confirm = $false ErrorAction = 'Stop' SkipPublisherCheck = $SkipPublisherCheck } $modulesToInstall | ForEach-Object { if (-not $WhatIfPreference) { Write-Host "Installing module $_ version $RequiredVersion" PowerShellGet\Install-Module -Name $_ @installModuleParams } else { Write-Host "What if: Installing module $_ version $RequiredVersion" } } Write-Verbose "[$($MyInvocation.MyCommand)] Modules install complete" } finally { if (-not $WhatIfPreference) { Write-Verbose "[$($MyInvocation.MyCommand)] Unregistering temporary repository $script:AWSToolsTempRepoName" PowerShellGet\Unregister-PSRepository -Name $script:AWSToolsTempRepoName -ErrorAction 'Continue' } Write-Verbose "[$($MyInvocation.MyCommand)] Delete repository folder $temporaryRepoDirectory" Microsoft.PowerShell.Management\Remove-Item -Path $temporaryRepoDirectory -Recurse -WhatIf:$false } } } else { Write-Verbose "[$($MyInvocation.MyCommand)] All modules are up to date" } if ($CleanUp) { Uninstall-AWSToolsModule -ExceptVersion $RequiredVersion } } End { Write-Verbose "[$($MyInvocation.MyCommand)] End" } } <# .Synopsis Updates all currently installed AWS.Tools modules. .Description This cmdlet uses Install-Module to update all AWS.Tools modules. .Notes This cmdlet uses the PSRepository named PSGallery as source. Use 'Get-PSRepository -Name PSGallery' for information on the PSRepository used by Update-AWSToolsModule. This cmdlet downloads all modules from https://www.powershellgallery.com/api/v2/package/ and considers it a trusted source. .Example Update-AWSToolsModule -CleanUp This example updates all installed AWS.Tools modules to the latest version available on the PSGallery and uninstalls all other versions. #> function Update-AWSToolsModule { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] Param( ## Specifies the exact version of the modules to update to. [Parameter(ValueFromPipelineByPropertyName, Position = 0)] [Version] $RequiredVersion, ## Specifies the maximum version of the modules to update to. [Parameter(ValueFromPipelineByPropertyName)] [Version] $MaximumVersion, ## Specifies that, after a successful install, all other versions of the AWS Tools modules should be uninstalled. [Parameter(ValueFromPipelineByPropertyName)] [Switch] $CleanUp, ## Allows skipping the publisher validation check. [Parameter(ValueFromPipelineByPropertyName)] [Switch] $SkipPublisherCheck, #Specifies the installation scope of the module. The acceptable values for this parameter are AllUsers and CurrentUser. #The AllUsers scope installs modules in a location that is accessible to all users of the computer: # $env:ProgramFiles\PowerShell\Modules #The CurrentUser installs modules in a location that is accessible only to the current user of the computer: # $home\Documents\PowerShell\Modules #When no Scope is defined, the default is CurrentUser. [Parameter(ValueFromPipelineByPropertyName)] [ValidateSet('CurrentUser', 'AllUsers')] [string] $Scope = 'CurrentUser', #Overrides warning messages about installation conflicts about existing commands on a computer. [Parameter(ValueFromPipelineByPropertyName)] [Switch] $AllowClobber, #Specifies a proxy server for the request, rather than connecting directly to an internet resource. [Parameter(ValueFromPipelineByPropertyName)] [Uri] $Proxy, ## Specifies a user account that has permission to use the proxy server specified by the Proxy parameter. [Parameter(ValueFromPipelineByPropertyName)] [PSCredential] $ProxyCredential, ## Forces an update of each specified module without a prompt to request confirmation [Parameter(ValueFromPipelineByPropertyName)] [Switch] $Force ) Begin { $RequiredVersion = Get-CleanVersion $RequiredVersion $MaximumVersion = Get-CleanVersion $MaximumVersion Write-Verbose "[$($MyInvocation.MyCommand)] ConfirmPreference=$ConfirmPreference WhatIfPreference=$WhatIfPreference VerbosePreference=$VerbosePreference Force=$Force" } Process { $ErrorActionPreference = 'Stop' Write-Verbose "[$($MyInvocation.MyCommand)] Searching installed modules" [PSModuleInfo[]]$installedAwsToolsModules = Get-AWSToolsModule -SkipIfInvalidSignature [string[]]$installedAwsToolsModuleNames = $installedAwsToolsModules | Select-Object -Expand Name | Sort-Object -Unique if ($installedAwsToolsModuleNames) { Write-Verbose "[$($MyInvocation.MyCommand)] Found modules ($installedAwsToolsModuleNames)" $installAWSToolsModuleParams = @{ Name = $installedAwsToolsModuleNames RequiredVersion = $RequiredVersion MaximumVersion = $MaximumVersion Scope = $Scope AllowClobber = $AllowClobber CleanUp = $CleanUp Force = $Force SkipUpdate = $true Proxy = $Proxy ProxyCredential = $ProxyCredential SkipPublisherCheck = $SkipPublisherCheck } Install-AWSToolsModule @installAWSToolsModuleParams } } End { Write-Verbose "[$($MyInvocation.MyCommand)] End" } } # SIG # Begin signature block # MIIfKgYJKoZIhvcNAQcCoIIfGzCCHxcCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCD3XIAxiJIeayjS # nIPmy0RFC6oZkzg3jBDt4kibfZrwCKCCDlkwggawMIIEmKADAgECAhAIrUCyYNKc # TJ9ezam9k67ZMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV # BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0z # NjA0MjgyMzU5NTlaMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw # ggIKAoICAQDVtC9C0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0 # JAfhS0/TeEP0F9ce2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJr # Q5qZ8sU7H/Lvy0daE6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhF # LqGfLOEYwhrMxe6TSXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+F # LEikVoQ11vkunKoAFdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh # 3K3kGKDYwSNHR7OhD26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJ # wZPt4bRc4G/rJvmM1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQay # g9Rc9hUZTO1i4F4z8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbI # YViY9XwCFjyDKK05huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchAp # QfDVxW0mdmgRQRNYmtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRro # OBl8ZhzNeDhFMJlP/2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IB # WTCCAVUwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+ # YXsIiGX0TkIwHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0P # AQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAk # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAC # hjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9v # dEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5j # b20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAED # MAgGBmeBDAEEATANBgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql # +Eg08yy25nRm95RysQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFF # UP2cvbaF4HZ+N3HLIvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1h # mYFW9snjdufE5BtfQ/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3Ryw # YFzzDaju4ImhvTnhOE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5Ubdld # AhQfQDN8A+KVssIhdXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw # 8MzK7/0pNVwfiThV9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnP # LqR0kq3bPKSchh/jwVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatE # QOON8BUozu3xGFYHKi8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bn # KD+sEq6lLyJsQfmCXBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQji # WQ1tygVQK+pKHJ6l/aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbq # yK+p/pQd52MbOoZWeE4wggehMIIFiaADAgECAhADDZQ2iew02WrUI+ndycx+MA0G # CSqGSIb3DQEBCwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwHhcNMjEwOTEwMDAwMDAwWhcNMjIwOTEw # MjM1OTU5WjCB9jEdMBsGA1UEDwwUUHJpdmF0ZSBPcmdhbml6YXRpb24xEzARBgsr # BgEEAYI3PAIBAxMCVVMxGTAXBgsrBgEEAYI3PAIBAhMIRGVsYXdhcmUxEDAOBgNV # BAUTBzQxNTI5NTQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw # DgYDVQQHEwdTZWF0dGxlMSIwIAYDVQQKExlBbWF6b24gV2ViIFNlcnZpY2VzLCBJ # bmMuMRcwFQYDVQQLEw5TREtzIGFuZCBUb29sczEiMCAGA1UEAxMZQW1hem9uIFdl # YiBTZXJ2aWNlcywgSW5jLjCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGB # AL8OvUej3gsogXSqvatSmFR2rOaCZvFPnJTzh+tV8R6IrbUnZEwk6T0uK0BJ/6s2 # KWndRpiW2oCiwywi5zeK6alZUXjoq0VK81fLLOnBcabEjWvrEmbg/RDmY5BP+zVw # +znz5GcS6Lcwc6iFIg8gNvASWbjSsFPlXhQ/8DZ3lET8O5QrLz4bbdGyA0/3vE+c # zL0vJmT2vU0T9T26SKpQGlCbm27laKfq1Tnot1x4ntDmuQDgZFQMC+H9ewd77/Dl # vZ0AKTt61QoplRR+YxbS+IhDUw9uukRla04XozKmqnAxYoC2BXe7utnLRGfC7027 # mVOTNskEdgvDZp8qWHnba3GXu9XZEmrGKOW/vEDtVHOi5OVNjhqdpFQ/BtY/xVJZ # fFsnmgI3hwlL2+gMNMZVlSJ6ukp3uvyuB/K+6GD2r5ckwc4/OIgvgGpmcRTwuIQ+ # AChyX4UBPN+GTU9kSmDDze8lt5JpAQa9nKpA5HCd1+PYAyMZKJT1l3T0a43vaDCi # vwIDAQABo4ICNTCCAjEwHwYDVR0jBBgwFoAUaDfg67Y7+F8Rhvv+YXsIiGX0TkIw # HQYDVR0OBBYEFJJZ6VTLO627RMRb/IXUTCt+3G25MC4GA1UdEQQnMCWgIwYIKwYB # BQUHCAOgFzAVDBNVUy1ERUxBV0FSRS00MTUyOTU0MA4GA1UdDwEB/wQEAwIHgDAT # BgNVHSUEDDAKBggrBgEFBQcDAzCBtQYDVR0fBIGtMIGqMFOgUaBPhk1odHRwOi8v # Y3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JT # QTQwOTZTSEEzODQyMDIxQ0ExLmNybDBToFGgT4ZNaHR0cDovL2NybDQuZGlnaWNl # cnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0 # MjAyMUNBMS5jcmwwPQYDVR0gBDYwNDAyBgVngQwBAzApMCcGCCsGAQUFBwIBFhto # dHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwgZQGCCsGAQUFBwEBBIGHMIGEMCQG # CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wXAYIKwYBBQUHMAKG # UGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENv # ZGVTaWduaW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3J0MAwGA1UdEwEB/wQCMAAw # DQYJKoZIhvcNAQELBQADggIBAIbYpsI/cnNv/0M7QL7LV93WCIBHZDUa4slc40zV # vxmv1mefP6u37QiYcvdql40EdOs2E2L0dPMEwzKpNEx1sP6eyKCpNritBmwNnbdQ # mW5dHya7J7VIGyNzwhH9SnRF7xsa3MfWaAA6EG2iKU4Kx0XqFE4y13xGCS+PXRZu # wW9QTcnZy7fGHiyOu/f2DlcuzFPFXkxsb5rjbwxd39w3ka3oUbx5PQEMnVxDKl+2 # MnmPNbjOEAYXUIRTkvnj2YHZCHSInOTjh1l54uNJe3RCf8ocOE4PrKee6dpJxdX7 # YacGLRGWHneDND8NQNml+eZGGh3rSg0fDtbDT3vu6k6Z2Ycig7d9WCvXwyzeIH7q # ydmRfHARi2sk3l2pJHO3tcNH+rUVrIzwGeMasjAalvqyShTVUeJ+kFMvVw5pzugn # g6lu9wdhv0U64jcYLV7bGbSyZq5+Fj4pycc+30K+xi8ogEltU89qwa9q7tCGxVXa # XztjAVQ7GhS3kSwGJiSuCKc8pc5HwbaonSccOoBvd4QkUOHVx7l3ZeiZIDYmUe/i # 0g7nH4Jwigkj5MS7rg5XEERFfKHSMT+w0H6kdmYIFkQSqEj+VaHEeNiJaECKCYIr # zNCsElwPcIfXMZLD6+5VcoBkGsEiGf7IPYjE+3HraoOORFzhHIAkyOzcpw6KfwIx # M32rMYIQJzCCECMCAQEwfTBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNl # cnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWdu # aW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExAhADDZQ2iew02WrUI+ndycx+MA0G # CWCGSAFlAwQCAQUAoHwwEAYKKwYBBAGCNwIBDDECMAAwGQYJKoZIhvcNAQkDMQwG # CisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZI # hvcNAQkEMSIEIAkyetgUPuSuX7PMb/jyobjul897fWynx/GZy0/Yec3pMA0GCSqG # SIb3DQEBAQUABIIBgKqfWdsOqkKHtIEexLP3j4FpOepQ29q8U1w8pTMp5c3cQUZb # YaxdBh49Ttgct3pmg3i01K5yrCjv6PwgFGhM4xuJomdLlcRRez/b5COpyVr7+hFB # xBirk8v3jIBexUvRkqdDHMJfSlrQmjJERdf3G/1Aqotp06Llrj6zCGK0xMcnjD+j # 1XYHpPaXqlDN/KBc9Upq8c+4RfxN8Woyt5PX/7NZjdXpPPh9Jej9X8DGwSDLRM+W # RFqePdNBgg5Gn/HGDI174IZVqr2tKvqqJoUslpO4f2RvC014QlGf8JyvfGdOA8jR # G/YYCEGvTD1YnVImeh3/Gnt5XDStFrhOzEqoN4k/paAOpSaUuDJVQJ70U9d/xyxL # +ffrEzA6e3qytd+Tcbv/3sPMHjBiqNLRvpDKjKiDfiRYVx458vrJ5OJCsUOHnLiJ # EhMrF323jTY5TGLJL6zF0N3vcbWavrPCvNld1Hsxll1U45tfTZbRG7sjjlSnqeM1 # /0C+hHVo0wO2Pqg0LKGCDX0wgg15BgorBgEEAYI3AwMBMYINaTCCDWUGCSqGSIb3 # DQEHAqCCDVYwgg1SAgEDMQ8wDQYJYIZIAWUDBAIBBQAwdwYLKoZIhvcNAQkQAQSg # aARmMGQCAQEGCWCGSAGG/WwHATAxMA0GCWCGSAFlAwQCAQUABCBzH+fQSeQyKVXg # kj01sEwLRS3JgprXuWbrmiO09SII3gIQJoKbRsUpsbUI9+X42a8DJBgPMjAyMTEw # MDIwMTEzNDFaoIIKNzCCBP4wggPmoAMCAQICEA1CSuC+Ooj/YEAhzhQA8N0wDQYJ # KoZIhvcNAQELBQAwcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IElu # YzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQg # U0hBMiBBc3N1cmVkIElEIFRpbWVzdGFtcGluZyBDQTAeFw0yMTAxMDEwMDAwMDBa # Fw0zMTAxMDYwMDAwMDBaMEgxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2Vy # dCwgSW5jLjEgMB4GA1UEAxMXRGlnaUNlcnQgVGltZXN0YW1wIDIwMjEwggEiMA0G # CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDC5mGEZ8WK9Q0IpEXKY2tR1zoRQr0K # dXVNlLQMULUmEP4dyG+RawyW5xpcSO9E5b+bYc0VkWJauP9nC5xj/TZqgfop+N0r # cIXeAhjzeG28ffnHbQk9vmp2h+mKvfiEXR52yeTGdnY6U9HR01o2j8aj4S8bOrdh # 1nPsTm0zinxdRS1LsVDmQTo3VobckyON91Al6GTm3dOPL1e1hyDrDo4s1SPa9E14 # RuMDgzEpSlwMMYpKjIjF9zBa+RSvFV9sQ0kJ/SYjU/aNY+gaq1uxHTDCm2mCtNv8 # VlS8H6GHq756WwogL0sJyZWnjbL61mOLTqVyHO6fegFz+BnW/g1JhL0BAgMBAAGj # ggG4MIIBtDAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8E # DDAKBggrBgEFBQcDCDBBBgNVHSAEOjA4MDYGCWCGSAGG/WwHATApMCcGCCsGAQUF # BwIBFhtodHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwHwYDVR0jBBgwFoAU9Lbh # IB3+Ka7S5GGlsqIlssgXNW4wHQYDVR0OBBYEFDZEho6kurBmvrwoLR1ENt3janq8 # MHEGA1UdHwRqMGgwMqAwoC6GLGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEy # LWFzc3VyZWQtdHMuY3JsMDKgMKAuhixodHRwOi8vY3JsNC5kaWdpY2VydC5jb20v # c2hhMi1hc3N1cmVkLXRzLmNybDCBhQYIKwYBBQUHAQEEeTB3MCQGCCsGAQUFBzAB # hhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTwYIKwYBBQUHMAKGQ2h0dHA6Ly9j # YWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJBc3N1cmVkSURUaW1lc3Rh # bXBpbmdDQS5jcnQwDQYJKoZIhvcNAQELBQADggEBAEgc3LXpmiO85xrnIA6OZ0b9 # QnJRdAojR6OrktIlxHBZvhSg5SeBpU0UFRkHefDRBMOG2Tu9/kQCZk3taaQP9rhw # z2Lo9VFKeHk2eie38+dSn5On7UOee+e03UEiifuHokYDTvz0/rdkd2NfI1Jpg4L6 # GlPtkMyNoRdzDfTzZTlwS/Oc1np72gy8PTLQG8v1Yfx1CAB2vIEO+MDhXM/EEXLn # G2RJ2CKadRVC9S0yOIHa9GCiurRS+1zgYSQlT7LfySmoc0NR2r1j1h9bm/cuG08T # HfdKDXF+l7f0P4TrweOjSaH6zqe/Vs+6WXZhiV9+p7SOZ3j5NpjhyyjaW4emii8w # ggUxMIIEGaADAgECAhAKoSXW1jIbfkHkBdo2l8IVMA0GCSqGSIb3DQEBCwUAMGUx # CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 # dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9v # dCBDQTAeFw0xNjAxMDcxMjAwMDBaFw0zMTAxMDcxMjAwMDBaMHIxCzAJBgNVBAYT # AlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2Vy # dC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3Rh # bXBpbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC90DLuS82P # f92puoKZxTlUKFe2I0rEDgdFM1EQfdD5fU1ofue2oPSNs4jkl79jIZCYvxO8V9PD # 4X4I1moUADj3Lh477sym9jJZ/l9lP+Cb6+NGRwYaVX4LJ37AovWg4N4iPw7/fpX7 # 86O6Ij4YrBHk8JkDbTuFfAnT7l3ImgtU46gJcWvgzyIQD3XPcXJOCq3fQDpct1Hh # oXkUxk0kIzBdvOw8YGqsLwfM/fDqR9mIUF79Zm5WYScpiYRR5oLnRlD9lCosp+R1 # PrqYD4R/nzEU1q3V8mTLex4F0IQZchfxFwbvPc3WTe8GQv2iUypPhR3EHTyvz9qs # EPXdrKzpVv+TAgMBAAGjggHOMIIByjAdBgNVHQ4EFgQU9LbhIB3+Ka7S5GGlsqIl # ssgXNW4wHwYDVR0jBBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8wEgYDVR0TAQH/ # BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgw # eQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy # dC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9E # aWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0 # dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5j # cmwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3Vy # ZWRJRFJvb3RDQS5jcmwwUAYDVR0gBEkwRzA4BgpghkgBhv1sAAIEMCowKAYIKwYB # BQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCwYJYIZIAYb9bAcB # MA0GCSqGSIb3DQEBCwUAA4IBAQBxlRLpUYdWac3v3dp8qmN6s3jPBjdAhO9LhL/K # zwMC/cWnww4gQiyvd/MrHwwhWiq3BTQdaq6Z+CeiZr8JqmDfdqQ6kw/4stHYfBli # 6F6CJR7Euhx7LCHi1lssFDVDBGiy23UC4HLHmNY8ZOUfSBAYX4k4YU1iRiSHY4yR # UiyvKYnleB/WCxSlgNcSR3CzddWThZN+tpJn+1Nhiaj1a5bA9FhpDXzIAbG5KHW3 # mWOFIoxhynmUfln8jA/jb7UBJrZspe6HUSHkWGCbugwtK22ixH67xCUrRwIIfEmu # E7bhfEJCKMYYVs9BNLZmXbZ0e/VWMyIvIjayS6JKldj1po5SMYIChjCCAoICAQEw # gYYwcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UE # CxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1 # cmVkIElEIFRpbWVzdGFtcGluZyBDQQIQDUJK4L46iP9gQCHOFADw3TANBglghkgB # ZQMEAgEFAKCB0TAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcN # AQkFMQ8XDTIxMTAwMjAxMTM0MVowKwYLKoZIhvcNAQkQAgwxHDAaMBgwFgQU4deC # qOGRvu9ryhaRtaq0lKYkm/MwLwYJKoZIhvcNAQkEMSIEIHAIDgIUP/PjEO9kHKpc # uJ+dJ6o7dCwSpha1oC+GY+HoMDcGCyqGSIb3DQEJEAIvMSgwJjAkMCIEILMQkAa8 # CtmDB5FXKeBEA0Fcg+MpK2FPJpZMjTVx7PWpMA0GCSqGSIb3DQEBAQUABIIBAHW+ # MGB4NyJNvZiT7lKW5Y+ALxYcNro3DY4tC/5DcRCe0k7bHieTHPLPSzmVIuvjrsOy # Hx+j9aOX86BKUIijqrk2zNyuHOhmJi7ztJJkpnkM/GG9SZBDnkcLWrm7IivOpLuU # OCb00pu/vqRZNpxvUN9TZ3ju+sybNL8bDAxFvrPOPweUkFIrJpaK8NZoGzWuAkU7 # 5S2NQpzuzb+RW/mLVEyXmT4APfEIR4TY9eEqzYav4iYnLOtnkBMPjk6nq/3wU7my # uynjLGRk2umEVy/eT7WwFGKXKtP5IPa7xl9knwkJvF9wISRJnTQiGm6AKEbshb4+ # usPnabQzeTZo7um53K8= # SIG # End signature block |