Reputation: 23
I'm trying to use certificates to embed credentials into a Service resource. I've got PKI in the infrastructure and all my test servers are auto-enrolled. I exported their certs locally to work with and have them in my ConfigData as follows:
@{
AllNodes = @(
@{
NodeName = "*"
NeoConfigDestinationPath = "D:\ServerBox\Servers\JRun4\_build\shared\config"
}
@{
NodeName = 'DEVOPS'
Role = @('DSCPullServer')
CertificateFile = "D:\EQ_DSCModule\Certs\DEVOPS.cer"
Thumbprint = "AE4F10AE4141C8726EEEBE888C69FE7ABB3099A8"
}
@{
NodeName = 'Server1'
Role = @('IIS', 'ServerBox', 'DevInt')
CFServices = @("Adobe CF9 1", "Adobe CF9 2", "Adobe CF9 3", "Adobe CF9 4")
CertificateFile = "D:\EQ_DSCModule\Certs\Client1.cer"
Thumbprint = "4FA343A76AEA2B805850190E9C04AA9E2A82A162"
}
@{
NodeName = 'Server2'
Role = @('IIS', 'ServerBox', 'DevInt')
CFServices = @("Adobe CF9 1")
CertificateFile = "D:\EQ_DSCModule\Certs\Client2.cer"
Thumbprint = "0FCB76684F0C74495DEB54F637B50BDA7182483D"
}
)
ServerBoxConfig = @{
SourcePath = "\\Share\Path\DevOps\ServerBox"
DestinationPath = "D:\ServerBox"
}
DevIntConfig = @{
SourcePath = "\\Share\Path\DevOps\DevInt"
DestinationPath = "D:\ServerBox\IIS\wwwroot"
NeoConfigSourcePath = "\\Share\Path\DevOps\ServerConfig\Environments\DevInt\NeoConfig"
}
}
This this is the config script that I'm running:
$webCFDevCred = Get-Credential -Credential "[email protected]"
Configuration EqConfig
{
Import-DSCResource -Module xPSDesiredStateConfiguration
Import-DSCResource -Module cChoco
Node $AllNodes.NodeName {
cChocoInstaller installChoco {
InstallDir = "C:\ProgramData\Chocolatey"
}
}
Node $AllNodes.Where({ $_.role -eq 'DSCPullServer' }).NodeName { ... } #DSCPullServer
Node $AllNodes.Where({ $_.role -eq 'IIS' }).NodeName { ... } #IIS
Node $AllNodes.Where({ $_.role -eq 'ServerBox' }).NodeName {
File ServerBox
{
Ensure = "Present"
Type = "Directory"
Recurse = $true
MatchSource = $true
Force = $true
Checksum = "modifiedDate"
SourcePath = $ConfigurationData.ServerBoxConfig.SourcePath
DestinationPath = $ConfigurationData.ServerBoxConfig.DestinationPath
}
} #ServerBox
Node $AllNodes.Where({ $_.role -eq 'DevInt' }).NodeName {
File DevInt
{
Ensure = "Present"
Type = "Directory"
Recurse = $true
MatchSource = $true
Force = $true
Checksum = "modifiedDate"
SourcePath = $ConfigurationData.DevIntConfig.SourcePath
DestinationPath = $ConfigurationData.DevIntConfig.DestinationPath
DependsOn = "[File]ServerBox"
}
File DevInt_Config
{
Ensure = "Present"
Type = "Directory"
MatchSource = $true
Force = $true
Checksum = "modifiedDate"
SourcePath = $ConfigurationData.DevIntConfig.NeoConfigSourcePath
DestinationPath = $Node.NeoConfigDestinationPath
DependsOn = "[File]ServerBox"
}
#This runs a script to build out the ColdFusion cluster/servers
#Uses the number of services as the param for serverCount
cChocoPackageInstaller installServerBox {
Name = "ServerBox.DevInt -params $($Node.CFServices.Length)"
DependsOn = @("[cChocoInstaller]installChoco", "[File]DevInt_Config")
}
#Sets the services generated by the ServerBox script
$Node.CFServices.ForEach({
Service "Service-$_" {
Name = $_
State = 'Running'
Credential = $webCFDevCred
DependsOn = "[cChocoPackageInstaller]installServerBox"
}
})
} #DevInt
} #Configuration
EqConfig -ConfigurationData .\EQConfigData.psd1 -Output .\EqConfig -Verbose
Function Get-ComputerGuid
{
param (
[Parameter(Mandatory = $true)]
[string]$ComputerName
)
process
{
([guid]([adsisearcher]"(samaccountname=$ComputerName`$)").FindOne().Properties["objectguid"][0]).Guid
}
}
$DSCPullFolder = "C:\Program Files\WindowsPowerShell\DscService\Configuration"
Get-ChildItem .\EqConfig\* -Filter *.mof | ForEach-Object {
$guidMofFile = "$DSCPullFolder\$(Get-ComputerGuid $_.BaseName).mof"
$newMof = copy $_.FullName $guidMofFile -PassThru -Force
$newHash = (Get-FileHash $newMof).hash
[System.IO.File]::WriteAllText("$newMof.checksum", $newHash)
}
Configuration EqLocalConfig
{
Node $AllNodes.NodeName {
LocalConfigurationManager {
AllowModuleOverwrite = 'True'
CertificateID = $Node.Thumbprint
ConfigurationID = $(Get-ComputerGuid $nodeName)
ConfigurationModeFrequencyMins = 15
ConfigurationMode = 'ApplyAndAutoCorrect'
RebootNodeIfNeeded = 'True'
RefreshMode = 'PULL'
DownloadManagerName = 'WebDownloadManager'
DownloadManagerCustomData = (@{ ServerUrl = "https://DEVOPS:443/psdscpullserver.svc" })
}
}
}
EqLocalConfig -ConfigurationData .\EQConfigData.psd1 -Verbose
Set-DscLocalConfigurationManager -Path .\EqLocalConfig -Verbose
As far as I can tell it should work. My MOFs get generated with encrypted passwords inside, but when the client servers pick up the config and get to the Service step, it errors out. Checking the event viewer this is the details on the event:
"This event indicates that failure happens when LCM is processing the configuration. ErrorId is 0x1. ErrorDetail is The SendConfigurationApply function did not succeed.. ResourceId is [Service]Service-Adobe CF9 1 and SourceInfo is D:\EQ_DSCModule\EqConfig.ps1::285::4::Service. ErrorMessage is PowerShell provider MSFT_ServiceResource failed to execute Set-TargetResource functionality with error message: Failed to change 'Credential' property. Message: 'The 'Change' method of 'Win32_Service' failed with error code: '22'.' ."
According to MSDN (https://msdn.microsoft.com/en-us/library/aa384901%28v=vs.85%29.aspx) error code 22 on the Change method means "The account under which this service runs is either invalid or lacks the permissions to run the service." I know the service account works fine and I can add it myself using WMI as follows:
For ($i=0; $i -lt $clusterCount; $i++) {
(Get-WmiObject -Query "SELECT * FROM Win32_Service WHERE Name = 'Adobe CF9 $($i+1)'").Change($null,$null,$null,$null,$null,$null,'[email protected]','password',$null,$null,$null)
}
So if I can add the account using WMI, DSC should be able to as well, right? Ugh!
Ideas?
Upvotes: 0
Views: 694
Reputation: 11
When you use both certificate files and thumbprint (certificateid) the encryption will happen with the certificate file but only the thumbprint (certificateid) you entered gets written to the .mof file. They can easily get out of sync. As a test try adding the certificates to the local machine store and then remove the reference to the certificate files from the script. Regenerate and fix any issues if a certificate can't be found. See if that fixes the issue.
Upvotes: 1