Signing existing OS Configuration Discovery scripts

Very simply, this is an example of how to take existing configuration item discovery scripts that are present in a given Configuration Baseline and sign each of them.  This can be useful if you are importing scripts from the SCAP extensions etc..  Depending on your configuration item source, you may have several hundred scripts to sign.

Hopefully, this helps. (Note, this needs to be run from the CCM:\ drive)

$baselinename = 'My Baseline'

#Get XML version of baseline
$baselinexml = [xml](Get-CMBaselineXMLDefinition -Name $baselinename)

#Get all CI Unique IDs for configitems that are assign to baseline
$baselineconfigItems = $baselinexml.GetElementsByTagName('OperatingSystemReference')
#Filter out individual baseline if needed
#$baselineconfigItems = $baselineconfigItems | Where{$_.LogicalName -match 'LogicalName_01c079c3-f042-4788-bf3c-90b53fdcc159'}

#Get all compliance items (use fast mode at moment)
$arrComplianceItems = Get-CMConfigurationItem -Fast

#ForEach configuration item in configuration baseline
ForEach($configitemID in $baselineconfigItems){
   #Find the matching config item object
   $objconfigItem = $arrComplianceItems | Where{$_.modelname -eq ($configitemID.AuthoringScopeID + '/' + $configitemID.LogicalName)}
   #Update the config item object with all properties
   $objconfigItem = Get-CMConfigurationItem -Id $objconfigItem.CI_ID

   #Get the matching compliance setting
   $objComplianceSetting = Get-cmcompliancesetting -id $objconfigItem.ci_id

   #Get the current discovery script
   $psscript = $objComplianceSetting | Select -expand DiscoveryScript | Where{$_.ScriptLanguage -eq 'Powershell'} | Select -expand Script
      #Save discovery script to temp location
      $filename = (Join-path $env:TEMP -childpath ($configItemid.logicalname + '.ps1'))
      $psscript | out-file $filename -encoding utf8

      #Get the first available code signing cert out of the user store
      $cert = @(gci cert:\currentuser\my -codesigning)[0]

      #Sign file
      $signingvalidity = Set-AuthenticodeSignature $filename $cert –TimestampServer
      if($signingvalidity.status -eq 'Valid'){
         #Save the script in the Configuraiton item object
         Set-CMComplianceSettingScript -InputObject $objconfigitem -DiscoveryScriptFile $filename -DiscoveryScriptLanguage powershell -SettingName $objComplianceSetting.Name
         #Save the updated object to the configuration manager environment
         $objconfigItem | Set-CMConfigurationItem
         write-host "Failed to sign $filename"
      $msg = $configItemID.LogicalName + "does not reference a powershell script"
      write-host $msg


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s