XMLOps/New-PublisherLevelRules.psm1
Function New-PublisherLevelRules { <# .SYNOPSIS Creates new Publisher level rules in an XML file Each rules includes the Signers, AllowedSigners, and CiSigners (depending on kernel/user mode) .PARAMETER PublisherSigners The PublisherSigners to be used for creating the rules, they are the output of the BuildSignerAndHashObjects Method .PARAMETER XmlFilePath The path to the XML file to be modified .INPUTS System.Collections.Generic.List[WDACConfig.PublisherSignerCreator] System.IO.FileInfo .OUTPUTS System.Void #> [CmdletBinding()] [OutputType([System.Void])] Param ( [Parameter(Mandatory = $true)][System.Collections.Generic.List[WDACConfig.PublisherSignerCreator]]$PublisherSigners, [Parameter(Mandatory = $true)][System.IO.FileInfo]$XmlFilePath ) Begin { . "$([WDACConfig.GlobalVars]::ModuleRootPath)\CoreExt\PSDefaultParameterValues.ps1" [WDACConfig.VerboseLogger]::Write("New-PublisherLevelRules: There are $($PublisherSigners.Count) Publisher Signers to be added to the XML file") # Load the XML file [System.Xml.XmlDocument]$Xml = Get-Content -Path $XmlFilePath # Define the namespace manager [System.Xml.XmlNamespaceManager]$Ns = New-Object -TypeName System.Xml.XmlNamespaceManager -ArgumentList $Xml.NameTable $Ns.AddNamespace('ns', 'urn:schemas-microsoft-com:sipolicy') # Find the Signers Node [System.Xml.XmlElement]$SignersNode = $Xml.SelectSingleNode('//ns:Signers', $Ns) # Find the ProductSigners Nodes [System.Xml.XmlElement]$UMCI_ProductSigners_Node = $Xml.SelectSingleNode('//ns:SigningScenarios/ns:SigningScenario[@Value="12"]/ns:ProductSigners', $Ns) [System.Xml.XmlElement]$KMCI_ProductSigners_Node = $Xml.SelectSingleNode('//ns:SigningScenarios/ns:SigningScenario[@Value="131"]/ns:ProductSigners', $Ns) # Find the CiSigners Node [System.Xml.XmlElement]$CiSignersNode = $Xml.SelectSingleNode('//ns:CiSigners', $Ns) } Process { foreach ($PublisherData in $PublisherSigners) { #Region Creating Signers # Create signer for each certificate details in the PublisherSigners # Some files are signed by multiple signers foreach ($SignerData in $PublisherData.CertificateDetails) { [System.String]$Guid = [System.Guid]::NewGuid().ToString().replace('-', '').ToUpper() [System.String]$SignerID = "ID_SIGNER_B_$Guid" # Create the new Signer element [System.Xml.XmlElement]$NewSignerNode = $Xml.CreateElement('Signer', $SignersNode.NamespaceURI) $NewSignerNode.SetAttribute('ID', $SignerID) $NewSignerNode.SetAttribute('Name', $SignerData.IntermediateCertName) # Create the CertRoot element and add it to the Signer element [System.Xml.XmlElement]$CertRootNode = $Xml.CreateElement('CertRoot', $SignersNode.NamespaceURI) $CertRootNode.SetAttribute('Type', 'TBS') $CertRootNode.SetAttribute('Value', $SignerData.IntermediateCertTBS) [System.Void]$NewSignerNode.AppendChild($CertRootNode) # Create the CertPublisher element and add it to the Signer element [System.Xml.XmlElement]$CertPublisherNode = $Xml.CreateElement('CertPublisher', $SignersNode.NamespaceURI) $CertPublisherNode.SetAttribute('Value', $SignerData.LeafCertName) [System.Void]$NewSignerNode.AppendChild($CertPublisherNode) # Add the new Signer element to the Signers node [System.Void]$SignersNode.AppendChild($NewSignerNode) #Region Adding signer to the Signer Scenario and CiSigners # For User-Mode files if ($PublisherData.SiSigningScenario -eq '1') { # Check if AllowedSigners node exists, if not, create it $UMCI_Temp_AllowedSignersNode = $UMCI_ProductSigners_Node.SelectSingleNode('ns:AllowedSigners', $Ns) if ($Null -eq $UMCI_Temp_AllowedSignersNode) { [System.Xml.XmlElement]$UMCI_Temp_AllowedSignersNode = $Xml.CreateElement('AllowedSigners', $Ns.LookupNamespace('ns')) [System.Void]$UMCI_ProductSigners_Node.AppendChild($UMCI_Temp_AllowedSignersNode) } # Create Allowed Signers inside the <AllowedSigners> -> <ProductSigners> -> <SigningScenario Value="12"> [System.Xml.XmlElement]$NewUMCIAllowedSignerNode = $Xml.CreateElement('AllowedSigner', $UMCI_Temp_AllowedSignersNode.NamespaceURI) $NewUMCIAllowedSignerNode.SetAttribute('SignerId', $SignerID) [System.Void]$UMCI_Temp_AllowedSignersNode.AppendChild($NewUMCIAllowedSignerNode) # Create a CI Signer for the User Mode Signer [System.Xml.XmlElement]$NewCiSignerNode = $Xml.CreateElement('CiSigner', $CiSignersNode.NamespaceURI) $NewCiSignerNode.SetAttribute('SignerId', $SignerID) [System.Void]$CiSignersNode.AppendChild($NewCiSignerNode) } # For Kernel-Mode files elseif ($PublisherData.SiSigningScenario -eq '0') { # Check if AllowedSigners node exists, if not, create it $KMCI_Temp_AllowedSignersNode = $KMCI_ProductSigners_Node.SelectSingleNode('ns:AllowedSigners', $Ns) if ($Null -eq $KMCI_Temp_AllowedSignersNode) { [System.Xml.XmlElement]$KMCI_Temp_AllowedSignersNode = $Xml.CreateElement('AllowedSigners', $Ns.LookupNamespace('ns')) [System.Void]$KMCI_ProductSigners_Node.AppendChild($KMCI_Temp_AllowedSignersNode) } # Create Allowed Signers inside the <AllowedSigners> -> <ProductSigners> -> <SigningScenario Value="131"> [System.Xml.XmlElement]$NewKMCIAllowedSignerNode = $Xml.CreateElement('AllowedSigner', $KMCI_Temp_AllowedSignersNode.NamespaceURI) $NewKMCIAllowedSignerNode.SetAttribute('SignerId', $SignerID) [System.Void]$KMCI_Temp_AllowedSignersNode.AppendChild($NewKMCIAllowedSignerNode) # Kernel-Mode signers don't need CI Signers } #Endregion Adding signer to the Signer Scenario and CiSigners } #Endregion Creating Signers } } End { # Save the modified XML back to the file $Xml.Save($XmlFilePath) } } Export-ModuleMember -Function 'New-PublisherLevelRules' |