I am not able to make mof signature work. The LCM always give back an error message.
First, I made sure that the mof signature is valid. Doing a Get-AuthenticodeSignature on the mof return Valid.
Second, I configured the LCM with this extra section:
SignedItemType = 'Configuration'
But when I tell the node to go get it’s mof, it returns the following error:
“Failed to open trusted publisher store. The store path is either invalid or does not exist.”
According to the doc, it should use the default Windows trusted publisher store to validate the certificate chain(which I assume is “TrustedPublisher” in the MMC.)
So, not understanding why it cannot open the store(and the event viewer logs mention nothing else) I modifed the section like this:
SignedItemType = ‘Configuration’
TrustedStorePath = “Cert:\LocalMachine\TrustedPublisher”
and now I get this error:
Validating the signer signature trust failed. The signer certificate did not match with any valid code signing certificate that is installed on the node
The signing certificate is from Entrust(so the root cert is already in the Windows Root Store) and I even made sure all the certificates for the certificates chains are in the Trusted Publisher.
Documentation on this feature(mof signature) is horribly lacking, so anyone got a clue what is going wrong here? I would preferably want this to work with scenario A(the one where we do not specify a store).
Can you help me understand a bit about your broader use case? Are you trying to manually create a MOF and then sign it?
Additionally, keep in mind that certificates used for this need to be enabled for DocumentEncryption as a use. Have you verified that?
Indeed, I created a mof from a configuration and then I signed it using Set-AuthenticodeSignature with a code signing certificate from Entrust. Doing a Get-AuthenticodeSignature on the mof then return a “valid” result.
DocumentEncryption is not enabled on that certificate, but I don’t think it should be either?(could be wrong) as the Policy required for signing is DocumentSigning. I know it’s required to encrypt mof files, but it shouldn’t be for signing them?
To be sure, I just ran another test where I tried signing the mof with the certificate we use to encrypt infromations inside MOF files(and that one has the DocumentEncryption policy enabled). Set-AuthenticodeSignature refused to sign the mof using that certificate, stating that “The specified certificate is not suitable for code signing.”
I’m still not sure what you are trying to do. Are you generating the MOF using something other than PowerShell? Signing/encryption happens automatically when using the cmdlets.
Yes, I am using powersehll to generate the MOF. Then I use the cmdlet Set-AuthenticodeSignature to digitally sign it like the documentation(and The DSC Book -great work-) mention. I am not aware of other methods(?)
How to sign configuration and module
•Configuration Files (.MOFs): The existing PowerShell cmdlet Set-AuthenticodeSignature is extended to support signing of MOF files.
The signature is valid, it’s the target node that cannot seem to be able to verify the signature somehow, so it refuse to use the mof.
Also, the weird thing is, the doc mention this:
The Local Configuration Manager performs the following steps to verify the digital signatures.
1.Verify the signature on a configuration file (.MOF) is valid. It uses the PowerShell cmdlet Get-AuthenticodeSignature, which is extended in 5.1 to support MOF signature validation.
2.Verify the certificate authority that authorized the signer is trusted.
So I used Trace-xDscOperation on the target node to get the location of the downloaded mof, and I ran Get-AuthenticodeSignature against the mof. It returns “Valid” as expected. So, if the LCM uses the same cmdlet, why does it fail when it’s doing the check? Bug?
Just fyi I have escalated to the development lead for DSC.
In the mean time if you would like to try the DSC service in Azure, this process will be handled automatically.
Thanks! I guess we won’t be able to use that feature until it’s fixed then. Azure automation is really not an option for us.
I work on the PowerShell DSC team.
Scenario A (the one where you don’t specify a store) definitely has a bug in it.
It look like we are setting the default to ‘cert:\LocalMachine\DSCStore’ which is also the value we use in all of our tests.
So I have filed a bug for the team to fix that, but it will be a while before that fix would be released.
The failure in Scenario B is more of a mystery.
We do call Get-AuthenticodeSignature, but we also do some more certificate retrieval/validation after that.
Based on the error message you are getting, DSC is actually getting past Get-AuthenticodeSignature and failing in that certificate retrieval/validation.
Here’s what we do in that section where your scenario is failing:
- We run Get-AuthenticodeSignature and use the certificate from the result of this cmdlet to compare against.
- We get all certificates we can from the specified certificate store that are not expired
- We run through all the retrieved certificates and try to find one that matches the following:
- The subject of the certificate must match the subject of the certificate retrieved by Get-AuthenticodeSignature
- The thumbprint of the certificate must match the thumbprint of the certificate retrieved by Get-AuthenticodeSignature
- The certificate must have the OID ‘184.108.40.206.220.127.116.11.3’ under the Enhanced Key Usage extension for the certificate. (https://msdn.microsoft.com/en-us/library/windows/desktop/aa378132(v=vs.85).aspx) This should just mean that the certificate can sign code.
From the error message it looks like your scenario is failing somewhere in step 3.
Thanks for the reply and the bug confirmation
I looked at the workflow, and I admit it raised a question. Why try to find the signing certificate on the target node and not only validate that the signature is valid? Our PKI doesn’t do signing certificate(and the team in charge of it gave us a definitive NO about allowing that type of certificate) so we use a code signing certificate from Entrust. Since january 2017, we can only get those certificates on a usb security token that protect the private key. So, distributing that certificate is impractical(and it would probably break every good practice concerning certificates anyway and we would end up as an example of Bad™ in the next book by Don :P)
But, as a test, I exported the public key(exporting the private key from the security token is not even possible) in a .cer and imported it on the target node under Cert:\LocalMachine\my and configured the LCM to use that store. I still got the : Validating the signer signature trust failed. The signer certificate did not match with any valid code signing certificate that is installed on the node.
Second test: I created Cert:\LocalMachine\DSCStore and removed the TrustedStorePath line. You were right, it does look there as I did not get the “Failed to…” message anymore. But I still got the Validating the signer signature trust failed. The signer certificate did not match with any valid code signing certificate that is installed on the node.
I can confirm that the certificate located in Cert:\LocalMachine\DSCStore is the one we used to sign(minus the private key part). It has the same thumbprint and subject as what is reported by Get-AuthenticodeSignature, and it has “Code Signing (18.104.22.168.22.214.171.124.3)” in the Enhanced Key Usage value. Does it actually look for the private key? The only other thing that might cause trouble is that there is an accentuated character in the certificate subject. But it might not be an issue since the accentuated character appear correctly when we do the command
Get-AuthenticodeSignature .\localhost.mof | format-list