Public/Add-SRDSCNode.ps1
function Add-SRDSCNode { <# .Description Onboards an Datum Node Endpoint into the DSC Pull Server. The calling process uses PowerShell remoting to configure the endpoint (ensure that PowerShell Remoting is enabled on the endpoint). The command supports ConfigurationID and Registration Key (Preferred). If using a ConfigurationID upon registration, will capture and store the Configuration ID locally on the Pull Server, so the build script can associate the NODE to it's Configuration ID. The Registration Key is the preferred way. It onboard the endpoint node and set's the Configuation Name to the . If a Pull Server has already been configured on the LCM endpoint, the process won't perform the onboarding process, however it will still return the ConfigurationID. .PARAMETER NodeName The ComputerName Endpoint. .PARAMETER DSCPullServer The PullServer URL Location .PARAMETER UseConfigurationIDs A switch to register the endpoint using ConfigurationIDs, instead of a Pull Server Registration Key. .PARAMETER Force Overwrite any existing LCM configuration and onboard the Node onto the new DSC Pull Server. .EXAMPLE Add-SRDSCNode -NodeName 'NODE01' -DSCPullServer 'HTTP://DSCPULLSERVER01' -Force Forcibly Adds 'NODE01' to the DSCPullServer 'HTTP://DSCPULLSERVER01' .EXAMPLE Add-SRDSCNode -NodeName 'NODE01' -DSCPullServer 'HTTP://DSCPULLSERVER01' Adds 'NODE01' to the DSCPullServer 'HTTP://DSCPULLSERVER01'. If an LCM configuration already exists, stop. .SYNOPSIS Onboards an Endpoint Node into the DSC Pull Server. #> [CmdletBinding()] param ( [Parameter(Mandatory)] [String] $NodeName, [Parameter(Mandatory)] [String] $DSCPullServer, [Parameter()] [Switch] $UseConfigurationIDs, [Switch] $Force ) Write-Host "[Add-SRDSCNode] Onboarding $NodeName into $DSCPullServer" Write-Host "[Add-SRDSCNode] PowerShell Remoting to $NodeName to Register LCM to $DSCPullServer" $RegistrationKey = $Global:SRDSC.DSCPullServer.PullServerRegistrationKey $CertificateByteArray = Get-Content -LiteralPath "{0}\PowerShell\SRDSC\PullServer.cer" -f $Env:ProgramData -Raw -Encoding Byte # Load the DSC Server Configuration Data $invokeCommandParams = @{ ArgumentList = $DSCPullServer,$Force,$RegistrationKey,$UseConfigurationIDs,$CertificateByteArray ComputerName = $NodeName ErrorAction = 'Stop' } $NodeDSCLCMConfiguration = Invoke-Command @invokeCommandParams -ScriptBlock { param($DSCPullServer, $Force, $RegistrationKey, $UseConfigurationIDs, $CertificateByteArray) # # Functions # function Get-DscSplattedResource { [CmdletBinding()] Param( [String] $ResourceName, [String] $ExecutionName, [hashtable] $Properties ) $stringBuilder = [System.Text.StringBuilder]::new() $null = $stringBuilder.AppendLine("Param([hashtable]`$Parameters)") $null = $stringBuilder.AppendLine(" $ResourceName $ExecutionName { ") foreach($PropertyName in $Properties.keys) { $null = $stringBuilder.AppendLine("$PropertyName = `$(`$Parameters['$PropertyName'])") } $null = $stringBuilder.AppendLine("}") Write-Debug ("Generated Resource Block = {0}" -f $stringBuilder.ToString()) [scriptblock]::Create($stringBuilder.ToString()).Invoke($Properties) } Set-Alias -Name x -Value Get-DscSplattedResource # # Main Code Block # # Test if DSC has been configured on the endpoint. if ((-not($Force.IsPresent)) -and ($null -ne (Get-DscConfigurationStatus -ErrorAction SilentlyContinue))) { # Otherwise return the DSC Configuration with Configuration ID return Get-DscLocalConfigurationManager } # # Install the DSC Certificate # $certificateLocation = 'C:\Windows\Temp\SRDSCClientCertificate.cer' $certificateStore = 'Cert:\LocalMachine\Root' # Remove any existing certificate at the specified location Remove-Item -LiteralPath $certificateLocation -Force -ErrorAction SilentlyContinue # Save the certificate to the file system [IO.File]::WriteAllBytes($certificateLocation, $CertificateByteArray) # Remove any existing certificates with matching subject name from the root store Get-ChildItem $certificateStore -Recurse | Where-Object {$_.Subject -like "*DSC.$ENV:USERDNSDOMAIN"} | Remove-Item -Force -Confirm:$false # Import the certificate into the root store Import-Certificate -FilePath $certificateLocation -CertStoreLocation $certificateStore # # Compile the DSC Resource # # # Settings Resource $DSCResourceSettings = @{ RefreshMode = 'Pull' RefreshFrequencyMins = 30 RebootNodeIfNeeded = $true ConfigurationMode = 'ApplyAndAutoCorrect' } # # ConfigurationRepositoryWeb Resource $DSCResourceConfigurationRepositoryWeb = @{ ServerURL = 'https://{0}:8080/PSDSCPullServer.svc' -f $DSCPullServer } # # Apply Logic. If Configuration ID's are set, use Configuration Id's # Otherwise use registration. # If ConfigurationID's have been specified. Add them in! if ($UseConfigurationIDs.IsPresent) { $DSCResourceSettings.ConfigurationID = [guid]::NewGuid().Guid } else { $DSCResourceConfigurationRepositoryWeb.RegistrationKey = $RegistrationKey $DSCResourceConfigurationRepositoryWeb.ConfigurationNames = @($ENV:COMPUTERNAME) } # # Define the Configuration # [DSCLocalConfigurationManager()] configuration PullClientConfigNames { Node localhost { # # Onboard the machine into DSC and Return the LCM Configuration x -ResourceName 'Settings' -Properties $DSCResourceSettings x -ResourceName 'ConfigurationRepositoryWeb' -ExecutionName 'PullSrv' -Properties $DSCResourceConfigurationRepositoryWeb ReportServerWeb PullSrv { ServerURL = 'https://{0}:8080/PSDSCPullServer.svc' -f $DSCPullServer } } } # Generate the Configuration MOF File PullClientConfigNames -OutputPath C:\Windows\Temp\DSC\ -ErrorAction Stop # Set the LocalConfiguration Set-DscLocalConfigurationManager -Path C:\Windows\Temp\DSC\ -Verbose -ErrorAction Stop # Retrive the ConfigurationID ID Write-Output (Get-DscLocalConfigurationManager) } Write-Host "[Add-SRDSCNode] PowerShell Remoting Completed." Write-Host "[Add-SRDSCNode] LCM Configuration: $($NodeDSCLCMConfiguration | ConvertTo-Json)" if ($UseConfigurationIDs.IsPresent) { Write-Host "[Add-SRDSCNode] Writing ConfigurationID of Node as [SecureString]" # Import existing node registrations from file, if any $DatumLCMConfiguration = @() if (Test-Path -LiteralPath $Global:SRDSC.DatumModule.NodeRegistrationFile) { $NodeRegistrationFile = Import-Clixml -LiteralPath $Global:SRDSC.DatumModule.NodeRegistrationFile # Filter out the existing node to enable rewrites $DatumLCMConfiguration = $NodeRegistrationFile | Where-Object {$_.NodeName -ne $NodeName} } # Add the new node registration to the configuration list $DatumLCMConfiguration += [PSCustomObject]@{ NodeName = $NodeName ConfigurationID = [String]$NodeDSCLCMConfiguration.ConfigurationID | ConvertTo-SecureString -AsPlainText -Force } # Export it again $DatumLCMConfiguration | Export-Clixml -LiteralPath $Global:SRDSC.DatumModule.NodeRegistrationFile } Write-Host "[Add-SRDSCNode] Onboarded." } if ($isModule) { Export-ModuleMember -Function Add-SRDSCNode } |