From 8ceddd59188db4eb699a0523baf1c2c2bcbffe8f Mon Sep 17 00:00:00 2001 From: Stephen Valdinger Date: Wed, 4 Dec 2024 10:04:39 -0500 Subject: [PATCH] (#240) Parameterize setup This script adds parameterization to the ClientSetup.ps1 script that is hosted within the Nexus repository. It also adds parameterization to the registration script that is executed on a client so you can customize the installation. --- scripts/ClientSetup.ps1 | 167 ++++++++++++++++++++++++++++--- scripts/Register-C4bEndpoint.ps1 | 110 ++++++++++++++++++-- 2 files changed, 255 insertions(+), 22 deletions(-) diff --git a/scripts/ClientSetup.ps1 b/scripts/ClientSetup.ps1 index 9b12a73..bb606e3 100644 --- a/scripts/ClientSetup.ps1 +++ b/scripts/ClientSetup.ps1 @@ -14,7 +14,7 @@ param( # The credential necessary to access the internal Nexus repository. This can # be ignored if Anonymous authentication is enabled. # This parameter will be necessary if your C4B server is web-enabled. - [Parameter()] + [Parameter(Mandatory)] [pscredential] $Credential, @@ -41,19 +41,38 @@ param( # Client salt value used to populate the centralManagementClientCommunicationSaltAdditivePassword # value in the Chocolatey config file - [Parameter()] + [Parameter(Mandatory)] [string] $ClientSalt, # Server salt value used to populate the centralManagementServiceCommunicationSaltAdditivePassword # value in the Chocolatey config file - [Parameter()] + [Parameter(Mandatory)] [string] $ServiceSalt, + # Allows for the application of user-defined configuration that is applied after the base configuration. + # Can override base configuration with this parameter + [Parameter()] + [Hashtable[]] + $AdditionalConfiguration, + + # Allows for the toggling of additonal features that is applied after the base configuration. + # Can override base configuration with this parameter + [Parameter()] + [Hashtable[]] + $AdditionalFeatures, + + # Allows for the installation of additional packages after the system base packages have been installed. [Parameter()] - [Switch] - $InternetEnabled + [Hashtable[]] + $AdditionalPackages, + + # Allows for the addition of alternative sources after the base conifguration has been applied. + # Can override base configuration with this parameter + [Parameter()] + [Hashtable[]] + $AdditionalSources ) Set-ExecutionPolicy Bypass -Scope Process -Force @@ -69,11 +88,14 @@ $params = @{ if (-not $IgnoreProxy) { if ($ProxyUrl) { + $proxy = [System.Net.WebProxy]::new($ProxyUrl, $true <#bypass on local#>) $params.Add('ProxyUrl', $ProxyUrl) } if ($ProxyCredential) { $params.Add('ProxyCredential', $ProxyCredential) + $proxy.Credentials = $ProxyCredential + } } @@ -87,7 +109,8 @@ $NupkgUrl = if (-not $ChocolateyVersion) { $QueryUrl = ($RepositoryUrl.TrimEnd('/index.json'), "v3/registration/Chocolatey/index.json") -join '/' $Result = $webClient.DownloadString($QueryUrl) | ConvertFrom-Json $Result.items.items[-1].packageContent -} else { +} +else { # Otherwise, assume the URL "$($RepositoryUrl.TrimEnd('/index.json'))/v3/content/chocolatey/$($ChocolateyVersion)/chocolatey.$($ChocolateyVersion).nupkg" } @@ -118,13 +141,8 @@ choco config set commandExecutionTimeoutSeconds 14400 # Nexus NuGet V3 Compatibility choco feature disable --name="'usePackageRepositoryOptimizations'" -if ($InternetEnabled) { - choco source add --name="'ChocolateyInternal'" --source="'$RepositoryUrl'" --allow-self-service --user="'$($Credential.UserName)'" --password="'$($Credential.GetNetworkCredential().Password)'" --priority=1 -} -else { - choco source add --name="'ChocolateyInternal'" --source="'$RepositoryUrl'" --allow-self-service --priority=1 -} - +#Environment base Source configuration +choco source add --name="'ChocolateyInternal'" --source="'$RepositoryUrl'" --allow-self-service --user="'$($Credential.UserName)'" --password="'$($Credential.GetNetworkCredential().Password)'" --priority=1 choco source disable --name="'Chocolatey'" choco source disable --name="'chocolatey.licensed'" @@ -158,3 +176,126 @@ if ($ServiceSalt) { } choco feature enable --name="'useChocolateyCentralManagement'" choco feature enable --name="'useChocolateyCentralManagementDeployments'" + + +Write-Host "Applying user supplied configuration" -ForegroundColor Cyan +#How we call choco from here changes as we need to be more dynamic with thingsii . +if ($AdditionalConfiguration) { + <# + We expect to pass in a hashtable with configuration information with the following shape: + + @{ + Name = BackgroundServiceAllowedCommands + Value = 'install,upgrade,uninstall' + } + #> + foreach ($conf in $AdditionalConfiguration) { + $c = [System.Collections.Generic.list[string]]::new() + $c.Add('config') + $c.Add('set') + $c.Add("--name='$($conf.Name)'") + $c.Add("--value='$($conf.Value)'") + + & choco @c + + } +} + +if ($AdditionalFeatures) { + <# + We expect to pass in feature information as a hashtable with the following shape: + + @{ + Name = useBackgroundservice + State = 'Enabled' + } + #> + foreach ($feature in $AdditionalFeatures) { + + $c = [System.Collections.Generic.list[string]]::new() + $c.Add('feature') + + $state = switch ($feature['State']) { + 'Enabled' { 'enable' } + 'Disabled' { 'disable' } + default { Write-Error 'State must be either Enabled or Disabled' } + } + + $c.Add($state) + $c.add("--name='$($feature.Name)'") + & choco @c + } +} + +if ($AdditionalSources) { + + <# + We expect a user to pass in a hashtable with source information with the folllowing shape: + @{ + Name = 'MySource' + Source = 'https://nexus.fabrikam.com/repository/MyChocolateySource' + #Optional items + Credentials = $MySourceCredential + AllowSelfService = $true + AdminOnly = $true + BypassProxy = $true + Priority = 10 + Certificate = 'C:\cert.pfx' + CertificatePassword = 's0mepa$$' + } +#> + Foreach ($a in $AdditionalSources) { + $c = [System.Collections.Generic.List[string]]::new() + #Required items + $c.Add('source') + $c.Add('add') + $c.Add("--name='$($a.Name)'") + $c.Add("--source='$($a.Source)'") + + #Add credentials if source has them + if ($a.ContainsKey('Credentials')) { + $c.Add("--user='$($a.Credentials.Username)'") + $c.Add("--password='$($a.Credentials.GetNetworkCredential().Password)'") + } + + switch ($true) { + $a['AllowSelfService'] { $c.add('--allow-self-service') } + $a['AdminOnly'] { $c.Add('--admin-only') } + $a['BypassProxy'] { $c.Add('--bypass-proxy') } + $a.ContainsKey('Priority') { $c.Add("--priority='$($a.Priority)'") } + $a.ContainsKey('Certificate') { $c.Add("--cert='$($a.Certificate)'") } + $a.ContainsKey('CerfificatePassword') { $c.Add("--certpassword='$($a.CertificatePassword)'") } + } + + + } + + +} + +if ($AdditionalPackages) { + + <# + We expect to pass in a hashtable with package information with the following shape: + + @{ + Id = 'firefox' + #Optional + Version = 123.4.56 + Pin = $true + } + #> + foreach ($package in $AdditionalPackages.GetEnumerator()) { + + $c = [System.Collections.Generic.list[string]]::new() + $c.add('install') + $c.add($package['Id']) + + switch ($true) { + $package.ContainsKey('Version') { $c.Add("--version='$($package.version)'") } + $package.ContainsKey('Pin') { $c.Add('--pin') } + } + + & choco @c + } +} \ No newline at end of file diff --git a/scripts/Register-C4bEndpoint.ps1 b/scripts/Register-C4bEndpoint.ps1 index dee0459..a17ced4 100644 --- a/scripts/Register-C4bEndpoint.ps1 +++ b/scripts/Register-C4bEndpoint.ps1 @@ -1,12 +1,104 @@ -# Here is a script you can run to setup your endpoints to connect to the C4B Server. -# This includes: -# - Installing Chocolatey -# - Installing your chocolatey-license -# - Running the Client Setup, which sets up Nexus repo and CCM acccess +[CmdletBinding()] +Param( + # The DNS name of the server that hosts your repository, Jenkins, and Chocolatey Central Management + [Parameter()] + [String] + $Fqdn = '{{ FQDN }}', -$HostName = {{hostname}} #This needs to be the same hostname as the CN/Subject of your SSL cert + # Client salt value used to populate the centralManagementClientCommunicationSaltAdditivePassword + # value in the Chocolatey config file + [Parameter()] + [String] + $ClientCommunicationSalt = '{{ ClientSaltValue }}', -# placeholder if using a self-signed cert + # Server salt value used to populate the centralManagementServiceCommunicationSaltAdditivePassword + # value in the Chocolatey config file + [Parameter()] + [String] + $ServiceCommunicationSalt = '{{ ServiceSaltValue }}', -$downloader = New-Object -TypeName System.Net.WebClient -Invoke-Expression ($downloader.DownloadString("https://$($HostName):8443/repository/choco-install/ClientSetup.ps1")) \ No newline at end of file + [Parameter(Mandatory)] + [PSCredential] + $RepositoryCredential, + + # The URL of a proxy server to use for connecting to the repository. + [Parameter()] + [String] + $ProxyUrl, + # The credentials, if required, to connect to the proxy server. + [Parameter()] + [PSCredential] + $ProxyCredential, + + # Allows for the application of user-defined configuration that is applied after the base configuration. + # Can override base configuration with this parameter + [Parameter()] + [Hashtable[]] + $AdditionalConfiguration, + + # Allows for the toggling of additonal features that is applied after the base configuration. + # Can override base configuration with this parameter + [Parameter()] + [Hashtable[]] + $AdditionalFeatures, + + # Allows for the installation of additional packages after the system base packages have been installed. + [Parameter()] + [Hashtable[]] + $AdditionalPackages, + + # Allows for the addition of alternative sources after the base conifguration has been applied. + # Can override base configuration with this parameter + [Parameter()] + [Hashtable[]] + $AdditionalSources +) + +# Touch NOTHING below this line +$RepositoryUrl = "https://$($fqdn):8443/repository/ChocolateyInternal/index.json" + +#Initialize params hashtable so we can add to it if needed later +$params = @{ + Credential = $RepositoryCredential + ClientSalt = $ClientCommunicationSalt + ServiceSalt = $ServiceCommunicationSalt + RepositoryUrl = $RepositoryUrl +} + +switch ($true) { + $PSBoundParameters.ContainsKey('AdditionalConfiguration') { + $params.Add('AdditionalConfiguration', $AdditionalConfiguration) + } + $PSBoundParameters.ContainsKey('AdditionalFeatures') { + $params.add('AdditionalFeatures', $AdditionalFeatures) + } + + $PSBoundParameters.ContainsKey('AdditionalPackages') { + $params.Add('AdditionalPackages', $AdditionalPackages) + } + + $PSBoundParameters.ContainsKey('AdditionalSources') { + $params.Add('AdditionalSources', $AdditionalSources) + } +} + +$downloader = [System.Net.WebClient]::new() + +#setup proxy if required +if ($ProxyUrl) { + $params.add('ProxyUrl', $ProxyUrl) + $proxy = [System.Net.WebProxy]::new($ProxyUrl, $true <#bypass on local#>) + + if ($ProxyCredential) { + $params.Add('ProxyCredential', $ProxyCredential) + $proxy.Credentials = $ProxyCredential + } + + $downloader.Proxy = $proxy +} + +$downloader.Credentials = $RepositoryCredential + +$script = $downloader.DownloadString("https://$($FQDN):8443/repository/choco-install/ClientSetup.ps1") + +& ([scriptblock]::Create($script)) @params