Part I.5: Creating a user for our Testlab with DSC

IntroToDsc

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

newUser_01

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” # To ensure the user account does not exist, set Ensure to “Absent”
UserName = “SomeName”
Password = $passwordCred # This needs to be a credential object
DependsOn = “[Group]GroupExample” # Configures GroupExample first
}

Let’s look at the error message again…

“Convert property ‘Password’ value from type ‘STRING’ to type ‘INSTANCE’ failed

And now side-by-side…

Password = $passwordCred # This needs to be a credential object
Can’t convert property ‘Password’ value from type ‘STRING’ to type ‘INSTANCE’ failed

Hmm…I 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.

newUser_015

So, let’s replace our -PassWord ‘RootPW’ with a parenthesis with Get-Credential and see what happens…

TestLab -MachineName DSCDC01 -WorkGroupName TESTLAB -Password (Get-Credential -UserName 'FoxDeploy' -Message 'Enter New Password') -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!

newUser_02

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

newUser_03

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.

configuration 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.

Advertisements

8 thoughts on “Part I.5: Creating a user for our Testlab with DSC

  1. Dan Iveson July 13, 2015 / 3:45 pm

    Big Fan, keep up the good work. I felt like it may have been a little clearer if you noted when you first showed the code for $ConfigData, that this would be made part of the code by adding a ConfigurationData parameter to the command to make the MOF file. TestLab -ConfigurationData $ConfigData. It took me going back to the original article referenced to put this piece together. Maybe if I would have read the article before, you already taught the usage of this parameter there, I don’t know.

  2. Scott September 18, 2015 / 12:29 pm

    Why are you initializing the $configData variable ($configData = ‘a’) before giving it the actual hash table?

  3. Francis February 15, 2016 / 11:12 am

    Dear Stephen, really great blog! I love it!
    One question: in the param block you are using [string[]]$nodename? If you would use an Array of nodenames you also would have to use Arrays of Machinenames – or do I get something wrong?

    • FoxDeploy February 15, 2016 / 11:24 am

      Sorry, I’m on vacation right now, but will be back in the office this week! When I am, I’ll double check this and see if I missed something! Wouldn’t be the first time. 😃

      • FoxDeploy February 19, 2016 / 9:40 am

        Yep, you’re right. If you provided more than one $nodename, you’d need to also feed in an array of MachineNames, and the code doesn’t currently have a mechanism to handle indexing through an array. I really intended this to be used on a single machine at a time, but left in array support. Good catch!

  4. Gregory Suvalian December 16, 2016 / 8:08 pm

    FYI. If you still want to hardcode password in your script (like original one intended), you can still do it via below

    $cred = [pscredential]::new(“dd”, (ConvertTo-SecureString “passwordhere” -AsPlainText -Force)) -as [pscredential]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s