{"id":1851,"date":"2014-01-31T16:10:00","date_gmt":"2014-01-31T16:10:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/powershell\/2014\/01\/31\/want-to-secure-credentials-in-windows-powershell-desired-state-configuration\/"},"modified":"2023-05-16T04:40:41","modified_gmt":"2023-05-16T12:40:41","slug":"want-to-secure-credentials-in-windows-powershell-desired-state-configuration","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell\/want-to-secure-credentials-in-windows-powershell-desired-state-configuration\/","title":{"rendered":"Want to secure credentials in Windows PowerShell Desired State Configuration?"},"content":{"rendered":"<div class=\"WordSection1\">\n<p class=\"MsoTitle\">As you start using Windows PowerShell Desired State Configuration (DSC), you might need to specify credentials for resources. In a <a href=\"https:\/\/devblogs.microsoft.com\/powershell\/hungry-for-more-windows-powershell-desired-state-configuration-resources\/\">previous post<\/a> we showed you how to define a resource that has a credential property.\u00a0 In this post, I\u2019ll discuss how to properly encrypt credentials when used in a DSC configuration.<\/p>\n<h2>Prerequisites<\/h2>\n<p class=\"MsoNormal\">First, let us discuss the requirements to encrypt a DSC configuration.<\/p>\n<ul>\n<li>You must have an Encryption capable certificate on the target node in the Local Computer\u2019s Personal Store (in PowerShell the path to the store is Cert:\\LocalMachine\\My, we used the workstation authentication template, see all templates <a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/cc740061(v=WS.10).aspx\">here<\/a>.)<\/li>\n<li>If you are running the configuration, from a separate machine than the target node, you must export the public key of the certificate and import it on the machine you will be running the configuration from.<\/li>\n<\/ul>\n<p class=\"MsoListParagraphCxSpLast\" style=\"margin-left: 1in; text-indent: -0.25in;\"><span style=\"font-family: 'Courier New';\">o<span style=\"font: 7pt 'Times New Roman';\">\u00a0\u00a0 <\/span><\/span>It is important that you keep the private key secure.\u00a0 Since the public key is all that is needed to encrypt, I recommend you only export the public key to the machine you are writing your configurations on in order to keep the private key more secure.<\/p>\n<h2>Assumptions<\/h2>\n<p class=\"MsoNormal\">For this article I\u2019m going to assume:<\/p>\n<ul>\n<li>You are using something like Active Directory Certificate Authority to issue and distribute the encryption certificates.<\/li>\n<li>Administrator access to the target node must be properly secured, as anyone with administrator access to the target node should be trusted with the credentials as the administrators can decrypt the credentials with enough effort.<\/li>\n<\/ul>\n<h2>Overview<\/h2>\n<p class=\"MsoNormal\">In order to encrypt credentials in a DSC configuration, you must follow a process.\u00a0 You must have a certificate on each target node which supports encryption.\u00a0 After that, you must have the public key and thumbprint of the certificate on the machine you are authoring the configuration on.\u00a0 The public key must be provided using the <a href=\"https:\/\/devblogs.microsoft.com\/powershell\/separating-what-from-where-in-powershell-dsc\/\">configuration data<\/a>, and I\u2019ll show you how to provide the thumbprint using configuration data as well.\u00a0 You must write a configuration script which configures the machine using the credentials, and sets up decryption by configuring the target node\u2019s <a href=\"https:\/\/devblogs.microsoft.com\/powershell\/understanding-meta-configuration-in-windows-powershell-desired-state-configuration\/\">Local Configuration Manager<\/a> (LCM) to decrypt the configuration using the encryption certificate as identified by its thumbprint.\u00a0 Finally, you must run the configuration, including, setting the LCM settings and starting the DSC configuration.<\/p>\n<p class=\"MsoNormal\"><a href=\"https:\/\/devblogs.microsoft.com\/powershell\/wp-content\/uploads\/sites\/30\/2014\/01\/3264.Diagram1_thumb_70D51AC4.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-19978\" src=\"https:\/\/devblogs.microsoft.com\/powershell\/wp-content\/uploads\/sites\/30\/2014\/01\/3264.Diagram1_thumb_70D51AC4.png\" alt=\"Diagram1\" width=\"629\" height=\"208\" srcset=\"https:\/\/devblogs.microsoft.com\/powershell\/wp-content\/uploads\/sites\/30\/2014\/01\/3264.Diagram1_thumb_70D51AC4.png 629w, https:\/\/devblogs.microsoft.com\/powershell\/wp-content\/uploads\/sites\/30\/2014\/01\/3264.Diagram1_thumb_70D51AC4-300x99.png 300w\" sizes=\"(max-width: 629px) 100vw, 629px\" \/><\/a><\/p>\n<h2>Configuration Data<\/h2>\n<p class=\"MsoNormal\">When dealing with encryption of DSC configuration, you must understand DSC <a href=\"https:\/\/devblogs.microsoft.com\/powershell\/separating-what-from-where-in-powershell-dsc\/\">configuration data<\/a>. This structure describes, to a configuration, the list of nodes to be operated on, if credentials in a configuration should be encrypted or not for each node, how credential will be encrypted, and other information you want to include.\u00a0 Below is an example of configuration data for a machine named \u201ctargetNode\u201d, which I\u2019d like to encrypt using a public key I\u2019ve exported and saved to \u201cC:\\publicKeys\\targetNode.cer\u201d.<\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">$ConfigData=\u00a0\u00a0\u00a0 @{\r\nAllNodes = @(\r\n@{\r\n# The name of the node we are describing\r\nNodeName = \"targetNode\"\r\n\r\n# The path to the .cer file containing the\r\n# public key of the Encryption Certificate\r\n# used to encrypt credentials for this node\r\nCertificateFile = \"C:\\publicKeys\\targetNode.cer\"\r\n\r\n# The thumbprint of the Encryption Certificate\r\n# used to decrypt the credentials on target node\r\nThumbprint = \"AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8\"\r\n\u00a0\u00a0\u00a0};\r\n );\r\n}<\/code><\/pre>\n<h2>Configuration Script<\/h2>\n<p class=\"MsoNormal\">After we have the configuration data, we can start building our configuration.\u00a0 Since credential are important to keep secure, you should always take the credential as a parameter to your configuration.\u00a0 This is so the credentials are stored for the shortest time possible.\u00a0 Below I\u2019ll give an example of copying a file from a share that is secured to a user.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">configuration CredentialEncryptionExample\r\n{\r\nparam(\r\n[Parameter(Mandatory=$true)]\r\n[ValidateNotNullorEmpty()]\r\n[PsCredential] $credential\r\n)\r\n\r\n\r\n\u00a0\u00a0\u00a0 Node $AllNodes.NodeName\r\n{\r\nFile exampleFile\r\n{\r\nSourcePath = \"\\\\Server\\share\\path\\file.ext\"\r\nDestinationPath = \"C:\\destinationPath\"\r\nCredential = $credential\r\n}\r\n}\r\n}<\/code><\/pre>\n<p class=\"MsoNormal\" style=\"margin-bottom: 0pt; background: white; line-height: normal;\"><span style=\"font-size: 9pt; font-family: 'Lucida Console';\">When you run CredentialEncryptionExample, DSC will prompt your for the credential and encrypt the mof using the CertificateFile associated with the node in the configuration data.<\/span><\/p>\n<p class=\"MsoNormal\" style=\"margin-bottom: 0pt; background: white; line-height: normal;\"><span style=\"font-size: 9pt; font-family: 'Lucida Console';\">\u00a0<\/span><\/p>\n<h2>Setting up Decryption<\/h2>\n<p class=\"MsoNormal\" style=\"margin-bottom: 0pt; background: white; line-height: normal;\"><span style=\"font-size: 9pt; font-family: 'Lucida Console';\">There is still one issue.\u00a0 When you run <\/span><a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/dn521623.aspx\"><span style=\"font-size: 9pt; font-family: 'Lucida Console';\">Start-DscConfiguration<\/span><\/a><span style=\"font-size: 9pt; font-family: 'Lucida Console';\">, the Local Configuration Manager (LCM) of target node does not know which certificate to use to decrypt the credentials.\u00a0 We need to add a LocalConfigurationManager resource to tell it.\u00a0 You must set the CertificateId to the thumbprint of the certificate.\u00a0 The first question becomes how to get the thumbprint.\u00a0 Below is an example of how to find a local certificate that would work for encryption (you may need to customize this to find the exact certificate you want to use.)<\/span><\/p>\n<p class=\"MsoNormal\" style=\"margin-bottom: 0pt; background: white; line-height: normal;\"><span style=\"font-size: 9pt; font-family: 'Lucida Console';\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\"># Get the certificate that works for encryption\r\nfunction Get-LocalEncryptionCertificateThumbprint\r\n{\r\n(dir Cert:\\LocalMachine\\my) | %{\r\n# Verify the certificate is for Encryption and valid\r\nif ($_.PrivateKey.KeyExchangeAlgorithm -and $_.Verify())\r\n{\r\nreturn $_.Thumbprint\r\n}\r\n}\r\n}<\/code><\/pre>\n<p class=\"MsoNormal\" style=\"margin-bottom: 0pt; background: white; line-height: normal;\"><span style=\"font-size: 9pt; font-family: 'Lucida Console';\">\u00a0<\/span><\/p>\n<p class=\"MsoNormal\" style=\"margin-bottom: 0pt; background: white; line-height: normal;\"><span style=\"font-size: 9pt; font-family: 'Lucida Console';\">After we have the thumbprint, we use this to build the configuration data (given in the above configuration data example.)\u00a0 Below is an example of the updated configuration with the LocalConfigurationManager resource, getting the value from the node in the configuration data.<\/span><\/p>\n<p class=\"MsoNormal\" style=\"margin-bottom: 0pt; background: white; line-height: normal;\"><span style=\"font-size: 9pt; font-family: 'Lucida Console';\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">configuration CredentialEncryptionExample\r\n{\r\nparam(\r\n[Parameter(Mandatory=$true)]\r\n[ValidateNotNullorEmpty()]\r\n[PsCredential] $credential\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 )\r\n\r\n\r\n\u00a0\u00a0\u00a0 Node $AllNodes.NodeName\r\n{\r\nFile exampleFile\r\n{\r\nSourcePath = \"\\\\Server\\share\\path\\file.ext\"\r\nDestinationPath = \"C:\\destinationPath\"\r\nCredential = $credential\r\n}\r\n\r\nLocalConfigurationManager\r\n{\r\n\u00a0CertificateId = $node.Thumbprint\r\n}\r\n}\r\n}<\/code><\/pre>\n<h2>Running the Configuration<\/h2>\n<p class=\"MsoNormal\">From this point, we need to run the configuration, it will output one *.meta.mof to configure LCM to decrypt the credentials using the certificate installed to the local machine store identified by the thumbprint, and one mof to apply the configuration.\u00a0 First, you will need to use <a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/dn521621.aspx\">Set-DscLocalConfigurationManager<\/a> to apply the *.meta.mof and then, Start-DscConfiguration to apply the configuration.\u00a0 Here is an example of how you would run this:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">Write-Host \"Generate DSC Configuration...\"\r\n\r\nCredentialEncryptionExample -ConfigurationData $ConfigData -OutputPath .\\CredentialEncryptionExample\r\n\r\n\r\nWrite-Host \"Setting up LCM to decrypt credentials...\"\r\n\r\nSet-DscLocalConfigurationManager .\\CredentialEncryptionExample -Verbose\r\n\r\nWrite-Host \"Starting Configuration...\"\r\nStart-DscConfiguration .\\CredentialEncryptionExample -wait -Verbose<\/code><\/pre>\n<p class=\"MsoNormal\" style=\"margin-bottom: 0pt; background: white; line-height: normal;\"><span style=\"font-size: 9pt; font-family: 'Lucida Console';\">\u00a0<\/span><\/p>\n<p class=\"MsoNormal\" style=\"margin-bottom: 0pt; background: white; line-height: normal;\"><span style=\"font-size: 9pt; font-family: 'Lucida Console';\">This example would push the configuration to the target node.\u00a0 If you reference our blog on how to setup a pull configuration, you can modify the setting in the LocalConfigurationManager resource and use these steps to deploy this using a pull server.<\/span><\/p>\n<h2>Summary<\/h2>\n<p class=\"MsoNormal\">You should be able to build a sample that uses credentials securely in DSC using the information in this post.\u00a0 I have written a more complete sample and have attached the code here:<\/p>\n<div id=\"scid:8eb9d37f-1541-4f29-b6f4-1eea890d4876:b0277b82-8d62-4765-a391-5b769ec77a79\" class=\"wlWriterEditableSmartContent\" style=\"float: none; margin: 0px; padding: 0px;\">\n<div><a title=\"Credential Sample Module\" href=\"https:\/\/devblogs.microsoft.com\/00\/00\/00\/63\/74\/6560.CredentialSample.psm1.txt\" target=\"_blank\" rel=\"noopener\">CredentialSample.psm1<\/a><\/div>\n<\/div>\n<p class=\"MsoNormal\">The sample expands on what we discussed here and includes a helper cmdlet to export and copy the public keys to the local machine and an example how to use it.<\/p>\n<p class=\"MsoNormal\">Travis Plunk<\/p>\n<p class=\"MsoNormal\">Windows PowerShell DSC Test<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>As you start using Windows PowerShell Desired State Configuration (DSC), you might need to specify credentials for resources. In a previous post we showed you how to define a resource that has a credential property.\u00a0 In this post, I\u2019ll discuss how to properly encrypt credentials when used in a DSC configuration. Prerequisites First, let us [&hellip;]<\/p>\n","protected":false},"author":600,"featured_media":13641,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[142,150,248,251,345,348],"class_list":["post-1851","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell","tag-desired-state-configuration","tag-dsc","tag-powershell","tag-powershell-4-0","tag-windows-powershell-4-0","tag-windows-powershell-desired-state-configuration"],"acf":[],"blog_post_summary":"<p>As you start using Windows PowerShell Desired State Configuration (DSC), you might need to specify credentials for resources. In a previous post we showed you how to define a resource that has a credential property.\u00a0 In this post, I\u2019ll discuss how to properly encrypt credentials when used in a DSC configuration. Prerequisites First, let us [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/1851","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/users\/600"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/comments?post=1851"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/1851\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media\/13641"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media?parent=1851"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/categories?post=1851"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/tags?post=1851"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}