Protecting credentials in Desired State Configuration using certificates
I'm new to DSC and trying to figure out how to make it work for us.
What I'm stuck on is how the credentials are actually protected. My current understanding is that it isn't all that great.
The big three problems are these. How does using a public key as a decryption source really protect those credentials? Which computers need the certificate in push and pull scenarios? What are the best practices for dealing with credentials in light of these issues?
Using a public key of a certificate is good for authenticating the source of a transmission. But using it as a decryption key means that access to the public key of the certificate determines access to the password.
If you have to push the cert to every computer that needs to decrypt MOF files, what is there to stop average users from getting access to the cert and being able to decrypt the MOF? Saying active directory security means that you may as well leave it in plain text and just rely on AD security.
Can someone help me get my head around this?
The Basic Idea
- The host to be configured must have a certificate installed (with private key).
- When setting up the target node's local configuration manager (LCM), you must specify the Thumbprint of that very certificate. This tells the LCM which local cert (or more accurately which cert's private key) will be used to decrypt the credential.
- Your DSC configuration must point to a file that contains the certificate only (public key) of that same certificate. This is done in the configuration data, so you can specify a different cert for each node, if you intend to use the same config for each.
- When the MOF is generated, the public key is used by the machine generating the MOF to encypt the credential.
- When the LCM on the target node retrieves the config from the pull server (in MOF form), it uses the private key of the certificate identified by the thumbprint to decrypt the credential object.
In Some Detail
The public key cannot be used to decrypt, and you are not sharing the private key with the config generation nor distribution machines.
It sounds like you're considering the workflow as though there is a single certificate in use for all credentials. You could do that, but I think the idea is that each node has its own key pair.
"Average users" which I'm taking to mean non-administrative users, are not able to export the private key of a certificate (unless granted the permissions), and since you won't be moving this key around, there's little chance of it being exposed. If the user's are administrators, well then of course they have access.
It's much more likely that storing plain text credentials in a config will be exposed whether it's through the unprocessed powershell config, or the generated MOF. If it's unencrypted, then you'd have to secure:
- The filesystem/network share location where the config is stored
- The fs/share where the generated MOFs are stored
- The fs/share where you store the MOFs on the pull server
- Ensure the pull server is running over SSL (you should do this anyway)
- Ensure there's authentication on the Pull server, otherwise any anonymous query could retrieve a config with exposed credentials.
I think the secure credentials in DSC are done rather nicely, but it's a bit of an ordeal to get set up with it initially.
AD PKI makes this easier
If you're using Enterprise PKI in your AD environment, there's a good chance that each machine is set up for automatic enrollment with the CA, so it already has a machine-specific certificate which renews itself. It has the necessary settings to be used for this purpose.
How I'm Implementing This
Since the tooling is so bare for DSC right now, it's likely that you'll be creating your own workflow for generating configs and writing scripts to assist anyway.
In my case I've got separate scripts for generating the LCM meta MOF and for generating the node's actual config, so my steps for securing credentials are split between both.
In the LCM generation script, I actually query the CA for the domain to find the certificate that corresponds to the hostname of the machine being configured. I retrieve the cert (the CA doesn't have the private key, only the public) and save it to a path for later use. The meta MOF gets configured to use the thumbprint of the cert.
In the node config script I set the configuration data to use the cert file (again public key only). When the MOF is generated the credentials are encrypted with that cert and can only be decrypted with the private key on the specific node.
Reference
I referenced my own experience in the above, but this article was a big help along the way: https://devblogs.microsoft.com/powershell/want-to-secure-credentials-in-windows-powershell-desired-state-configuration
I had to fill in some of the holes myself. One thing to note in the examples they show, is that they provide the Thumprint
in the node config. This isn't necessary for the node configuration; they're just generating the config and LCM meta config at the same time and using the configuration data to store the thumbprint for use there.
That last paragraph might be confusing, but it makes more sense in the context of the article. If you're not generating both configs at the same time then their example seems strange. I tested it; Thumbprint
is not required in the configuration data for encrypting credentials. CertificateFile
is required though, and it must be in configuration data, so if you weren't using config data before, you will be now.