Part I.5: Creating a user for our Testlab with DSC
Being that I am a creature of pure distilled vanity, I often reread my articles and blog posts after the fact to make sure that I wrote well and don’t have any typos. Well, when I reread my last post, I realized that I forgot to add the step of making a User Account with PowerShell DSC! Whoops!
As it turns out, actually creating a user with DSC had me ready to pull my hair off in frustration, so to save you intrepid Googlers from this pain, I’ve outlined what you SHOULDN’T do, and also have a working easy to understand demo in the bottom.
Add a User Resource to our DSC Config
So, building on our DSC Config from last week; when we want to add a new DSC Resource, the first start is to run Get-DSCResource and look at what Properties we can (and need to) focus on.
Get-DscResource User | select -ExpandProperty Properties
Based on what we see above, we should be good to add the following under xComputer
User LocalAdmin {
UserName = $UserName
DependsOn = '[xComputer]NewNameAndWorkGroup'
Description = 'Our new local admin'
Disabled = $false
Ensure = 'Present'
FullName = 'Stephen FoxDeploy'
Password = '$Password'
PasswordChangeRequired = $false
PasswordNeverExpires = $true
}
You can see that we added a few variables there, so let’s go add them all to our Parameter block.
Change our params block in this script to the following
param
(
[string[]]$NodeName ='localhost',
[Parameter(Mandatory)][string]$MachineName,
[Parameter(Mandatory)][string]$WorkGroupName,
[Parameter()][string]$UserName,
[Parameter()][string]$Password
)
Now let’s invoke it…
TestLab -MachineName DSCDC01 `
-WorkGroupName TESTLAB `
-Password 'myRootPw' `
-UserName 'Stephen FoxDeploy'
ERROR :(
Write-NodeMOFFile : Invalid MOF definition for node 'localhost': Exception calling 'ValidateInstanceText' with '1' argument(s): 'Convert property 'Password' value from type 'STRING' to type 'INSTANCE' failed At line:37, char:2 Buffer: onName = 'TestLab'; };^
Fix: Convert property value from type string to type instance failed
What?!? Maybe my brain just doesn’t work so good, but I had a really hard time understanding what this message meant: Convert Property Value from type String to type Instance. So I took a peek at TechNet.
Checking TechNet, I see this example of how to use the DSC User Resource(I’ve actually bolded the part that was causing me grief, let’s see if you can figure it out quicker than I could!):
```User UserExample { Ensure = “Present” “Absent” UserName = “SomeName” Password = $passwordCred DependsOn = “[Group]GroupExample” }
Let's look at the error message again…
"Convert property 'Password' value from type 'STRING' to type 'INSTANCE' failed
Hmm…If converting from a string failed, and TechNet says it needs to be a Credential object instead…! Wait! PowerShell is telling me I can't give the PW as a string, it actually has to be a credential object! Not sure why it took me so long to understand this. Actually, if we take a look at the output from Get-DSCResource, it even says right there what type to provide the data in.

So, let's replace our -PassWord 'RootPW' with a parenthesis with Get-Credential and see what happens...
```powershell
$cred = (Get-Credential -UserName 'FoxDeploy' -Message 'Enter New Password')
TestLab -MachineName DSCDC01 `
-WorkGroupName TESTLAB `
-Password $cred `
-UserName 'FoxDeploy'
Fix: Storing passwords as plain text is not recommended
Running the cmd above gives us…some more blood in the water, but this is great because we’ve solved the first problem!
ConvertTo-MOFInstance : System.InvalidOperationException error processing property 'Password' OF TYPE 'User': Converting and storing encrypted passwords as plain text is not recommended. For more information on securing credentials in MOF file, please refer to MSDN blog: http://go.microsoft.com/fwlink/?LinkId=393729
Hey, at least we’re getting somewhere! This is probably one of the most informative error messages I’ve ever had in PowerShell! It’s saying hey, you can’t do this, here is a link with more info. I like it! Much better than before.
I did some googling and found this article on the topic, it turns out we need to specify a -ConfigurationData parameter, which will allow us to tell PS to, just this once, ignore our bad behavior password.
Let’s throw this bad boy on there…
$configData = @{
AllNodes = @(
@{
NodeName = 'localhost';
PSDscAllowPlainTextPassword = $true
}
)
}
Now, to run it, one last time!
BLAM! Let’s apply it!
RESULTS
[[xComputer]NewNameAndWorkgroup] Checking if computer name is DSCDC01
[[xComputer]NewNameAndWorkgroup] Checking if workgroup name is TESTLAB
[[xComputer]NewNameAndWorkgroup] in 0.2420 seconds.
[[xComputer]NewNameAndWorkgroup]
[[User]LocalAdmin] A user with the name FoxDeploy does not exist.
[[User]LocalAdmin] in 2.4380 seconds.
[[User]LocalAdmin]
[[User]LocalAdmin] Configuration of user FoxDeploy started.
[[User]LocalAdmin] Performing the operation 'Add' on target 'User: FoxDeploy'.
[[User]LocalAdmin] User FoxDeploy created successfully.
[[User]LocalAdmin] Configuration of user FoxDeploy completed successfully.
[[User]LocalAdmin] in 2.5090 seconds.
Now, let’s look to see if our User was created
Ok, that’s damned sexy
Completed DSC File
This DSC config will rename our PC, join it to a workgroup, and then add a new local user to the machine. When you run this, you’ll be prompted to provide the PW for the new local user. Make sure to change the -Username value to a name you’d like to use.
cconfiguration TestLab
{
param
(
[string[]]$NodeName ='localhost',
[Parameter(Mandatory)][string]$MachineName,
[Parameter(Mandatory)][string]$WorkGroupName,
[Parameter()][string]$UserName,
[Parameter()]$Password
)
#Import the required DSC Resources
Import-DscResource -Module xComputerManagement
Node $NodeName
{
xComputer NewNameAndWorkgroup
{
Name = $MachineName
WorkGroupName = $WorkGroupName
}
User LocalAdmin {
UserName = $UserName
Description = 'Our new local admin'
Ensure = 'Present'
FullName = 'Stephen FoxDeploy'
Password = $Password
PasswordChangeRequired = $false
PasswordNeverExpires = $true
DependsOn = '[xComputer]NewNameAndWorkGroup'
}
}
}
$configData = 'a'
$configData = @{
AllNodes = @(
@{
NodeName = 'localhost';
PSDscAllowPlainTextPassword = $true
}
)
}
#See whats needs to be configured
# Get-DscResource User | select -ExpandProperty Properties | select -expand name
TestLab -MachineName DSCDC01 -WorkGroupName TESTLAB -Password (Get-Credential -UserName 'FoxDeploy' -Message 'Enter New Password') -UserName 'FoxDeploy' -ConfigurationData $configData
Start-DscConfiguration -ComputerName localhost -Wait -Force -Verbose -path .TestLab
Wrapping Up
So, it seems that most things in DSC look deceptively easy when you see the finished result, but working up to that is quite difficult. Instead this was more of a deep dive into using the User Resource with DSC. Join us again next week when we add our user to the Administators built-in Group, then make our machine into a Domain Controller.