Skip to content

Commit

Permalink
(chocolatey#240) Parameterize setup
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
steviecoaster committed Dec 6, 2024
1 parent 7865b78 commit c1f8e77
Show file tree
Hide file tree
Showing 5 changed files with 296 additions and 52 deletions.
36 changes: 6 additions & 30 deletions Set-SslSecurity.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -227,37 +227,13 @@ process {

$ClientSaltValue = New-CCMSalt
$ServiceSaltValue = New-CCMSalt
$ScriptBlock = @"
`$ClientCommunicationSalt = '$ClientSaltValue'
`$ServiceCommunicationSalt = '$ServiceSaltValue'
`$FQDN = '$SubjectWithoutCN'
`$NexusUserPW = '$NexusPw'
# Touch NOTHING below this line
`$User = 'chocouser'
`$SecurePassword = `$NexusUserPW | ConvertTo-SecureString -AsPlainText -Force
`$RepositoryUrl = "https://`$(`$fqdn):8443/repository/ChocolateyInternal/index.json"
`$credential = [pscredential]::new(`$user, `$securePassword)
`$downloader = [System.Net.WebClient]::new()
`$downloader.Credentials = `$credential
`$script = `$downloader.DownloadString("https://`$(`$FQDN):8443/repository/choco-install/ClientSetup.ps1")
`$params = @{
Credential = `$Credential
ClientSalt = `$ClientCommunicationSalt
ServiceSalt = `$ServiceCommunicationSalt
InternetEnabled = `$true
RepositoryUrl = `$RepositoryUrl
}
& ([scriptblock]::Create(`$script)) @params
"@

$ScriptBlock | Set-Content -Path $EndpointScript

Invoke-TextReplacementInFile -Path $EndpointScript -Replacement @{
"{{ ClientSaltValue }}" = $ClientSaltValue
"{{ ServiceSaltValue }}" = $ServiceSaltValue
"{{ FQDN }}" = $SubjectWithoutCn
}

# Agent Setup
$agentArgs = @{
CentralManagementServiceUrl = "https://$($SubjectWithoutCn):24020/ChocolateyManagementService"
Expand Down
4 changes: 4 additions & 0 deletions modules/C4B-Environment/C4B-Environment.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -2262,6 +2262,10 @@ The host name of the C4B instance.
"{{ jenkins_fqdn .*?}}" = ([uri]$Data.JenkinsUri).DnsSafeHost
"{{ jenkins_port .*?}}" = ([uri]$Data.JenkinsUri).Port
"{{ jenkins_password .*?}}" = [System.Web.HttpUtility]::HtmlEncode($Data.JenkinsCredential.Password.ToPlainText())

# Nexus Chocolatey Source Credential values
"{{ nexus_client_username .*?}}" = 'chocouser'
"{{ nexus_client_password .*?}}" = $Data.ChocoUserPassword
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions modules/C4B-Environment/ReadmeTemplate.html.j2
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,15 @@ function CopyToClipboard(id)
<td>Chocolatey Central Management Service Salt</td>
<td><a href="#" class="strip-decoration" onclick="CopyToClipboard('ccmservice');return false;"><div id="ccmservice" class="pw blurry-text">{{ ccm_service_salt | e }}</div></a></td>
</tr>
<tr>
<td>Nexus Repository Source Username</td>
<td><a href="#" class="strip-decoration" onclick="CopyToClipboard('nexususername');return false;"><div id="nexususername" class="pw blurry-text">{{ nexus_client_username | e }}</div></a></td>
</tr>
<tr>
<td>Nexus Repository Source Password</td>
<td><a href="#" class="strip-decoration" onclick="CopyToClipboard('nexuspassword');return false;"><div id="nexuspassword" class="pw blurry-text">{{ nexus_client_password | e }}</div></a></td>
</tr>

</table>
<blockquote>
<h3>📝 <strong>Note</strong></h3>
Expand Down
180 changes: 167 additions & 13 deletions scripts/ClientSetup.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand All @@ -41,19 +41,43 @@ 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,

#Install the Chocolatey Licensed Extension with right-click context menus available
[Parameter()]
[Switch]
$InternetEnabled
$IncludePackageTools,

# 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
)

Set-ExecutionPolicy Bypass -Scope Process -Force
Expand All @@ -69,11 +93,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

}
}

Expand All @@ -87,7 +114,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"
}
Expand Down Expand Up @@ -118,18 +146,19 @@ 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'"

choco upgrade chocolatey-license -y --source="'ChocolateyInternal'"
choco upgrade chocolatey.extension -y --params="'/NoContextMenu'" --source="'ChocolateyInternal'" --no-progress
if (-not $IncludePackageTools) {
choco upgrade chocolatey.extension -y --params="'/NoContextMenu'" --source="'ChocolateyInternal'" --no-progress
}
else {
Write-Warning "IncludePackageTools was passed. Right-Click context menus will be available for installers, .nupkg, and .nuspec file types!"
choco upgrade chocolatey.extension -y --source="'ChocolateyInternal'" --no-progress
}
choco upgrade chocolateygui -y --source="'ChocolateyInternal'" --no-progress
choco upgrade chocolateygui.extension -y --source="'ChocolateyInternal'" --no-progress

Expand Down Expand Up @@ -158,3 +187,128 @@ 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'
}
#>

$AdditionalConfiguration.GetEnumerator() | ForEach-Object {
$c = [System.Collections.Generic.list[string]]::new()
$c.Add('config')
$c.Add('set')
$c.Add("--name='$($_.Key)'")
$c.Add("--value='$($_.Value)'")

& choco @c
}
}

if ($AdditionalFeatures) {
<#
We expect to pass in feature information as a hashtable with the following shape:
@{
Name = useBackgroundservice
State = 'Enabled'
}
#>
$AdditionalFeatures.GetEnumerator() | ForEach-Object {

$c = [System.Collections.Generic.list[string]]::new()
$c.Add('feature')

$state = switch ($_.Value) {
'Enabled' { 'enable' }
'Disabled' { 'disable' }
default { Write-Error 'State must be either Enabled or Disabled' }
}

$c.Add($state)
$c.add("--name='$($_.Key)'")
& 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)'") }
}
}

& choco @c
}

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') }
}

#Ensure packages install and they don't flood the console output
$c.Add('-y')
$c.Add('--no-progress')

& choco @c
}
}
Loading

0 comments on commit c1f8e77

Please sign in to comment.