From c62dd1e460028f5b707dfe81b9fa7ea61b9fab8e Mon Sep 17 00:00:00 2001 From: Stephen Valdinger Date: Fri, 6 Sep 2024 16:08:59 -0400 Subject: [PATCH 1/2] (#251) Rework Script Variable Storage Prior to this json files were used to store metadata from each step which helped to generate a README file on the desktop at completion and then the files would be removed. This change converts the stored data to cliXml which allows a more secure storage mechanism, and also will help future efforts to improve idempotency and upgrades of the environment. [skip ci] (fixup) Add additional clixml logic --- Set-SslSecurity.ps1 | 20 ++++++--------- Start-C4bCcmSetup.ps1 | 5 ++-- Start-C4bJenkinsSetup.ps1 | 10 +++----- Start-C4bNexusSetup.ps1 | 10 +++----- Start-C4bSetup.ps1 | 6 +++-- scripts/Get-Helpers.ps1 | 54 +++++++++++---------------------------- 6 files changed, 37 insertions(+), 68 deletions(-) diff --git a/Set-SslSecurity.ps1 b/Set-SslSecurity.ps1 index ccaaa15..690355b 100644 --- a/Set-SslSecurity.ps1 +++ b/Set-SslSecurity.ps1 @@ -60,7 +60,7 @@ param( $Hostname = [System.Net.Dns]::GetHostName(), # API key of your Nexus repo, to add to the source setup on C4B Server. - [string]$NuGetApiKey = $(Get-Content "$env:SystemDrive\choco-setup\logs\nexus.json" | ConvertFrom-Json).NuGetApiKey, + [string]$NuGetApiKey = $($x = Import-Clixml "C:\choco-setup\clixml\nexus.xml" ; [System.Net.NetworkCredential]::new('',$x.NuGetApiKey).Password), # If provided, will skip launching the browser [switch]$SkipBrowserLaunch @@ -207,7 +207,7 @@ process { # Reset the NuGet v3 cache, such that it doesn't capture localhost as the FQDN Remove-NexusRepositoryFolder -RepositoryName ChocolateyInternal -Name v3 - Update-JsonFile -Path "$env:SystemDrive\choco-setup\logs\nexus.json" -Properties @{ + Update-Clixml -Path "$env:SystemDrive\choco-setup\clixml\nexus.xml" -Properties @{ NexusUri = "https://$($SubjectWithoutCn):8443" NexusRepo = $RepositoryUrl ChocoUserPassword = $NexusPw @@ -227,7 +227,7 @@ process { # Add firewall rule for Jenkins netsh advfirewall firewall add rule name="Jenkins-7443" dir=in action=allow protocol=tcp localport=7443 - Update-JsonFile -Path "$env:SystemDrive\choco-setup\logs\jenkins.json" -Properties @{ + Update-Clixml -Path "$env:SystemDrive\choco-setup\clixml\jenkins.xml" -Properties @{ JenkinsUri = "https://$($SubjectWithoutCn):7443" } @@ -316,30 +316,26 @@ Invoke-Expression (`$downloader.DownloadString("http://`$(`$HostName):80/Import- } } - Update-JsonFile -Path "$env:SystemDrive\choco-setup\logs\ccm.json" -Properties @{ + Update-Clixml -Path "$env:SystemDrive\choco-setup\clixml\ccm.xml" -Properties @{ CCMWebPortal = "https://$($SubjectWithoutCn)/Account/Login" CCMServiceURL = "https://$($SubjectWithoutCn):24020/ChocolateyManagementService" - ServiceSalt = $ServiceSaltValue - ClientSalt = $ClientSaltValue + ServiceSalt = $ServiceSaltValue | ConvertTo-SecureString -AsPlainText -Force + ClientSalt = $ClientSaltValue | ConvertTo-SecureString -AsPlainText -Force } # Save useful params to JSON - $SslJson = @{ + [PSCustomObject]@{ CertSubject = $SubjectWithoutCn CertThumbprint = $Certificate.Thumbprint CertExpiry = $Certificate.NotAfter IsSelfSigned = $IsSelfSigned - } - $SslJson | ConvertTo-Json | Out-File "$env:SystemDrive\choco-setup\logs\ssl.json" + } | Export-Clixml "$env:SystemDrive\choco-setup\clixml\ssl.xml" } end { Write-Host 'Writing README to Desktop; this file contains login information for all C4B services.' New-QuickstartReadme - Write-Host 'Cleaning up temporary data' - Remove-JsonFiles - if (-not $SkipBrowserLaunch -and $Host.Name -eq 'ConsoleHost') { $Message = 'The CCM, Nexus & Jenkins sites will open in your browser in 10 seconds. Press any key to skip this.' $Timeout = New-TimeSpan -Seconds 10 diff --git a/Start-C4bCcmSetup.ps1 b/Start-C4bCcmSetup.ps1 index ea9eed5..00a32bf 100644 --- a/Start-C4bCcmSetup.ps1 +++ b/Start-C4bCcmSetup.ps1 @@ -147,14 +147,13 @@ process { & choco @chocoArgs $CcmSvcUrl = choco config get centralManagementServiceUrl -r - $CcmJson = @{ + [pscustomobject]@{ CCMServiceURL = $CcmSvcUrl CCMWebPortal = "http://localhost/Account/Login" DefaultUser = "ccmadmin" DefaultPwToBeChanged = "123qwe" CCMDBUser = $DatabaseUser - } - $CcmJson | ConvertTo-Json | Out-File "$env:SystemDrive\choco-setup\logs\ccm.json" + } | Export-Clixml "$env:SystemDrive\choco-setup\clixml\ccm.xml" Write-Host "Chocolatey Central Management Setup has now completed" -ForegroundColor Green diff --git a/Start-C4bJenkinsSetup.ps1 b/Start-C4bJenkinsSetup.ps1 index 2bb7685..fbc8a05 100644 --- a/Start-C4bJenkinsSetup.ps1 +++ b/Start-C4bJenkinsSetup.ps1 @@ -14,7 +14,7 @@ param( [string]$HostName = $env:ComputerName, # API key of your Nexus repo, for Chocolatey Jenkins jobs to use - [string]$NuGetApiKey = $(Get-Content "$env:SystemDrive\choco-setup\logs\nexus.json" | ConvertFrom-Json).NuGetApiKey + [string]$NuGetApiKey = $($x = Import-Clixml "C:\choco-setup\clixml\nexus.xml" ; [System.Net.NetworkCredential]::new('',$x.NuGetApiKey).Password) ) process { $DefaultEap = $ErrorActionPreference @@ -115,12 +115,10 @@ process { Start-Service -Name Jenkins # Save useful params to JSON - $JenkinsJson = @{ + [PSCustomObject]@{ JenkinsUri = "http://$($HostName):8080" - JenkinsUser = "admin" - JenkinsPw = $JenkinsCred.GetNetworkCredential().Password - } - $JenkinsJson | ConvertTo-Json | Out-File "$env:SystemDrive\choco-setup\logs\jenkins.json" + JenkinsCredential = $JenkinsCred + } | Export-Clixml "$env:SystemDrive\choco-setup\clixml\jenkins.xml" Write-Host 'Jenkins setup complete' -ForegroundColor Green diff --git a/Start-C4bNexusSetup.ps1 b/Start-C4bNexusSetup.ps1 index 90c0ac6..6a2943e 100644 --- a/Start-C4bNexusSetup.ps1 +++ b/Start-C4bNexusSetup.ps1 @@ -115,14 +115,12 @@ process { $null = New-NetFirewallRule @FwRuleParams # Save useful params to JSON - $NexusJson = @{ + [PSCustomObject]@{ NexusUri = "http://localhost:8081" - NexusUser = "admin" - NexusPw = "$($Credential.GetNetworkCredential().Password)" + NexusCredential = $Credential NexusRepo = "$((Get-NexusRepository -Name 'ChocolateyInternal').url)/index.json" - NuGetApiKey = $NugetApiKey - } - $NexusJson | ConvertTo-Json | Out-File "$env:SystemDrive\choco-setup\logs\nexus.json" + NuGetApiKey = $NugetApiKey | ConvertTo-SecureString -AsPlainText -Force + } | Export-Clixml "$env:SystemDrive\choco-setup\clixml\nexus.xml" $ErrorActionPreference = $DefaultEap Stop-Transcript diff --git a/Start-C4bSetup.ps1 b/Start-C4bSetup.ps1 index d710190..6ea8188 100644 --- a/Start-C4bSetup.ps1 +++ b/Start-C4bSetup.ps1 @@ -102,8 +102,10 @@ try { $PkgsDir = Join-Path $FilesDir "files" $TempDir = Join-Path $ChocoPath "temp" $TestDir = Join-Path $ChocoPath "tests" - @($ChocoPath, $FilesDir, $PkgsDir, $TempDir, $TestDir) | ForEach-Object { - $null = New-Item -Path $_ -ItemType Directory -Force -ErrorAction SilentlyContinue + $xmlDir = Join-Path $ChocoPath "clixml" + + @($ChocoPath, $FilesDir, $PkgsDir, $TempDir, $TestDir,$xmlDir) | ForEach-Object { + $null = New-Item -Path $_ -ItemType Directory -Force -ErrorAction Stop } if (-not $PSScriptRoot -or $PSScriptRoot -ne $FilesDir) { diff --git a/scripts/Get-Helpers.ps1 b/scripts/Get-Helpers.ps1 index 7980705..a6b5f3f 100644 --- a/scripts/Get-Helpers.ps1 +++ b/scripts/Get-Helpers.ps1 @@ -2056,7 +2056,7 @@ function Invoke-TextReplacementInFile { } } -function Update-JsonFile { +function Update-Clixml { [CmdletBinding()] param( [Parameter(Mandatory)] @@ -2065,11 +2065,13 @@ function Update-JsonFile { [Parameter(Mandatory)] [hashtable]$Properties ) - $Json = Get-Content -Path $Path | ConvertFrom-Json + #$Json = Get-Content -Path $Path | ConvertFrom-Json + $CliXml = Import-Clixml $Path $Properties.GetEnumerator().ForEach{ - Add-Member -InputObject $Json -MemberType NoteProperty -Name $_.Key -Value $_.Value -Force + Add-Member -InputObject $CliXml -MemberType NoteProperty -Name $_.Key -Value $_.Value -Force } - $Json | ConvertTo-Json | Set-Content -Path $Path + + $CliXml | Export-Clixml $Path -Force } function Set-JenkinsCertificate { @@ -2156,32 +2158,6 @@ function Set-JenkinsCertificate { #endregion #region README functions -function Remove-JsonFiles { - <# -.SYNOPSIS -Removes unnecessary json data files from the system upon completion of the Quickstart Guide. -.PARAMETER JsonPath -The path to the JSON data files. Defaults to 'C:\choco-setup\logs'. -.EXAMPLE -./Start-C4bCleanup.ps1 -.EXAMPLE -./Start-C4bCleanup.ps1 -JsonPath C:\Temp\ -#> - - - [CmdletBinding()] - Param( - [Parameter()] - [String] - $JsonPath = "$env:SystemDrive\choco-setup\logs" - ) - - process { - - Get-ChildItem $JsonPath -Filter '*.json' | Foreach-Object { Remove-Item $_.FullName -Force } - } -} - Function New-QuickstartReadme { <# .SYNOPSIS @@ -2197,9 +2173,9 @@ The host name of the C4B instance. param() process { try { - $CCMData = Get-Content "$env:SystemDrive\choco-setup\logs\ccm.json" | ConvertFrom-Json - $NexusData = Get-Content "$env:SystemDrive\choco-setup\logs\nexus.json" | ConvertFrom-Json - $JenkinsData = Get-Content "$env:SystemDrive\choco-setup\logs\jenkins.json" | ConvertFrom-Json + $CCMData = Import-Clixml "$env:SystemDrive\choco-setup\clixml\ccm.xml" + $NexusData = Import-Clixml "$env:SystemDrive\choco-setup\clixml\nexus.xml" + $JenkinsData = Import-Clixml "$env:SystemDrive\choco-setup\clixml\jenkins.xml" } catch { Write-Error "Unable to read JSON files. Ensure the Quickstart Guide has been completed." } @@ -2215,20 +2191,20 @@ The host name of the C4B instance. # Chocolatey Configuration Values "{{ ccm_encryption_password .*?}}" = "Requested on first run." - "{{ ccm_client_salt .*?}}" = [System.Web.HttpUtility]::HtmlEncode($CCMData.ClientSalt) - "{{ ccm_service_salt .*?}}" = [System.Web.HttpUtility]::HtmlEncode($CCMData.ServiceSalt) - "{{ chocouser_password .*?}}" = [System.Web.HttpUtility]::HtmlEncode($NexusData.ChocoUserPassword) + "{{ ccm_client_salt .*?}}" = [System.Web.HttpUtility]::HtmlEncode([System.Net.NetworkCredential]::new('',$CCMData.ClientSalt).Password) + "{{ ccm_service_salt .*?}}" = [System.Web.HttpUtility]::HtmlEncode([System.Net.NetworkCredential]::new('',$CCMData.ServiceSalt).Password) + "{{ chocouser_password .*?}}" = [System.Web.HttpUtility]::HtmlEncode($NexusData.NexusCredential.GetNetworkCredential().Password) # Nexus Values "{{ nexus_fqdn .*?}}" = ([uri]$NexusData.NexusUri).DnsSafeHost "{{ nexus_port .*?}}" = ([uri]$NexusData.NexusUri).Port - "{{ nexus_password .*?}}" = [System.Web.HttpUtility]::HtmlEncode($NexusData.NexusPw) - "{{ lookup\('file', 'credentials\/nexus_apikey'\) .*?}}" = $NexusJson.NuGetApiKey + "{{ nexus_password .*?}}" = [System.Web.HttpUtility]::HtmlEncode($NexusData.NexusCredential.GetNetworkCredential().Password) + "{{ lookup\('file', 'credentials\/nexus_apikey'\) .*?}}" = [System.Net.NetworkCredential]::new('',$NexusData.NugetApiKey).Password # Jenkins Values "{{ jenkins_fqdn .*?}}" = ([uri]$JenkinsData.JenkinsUri).DnsSafeHost "{{ jenkins_port .*?}}" = ([uri]$JenkinsData.JenkinsUri).Port - "{{ jenkins_password .*?}}" = [System.Web.HttpUtility]::HtmlEncode($JenkinsData.JenkinsPw) + "{{ jenkins_password .*?}}" = [System.Web.HttpUtility]::HtmlEncode($JenkinsData.JenkinsCredential.GetNetworkCredential().Password) } } } From 8be9910a7e1bc754f606aec4df3f911c1d068423 Mon Sep 17 00:00:00 2001 From: James Ruskin Date: Mon, 16 Sep 2024 15:55:35 +0100 Subject: [PATCH 2/2] (#251) Use Single Store for Variables As there's little point separating the store out into CCM / Jenkins / etc anymore, we might as well start treating this like a KeyVault. As an initial step, we add Get and Set commands to the helpers, and default the path to a shared file. --- Set-SslSecurity.ps1 | 40 ++++++++------- Start-C4bCcmSetup.ps1 | 6 ++- Start-C4bJenkinsSetup.ps1 | 8 +-- Start-C4bNexusSetup.ps1 | 6 +-- scripts/Get-Helpers.ps1 | 100 ++++++++++++++++++++++++++++++-------- 5 files changed, 112 insertions(+), 48 deletions(-) diff --git a/Set-SslSecurity.ps1 b/Set-SslSecurity.ps1 index 690355b..81356b4 100644 --- a/Set-SslSecurity.ps1 +++ b/Set-SslSecurity.ps1 @@ -43,7 +43,10 @@ param( [Parameter(ParameterSetName='Subject')] [Parameter(ParameterSetName='Thumbprint')] [string] - $CertificateDnsName, + $CertificateDnsName = $( + if (-not (Get-Command Get-ChocoEnvironmentProperty -ErrorAction SilentlyContinue)) {. $PSScriptRoot\scripts\Get-Helpers.ps1} + Get-ChocoEnvironmentProperty CertSubject + ), # This option security hardens your C4B server, in scenarios where you have a non-self-signed certificate. # It adds a role and user credential to the Nexus server, which is used to authenticate the source setup on a client endpoint. @@ -60,7 +63,10 @@ param( $Hostname = [System.Net.Dns]::GetHostName(), # API key of your Nexus repo, to add to the source setup on C4B Server. - [string]$NuGetApiKey = $($x = Import-Clixml "C:\choco-setup\clixml\nexus.xml" ; [System.Net.NetworkCredential]::new('',$x.NuGetApiKey).Password), + [string]$NuGetApiKey = $( + if (-not (Get-Command Get-ChocoEnvironmentProperty -ErrorAction SilentlyContinue)) {. $PSScriptRoot\scripts\Get-Helpers.ps1} + Get-ChocoEnvironmentProperty NuGetApiKey -AsPlainText + ), # If provided, will skip launching the browser [switch]$SkipBrowserLaunch @@ -207,7 +213,7 @@ process { # Reset the NuGet v3 cache, such that it doesn't capture localhost as the FQDN Remove-NexusRepositoryFolder -RepositoryName ChocolateyInternal -Name v3 - Update-Clixml -Path "$env:SystemDrive\choco-setup\clixml\nexus.xml" -Properties @{ + Update-Clixml -Properties @{ NexusUri = "https://$($SubjectWithoutCn):8443" NexusRepo = $RepositoryUrl ChocoUserPassword = $NexusPw @@ -227,7 +233,7 @@ process { # Add firewall rule for Jenkins netsh advfirewall firewall add rule name="Jenkins-7443" dir=in action=allow protocol=tcp localport=7443 - Update-Clixml -Path "$env:SystemDrive\choco-setup\clixml\jenkins.xml" -Properties @{ + Update-Clixml -Properties @{ JenkinsUri = "https://$($SubjectWithoutCn):7443" } @@ -294,12 +300,9 @@ process { } Install-ChocolateyAgent @agentArgs - } - - else { - - # Agent Setup - $agentArgs = @{ + } else { + # Agent Setup + $agentArgs = @{ CentralManagementServiceUrl = "https://$($SubjectWithoutCn):24020/ChocolateyManagementService" } @@ -316,20 +319,21 @@ Invoke-Expression (`$downloader.DownloadString("http://`$(`$HostName):80/Import- } } - Update-Clixml -Path "$env:SystemDrive\choco-setup\clixml\ccm.xml" -Properties @{ + Update-Clixml -Properties @{ CCMWebPortal = "https://$($SubjectWithoutCn)/Account/Login" CCMServiceURL = "https://$($SubjectWithoutCn):24020/ChocolateyManagementService" - ServiceSalt = $ServiceSaltValue | ConvertTo-SecureString -AsPlainText -Force - ClientSalt = $ClientSaltValue | ConvertTo-SecureString -AsPlainText -Force - } - - # Save useful params to JSON - [PSCustomObject]@{ CertSubject = $SubjectWithoutCn CertThumbprint = $Certificate.Thumbprint CertExpiry = $Certificate.NotAfter IsSelfSigned = $IsSelfSigned - } | Export-Clixml "$env:SystemDrive\choco-setup\clixml\ssl.xml" + } + + if ($Hardened) { + Update-Clixml -Properties @{ + ServiceSalt = ConvertTo-SecureString $ServiceSaltValue -AsPlainText -Force + ClientSalt = ConvertTo-SecureString $ClientSaltValue -AsPlainText -Force + } + } } end { diff --git a/Start-C4bCcmSetup.ps1 b/Start-C4bCcmSetup.ps1 index 00a32bf..2492b67 100644 --- a/Start-C4bCcmSetup.ps1 +++ b/Start-C4bCcmSetup.ps1 @@ -31,6 +31,8 @@ process { $Packages = (Get-Content $PSScriptRoot\files\chocolatey.json | ConvertFrom-Json).packages + Set-ChocoEnvironmentProperty -Name DatabaseUser -Value $DatabaseCredential + # DB Setup Write-Host "Installing SQL Server Express" $chocoArgs = @('upgrade', 'sql-server-express', '-y', '--no-progress') @@ -147,13 +149,13 @@ process { & choco @chocoArgs $CcmSvcUrl = choco config get centralManagementServiceUrl -r - [pscustomobject]@{ + Update-Clixml -Properties @{ CCMServiceURL = $CcmSvcUrl CCMWebPortal = "http://localhost/Account/Login" DefaultUser = "ccmadmin" DefaultPwToBeChanged = "123qwe" CCMDBUser = $DatabaseUser - } | Export-Clixml "$env:SystemDrive\choco-setup\clixml\ccm.xml" + } Write-Host "Chocolatey Central Management Setup has now completed" -ForegroundColor Green diff --git a/Start-C4bJenkinsSetup.ps1 b/Start-C4bJenkinsSetup.ps1 index fbc8a05..76cf5eb 100644 --- a/Start-C4bJenkinsSetup.ps1 +++ b/Start-C4bJenkinsSetup.ps1 @@ -14,7 +14,7 @@ param( [string]$HostName = $env:ComputerName, # API key of your Nexus repo, for Chocolatey Jenkins jobs to use - [string]$NuGetApiKey = $($x = Import-Clixml "C:\choco-setup\clixml\nexus.xml" ; [System.Net.NetworkCredential]::new('',$x.NuGetApiKey).Password) + [string]$NuGetApiKey = $(Get-ChocoEnvironmentProperty NuGetApiKey -AsPlainText) ) process { $DefaultEap = $ErrorActionPreference @@ -114,11 +114,11 @@ process { Write-Host "Starting Jenkins service back up" -ForegroundColor Green Start-Service -Name Jenkins - # Save useful params to JSON - [PSCustomObject]@{ + # Save useful params + Update-Clixml -Properties @{ JenkinsUri = "http://$($HostName):8080" JenkinsCredential = $JenkinsCred - } | Export-Clixml "$env:SystemDrive\choco-setup\clixml\jenkins.xml" + } Write-Host 'Jenkins setup complete' -ForegroundColor Green diff --git a/Start-C4bNexusSetup.ps1 b/Start-C4bNexusSetup.ps1 index 6a2943e..259e48c 100644 --- a/Start-C4bNexusSetup.ps1 +++ b/Start-C4bNexusSetup.ps1 @@ -114,13 +114,13 @@ process { } $null = New-NetFirewallRule @FwRuleParams - # Save useful params to JSON - [PSCustomObject]@{ + # Save useful params + Update-Clixml -Properties @{ NexusUri = "http://localhost:8081" NexusCredential = $Credential NexusRepo = "$((Get-NexusRepository -Name 'ChocolateyInternal').url)/index.json" NuGetApiKey = $NugetApiKey | ConvertTo-SecureString -AsPlainText -Force - } | Export-Clixml "$env:SystemDrive\choco-setup\clixml\nexus.xml" + } $ErrorActionPreference = $DefaultEap Stop-Transcript diff --git a/scripts/Get-Helpers.ps1 b/scripts/Get-Helpers.ps1 index a6b5f3f..58d66cd 100644 --- a/scripts/Get-Helpers.ps1 +++ b/scripts/Get-Helpers.ps1 @@ -40,6 +40,10 @@ function Invoke-Choco { } } +Update-TypeData -TypeName SecureString -MemberType ScriptMethod -MemberName ToPlainText -Force -Value { + [System.Net.NetworkCredential]::new("TempCredential", $this).Password +} + #region Package functions (OfflineInstallPreparation.ps1) if (-not ("System.IO.Compression.ZipArchive" -as [type])) { Add-Type -Assembly 'System.IO.Compression' @@ -2059,14 +2063,21 @@ function Invoke-TextReplacementInFile { function Update-Clixml { [CmdletBinding()] param( - [Parameter(Mandatory)] - [string]$Path, + [Parameter()] + [string]$Path = "$env:SystemDrive\choco-setup\clixml\chocolatey-for-business.xml", [Parameter(Mandatory)] [hashtable]$Properties ) - #$Json = Get-Content -Path $Path | ConvertFrom-Json - $CliXml = Import-Clixml $Path + $CliXml = if (Test-Path $Path) { + Import-Clixml $Path + } else { + if (-not (Test-Path (Split-Path $Path -Parent))) { + $null = mkdir (Split-Path $Path -Parent) -Force + } + [PSCustomObject]@{} + } + $Properties.GetEnumerator().ForEach{ Add-Member -InputObject $CliXml -MemberType NoteProperty -Name $_.Key -Value $_.Value -Force } @@ -2074,6 +2085,55 @@ function Update-Clixml { $CliXml | Export-Clixml $Path -Force } +function Get-ChocoEnvironmentProperty { + [CmdletBinding(DefaultParameterSetName="All")] + param( + [Parameter(ParameterSetName="Specific", Mandatory, ValueFromPipeline, Position=0)] + [string]$Name, + + [Parameter(ParameterSetName="Specific")] + [switch]$AsPlainText + ) + begin { + $Content = Import-Clixml -Path "$env:SystemDrive\choco-setup\clixml\chocolatey-for-business.xml" + } + process { + if ($Name) { + if ($AsPlainText -and $Content.$Name -is [System.Security.SecureString]) { + return $Content.$Name.ToPlainText() + } else { + return $Content.$Name + } + } else { + $Content + } + } +} + +function Set-ChocoEnvironmentProperty { + [CmdletBinding(DefaultParameterSetName="Key")] + param( + [Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName="Key", Position=0)] + [Alias('Key')] + [string]$Name, + + [Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName="Key", Position=1)] + $Value, + + [Parameter(Mandatory, ValueFromPipeline, ParameterSetName="Hashtable")] + [hashtable]$InputObject = @{} + ) + begin { + $Properties = $InputObject + } + process { + $Properties.$Name = $Value + } + end { + Update-Clixml -Path "$env:SystemDrive\choco-setup\clixml\chocolatey-for-business.xml" -Properties $Properties + } +} + function Set-JenkinsCertificate { <# .Synopsis @@ -2173,11 +2233,9 @@ The host name of the C4B instance. param() process { try { - $CCMData = Import-Clixml "$env:SystemDrive\choco-setup\clixml\ccm.xml" - $NexusData = Import-Clixml "$env:SystemDrive\choco-setup\clixml\nexus.xml" - $JenkinsData = Import-Clixml "$env:SystemDrive\choco-setup\clixml\jenkins.xml" + $Data = Get-ChocoEnvironmentProperty } catch { - Write-Error "Unable to read JSON files. Ensure the Quickstart Guide has been completed." + Write-Error "Unable to read stored values. Ensure the Quickstart Guide has been completed." } Copy-Item $PSScriptRoot\ReadmeTemplate.html.j2 -Destination $env:Public\Desktop\Readme.html -Force @@ -2185,26 +2243,26 @@ The host name of the C4B instance. # Working around the existing j2 template, so we can keep them roughly in sync Invoke-TextReplacementInFile -Path $env:Public\Desktop\Readme.html -Replacement @{ # CCM Values - "{{ ccm_fqdn .*?}}" = ([uri]$CCMData.CCMWebPortal).DnsSafeHost - "{{ ccm_port .*?}}" = ([uri]$CCMData.CCMWebPortal).Port - "{{ ccm_password .*?}}" = [System.Web.HttpUtility]::HtmlEncode($CCMData.DefaultPwToBeChanged) + "{{ ccm_fqdn .*?}}" = ([uri]$Data.CCMWebPortal).DnsSafeHost + "{{ ccm_port .*?}}" = ([uri]$Data.CCMWebPortal).Port + "{{ ccm_password .*?}}" = [System.Web.HttpUtility]::HtmlEncode($Data.DefaultPwToBeChanged) # Chocolatey Configuration Values "{{ ccm_encryption_password .*?}}" = "Requested on first run." - "{{ ccm_client_salt .*?}}" = [System.Web.HttpUtility]::HtmlEncode([System.Net.NetworkCredential]::new('',$CCMData.ClientSalt).Password) - "{{ ccm_service_salt .*?}}" = [System.Web.HttpUtility]::HtmlEncode([System.Net.NetworkCredential]::new('',$CCMData.ServiceSalt).Password) - "{{ chocouser_password .*?}}" = [System.Web.HttpUtility]::HtmlEncode($NexusData.NexusCredential.GetNetworkCredential().Password) + "{{ ccm_client_salt .*?}}" = [System.Web.HttpUtility]::HtmlEncode((Get-ChocoEnvironmentProperty ClientSalt -AsPlainText)) + "{{ ccm_service_salt .*?}}" = [System.Web.HttpUtility]::HtmlEncode((Get-ChocoEnvironmentProperty ServiceSalt -AsPlainText)) + "{{ chocouser_password .*?}}" = [System.Web.HttpUtility]::HtmlEncode($Data.NexusCredential.Password.ToPlainText()) # Nexus Values - "{{ nexus_fqdn .*?}}" = ([uri]$NexusData.NexusUri).DnsSafeHost - "{{ nexus_port .*?}}" = ([uri]$NexusData.NexusUri).Port - "{{ nexus_password .*?}}" = [System.Web.HttpUtility]::HtmlEncode($NexusData.NexusCredential.GetNetworkCredential().Password) - "{{ lookup\('file', 'credentials\/nexus_apikey'\) .*?}}" = [System.Net.NetworkCredential]::new('',$NexusData.NugetApiKey).Password + "{{ nexus_fqdn .*?}}" = ([uri]$Data.NexusUri).DnsSafeHost + "{{ nexus_port .*?}}" = ([uri]$Data.NexusUri).Port + "{{ nexus_password .*?}}" = [System.Web.HttpUtility]::HtmlEncode($Data.NexusCredential.Password.ToPlainText()) + "{{ lookup\('file', 'credentials\/nexus_apikey'\) .*?}}" = Get-ChocoEnvironmentProperty NugetApiKey -AsPlainText # Jenkins Values - "{{ jenkins_fqdn .*?}}" = ([uri]$JenkinsData.JenkinsUri).DnsSafeHost - "{{ jenkins_port .*?}}" = ([uri]$JenkinsData.JenkinsUri).Port - "{{ jenkins_password .*?}}" = [System.Web.HttpUtility]::HtmlEncode($JenkinsData.JenkinsCredential.GetNetworkCredential().Password) + "{{ jenkins_fqdn .*?}}" = ([uri]$Data.JenkinsUri).DnsSafeHost + "{{ jenkins_port .*?}}" = ([uri]$Data.JenkinsUri).Port + "{{ jenkins_password .*?}}" = [System.Web.HttpUtility]::HtmlEncode($Data.JenkinsCredential.Password.ToPlainText()) } } }