Using Orchestrator to install a ConfigMgr Linux Client with PKI Certificate

My first blog post will be an extension of a great post by Laurie Rhodes who constructed an Orchestrator runbook to install the Linux SCCM client. HERE
I won't go into much detail about all of the steps in the runbook, but I will detail some of the bits I've added. My plan is to create some other blog posts about running the SCCM client on Linux to provide some more context.

A brief overview of the environment:

  • Multiple Windows forests and logical network locations. (Prod, PreProd, & SystemTest)
  • An SCCM Management Point serving each forest.
  • A SCORCH Runbook Server in each domain.
  • SCCM Management Points communicate on HTTPS.
  • A Windows CA in each forest.

I needed to add the following functionality to this work flow:
  • Execute the SSH commands from an Orchestrator server situated logically close to the target Linux server.
  • Request and export a certificate from the local CA to be used to secure communication from the target Linux server SCCM client and the HTTPS SCCM Management Point.
  • Append the hostname / IP address of the local SCCM management point to /etc/hosts on each Linux system.

Initialize Data

  • Linux Username: Input a user with root privileges on the target Linux system
  • Linux Password: User password.
  • Target IP Address: IP address of target Linux system.
  • Domain: The domain / environment the target Linux system is situated in.
  • System Name: The hostname of the target Linux system

Runbooks

The parent runbook is used to determine which Orchestrator Runbook Server executes the 'ConfigMgr - Install Universal Client' runbook by using the 'Domain' Initialize Data. 




The runbook server is defined in the Invoke Runbook activity property 'Runbook Server'.



The 'ConfigMgr - Install Universal Client' runbook (below) contains the following activities.



The 'Request PFX Certificate' runbook is invoked on the runbook server currently being used by parsing the 'Runbook Server' Published Data to it:


The 'Request PFX Certificate' runbook contains a simple PowerShell script, as described below.

Request and Export a PFX for Linux SCCM Client.

The 'Domain' and 'System Name' (shown as CN) Initialize Data values are parsed into the script which ultimately exports a PFX file to D:\SCORCH ready to be transferred to the target Linux system and used during SCCM client installation.

This is the contents of the PowerShell 'Run .Net Script' activity.

  • Define variables using values from the Orchestrator data bus:

  • Determine the issuing CA server and Certificate Template name using the 'Domain' Initialize Data value.
if ($Domain -like "PREPROD")
{
$CAName = "#SERVERNAME#\PreProd CA"
$TemplateName = "ConfigMgrClientCertificateforExport"
}
elseif ($Domain -like "PROD")
{
$CAName = "#SERVERNAME#\IssuingCA"
$TemplateName = "ConfigMgrClientCertificateforExport"
}
elseif ($Domain -like "ST")
{
$CAName = "#SERVERNAME#\ST CA"
$TemplateName = "ConfigMgrClientCertificateforExport"
}

  • Define a function to remove temporary certificate request files.
function Remove-ReqTempfiles()
{
param(
[String[]]$tempfiles
)
Write-Verbose "Cleanup temp files and pending requests"
   
#delete pending request (if a request exists for the CN)
$certstore = new-object system.security.cryptography.x509certificates.x509Store('REQUEST', 'LocalMachine')
$certstore.Open('ReadWrite')
foreach($certreq in $($certstore.Certificates))
{
if($certreq.Subject -eq "CN=$CN")
{
$certstore.Remove($certreq)
}
}
$certstore.close()

foreach($file in $tempfiles){remove-item ".\$file" -ErrorAction silentlycontinue}
}

  • Remove temporary request files (in case left over from previous requests)
Remove-ReqTempfiles -tempfiles "certreq.inf","certreq.req","$CN.cer","$CN.rsp"
  • Build certificate request file
$file = @"
[NewRequest]
Subject = "CN=$CN"
MachineKeySet = TRUE
KeyLength = 2048
Exportable = TRUE
[RequestAttributes]
CertificateTemplate = "$TemplateName"
"@

Set-Content .\certreq.inf $file
  • Submit certificate request and add to local cert store.
Invoke-Expression -Command "certreq -new certreq.inf certreq.req"
Invoke-Expression -Command "certreq -submit -config `"$CAName`" certreq.req $CN.cer"
Invoke-Expression -Command "certreq -accept $CN.cer"

  • Export PFX file to D:\SCORCH directory
$certpath = "d:\SCORCH\$CN.pfx"
Invoke-Expression -Command "certutil -privatekey -exportPFX -p 'Password' my $CN $certpath"
  • Remove certificate from local cert store, and remove temporary files.
$cert = Get-Childitem "cert:\LocalMachine\My" | where-object {$_.Thumbprint -eq (New-Object System.Security.Cryptography.X509Certificates.X509Certificate2((Get-Item "$CN.cer").FullName,"")).Thumbprint}

$certstore = new-object system.security.cryptography.x509certificates.x509Store('My', 'LocalMachine')
$certstore.Open('ReadWrite')
$certstore.Remove($cert)
$certstore.close() 

Remove-ReqTempfiles -tempfiles "certreq.inf","certreq.req","$CN.cer","$CN.rsp"


The resulting PFX file is transferred to the target Linux system in the 'Transfer Client Files' activity.
I added the following lines to the existing PowerShell script.

$certpath = "{certpath from "Request PFX Certificate"}"

$p = Start-Process cmd.exe -ArgumentList "/c D:\SCORCH\pscp.exe -l $linuxUsername -pw $linuxPassword -C -scp $certpath $linuxUsername`@$Target`:/tmp/" -wait -WindowStyle Hidden -PassThru



Append /etc/hosts with SCCM Management Point

Using an SSH activity, the /etc/hosts file is appended with the hostname and IP address of the corresponding SCCM Management Point for the target Linux system. 
The hostname and IP is determined using PowerShell ('Set MP' activity) and the 'Domain' Initialized Data.

$Domain = "#INITIALIZE-DATA#"

if ($Domain -like "PREPROD")
{
$MP= "#PREPROD-MP-FQDN#"
$MPNetbios = "#PREPROD-MP#"
$IP = "#IP ADDRESS#"
}

elseif ($Domain -like "PROD")
{
$MP= "#PROD-MP-FQDN#"
$MPNetbios = "#PROD-MP#"
$IP = "#IP ADDRESS#"
}
elseif ($Domain -like "ST")
{
$MP= "ST-MP-FQDN#"
$MPNetbios = "#ST-MP#"
$IP = "#IP-ADDRESS#"
}

The published data from this script is as follows:



The SSH command to use this data looks like this:

echo '{IP from "Set MP"}   {MPNetBios from "Set MP"}  {MP from "Set MP"}' >> /etc/hosts


SCCM Client Installation

Using the resulting PFX file and Published Data, the final installation command looks something like the following:

-t sudo /tmp/./install -mp {MP from "Set MP"} /tmp/ccm-Universalx64.tar -sitecode ### -UsePKICert /tmp/{CN from "Request PFX Certificate"}.pfx -NoCRLCheck -certpw #Password# -keepdb -fsp #FSP-Hostname#

Conclusion

The fundamental functions in this runbook were kindly put together by someone else, but with a few extra PowerShell scripts and some clever runbook invocation I was able to achieve my end goal.




0 comments:

Post a Comment

About Me

My photo
Senior Consultant at CDW UK specialising in Microsoft workspace and cloud technologies.