11

Here's my example:

$Config = @{
    AllNodes = @(
        @{ NodeName = 'localhost'; PSDscAllowPlainTextPassword = $True }
    )
}

Configuration LocalAdmin
{
    Param([String[]]$Node='localhost',[PSCredential]$Cred)

    Import-DscResource -ModuleName 'PSDscResources'
    Node $Node
    {
        User 'LocalAdmin'
        {
            Username = 'Admin'
            Description = 'DSC configuration test'
            Ensure = 'Present'
            FullName = 'Administrator Extraordinaire'
            Password = $Cred
            PasswordChangeRequired = $False
            PasswordNeverExpires = $True
        }
        Group 'AddToAdmin'
        {
            GroupName = 'Administrators'
            DependsOn = '[User]LocalAdmin'
            Ensure = 'Present'
            MembersToInclude = 'Admin'
        }
    }
}
Configuration DisableLocalAccounts
{
    Param([String[]]$Node='localhost')

    Import-DscResource -ModuleName 'PSDscResources'
    Node $Node
    {
        User 'Administrator'
        {
            Username = 'Administrator'
            Disabled = $True
        }
        User 'Guest'
        {
            Username = 'Guest'
            Disabled = $True
        }
        User 'DefaultAccount'
        {
            Username = 'DefaultAccount'
            Disabled = $True
        }
    }
}


Set-Location $env:UserProfile
LocalAdmin -Cred (Get-Credential -UserName 'Admin') -ConfigurationData $Config
DisableLocalAccounts

Start-DscConfiguration -ComputerName 'localhost' -Wait -Force -Verbose -Path '.\LocalAdmin'
Start-DscConfiguration -ComputerName 'localhost' -Wait -Force -Verbose -Path '.\DisableLocalAccounts'

The issue:
When I run Get-DscConfiguration, it only shows the configuration of whichever configuration I ran last.

PS C:\> Get-DscConfiguration


ConfigurationName        : DisableLocalAccounts
DependsOn                :
ModuleName               : PSDscResources
ModuleVersion            : 2.8.0.0
PsDscRunAsCredential     :
ResourceId               : [User]Administrator
SourceInfo               :
Description              : Built-in account for administering the computer/domain
Disabled                 : True
Ensure                   : Present
FullName                 :
Password                 :
PasswordChangeNotAllowed : False
PasswordChangeRequired   :
PasswordNeverExpires     : True
UserName                 : Administrator
PSComputerName           :
CimClassName             : MSFT_UserResource

ConfigurationName        : DisableLocalAccounts
DependsOn                :
ModuleName               : PSDscResources
ModuleVersion            : 2.8.0.0
PsDscRunAsCredential     :
ResourceId               : [User]Guest
SourceInfo               :
Description              : Built-in account for guest access to the computer/domain
Disabled                 : True
Ensure                   : Present
FullName                 :
Password                 :
PasswordChangeNotAllowed : True
PasswordChangeRequired   :
PasswordNeverExpires     : True
UserName                 : Guest
PSComputerName           :
CimClassName             : MSFT_UserResource

ConfigurationName        : DisableLocalAccounts
DependsOn                :
ModuleName               : PSDscResources
ModuleVersion            : 2.8.0.0
PsDscRunAsCredential     :
ResourceId               : [User]DefaultAccount
SourceInfo               :
Description              : A user account managed by the system.
Disabled                 : True
Ensure                   : Present
FullName                 :
Password                 :
PasswordChangeNotAllowed : False
PasswordChangeRequired   :
PasswordNeverExpires     : True
UserName                 : DefaultAccount
PSComputerName           :
CimClassName             : MSFT_UserResource

How do I apply multiple configurations? I cannot find documentation on this.

Maximilian Burszley
  • 18,243
  • 4
  • 34
  • 63
  • If you want to apply configuration after configuration on a windows box you can use something like Chef. Chef can also apply DSC configurations. – JoeRod May 03 '19 at 02:14

2 Answers2

12

You won't find this in the documentation because you (basically) can't do that.

I say basically, because you can do it, in a sense, with DSC Partial Configurations.

These require a different workflow and a different Local Configuration Manager (LCM) setup though. They do not work the way you are envisioning where you create multiple configurations and then apply them one after the other.

This is by design; what you're trying to do isn't really what DSC is for. The idea is that you are supposed to be supplying the (desired) state of the node you're configuring. Applying multiple configurations could easily cause conflicting settings to be applied.

Even with partials, the LCM is generating a single configuration (resolving your partials) and then applying that all at once.


What to do instead:

DSC is light on tooling. It doesn't really have much to say about how you ultimately generate your configs or handle common data, roles, etc. So you already have to roll your own for the most part.

Applying multiple separate configurations is probably something you should be taking care of in your own workflow, leading up to ultimately compiling your (single) MOF per node.

What are Partials For?

There are 2 use cases I can think of where it would be appropriate to use Partials.

First (and this is primarily the role for them Microsoft had in mind) is for larger and more segregated organizations, where different teams have sole responsibility and ownership for their knowledge domain, and you want those teams to be able to write and control their own configurations.

So for example, the OS team might write the configuration for various basic OS config items (setting time zone/NTP, license settings), and maybe they set the LCM setup to pull from the rest.

The DBA team writes a configuration for installing and configuring SQL server.

The security team writes a configuration for setting password policies, firewall rules and enforcement, etc.

These teams have their own procedures and rules and autonomy. They may have their own pull server where they publish these.

The second use case, which is often related to the first, is when you have multiple pull servers, or you want to combine push and pull. I believe that's only possible with partials.


Future

Do note that Windows PowerShell is unlikely to be updated anymore. PowerShell Core (which is based on .Net Core and runs on Windows, Linux, and MacOS) is where the majority of PowerShell development is going at this time.

With that, DSC will be changing too and getting a completely new edition going forward that works better cross-platform.

Just something to keep in mind if you're going down the path of writing a lot of tooling and workflow code to support DSC.

briantist
  • 45,546
  • 6
  • 82
  • 127
  • Fantastic answer. Thank you for all the resources. The main reason I was looking to modularize them was to make it easier to find the different configurations for easier management. – Maximilian Burszley Oct 27 '17 at 17:31
  • @TheIncorrigible1 I went through similar struggles with how to organize these once I was using DSC 5. When I started using DSC it was v4 (the first version) and didn't have partials, so it seemed natural to want to use them for organization but after trying it seems they aren't really for that. I've largely stopped using DSC for the time being, but DSC Core looks pretty exciting to me. – briantist Oct 27 '17 at 17:33
9

You don't always have to use partial configuration for what you are trying to accomplish. You can use composite configuration to achieve the same depending how you are using these configurations. Here is the translation of your example using composite configuration.

    $Config = @{
    AllNodes = @(
        @{ NodeName = 'localhost'; PSDscAllowPlainTextPassword = $True }
    )
}
Configuration LocalAdmin
{
    Param([String[]]$Node='localhost',[PSCredential]$Cred)

    Import-DscResource -ModuleName 'PSDscResources'
    Node $Node
    {
        User 'LocalAdmin'
        {
            Username = 'Admin'
            Description = 'DSC configuration test'
            Ensure = 'Present'
            FullName = 'Administrator Extraordinaire'
            Password = $Cred
            PasswordChangeRequired = $False
            PasswordNeverExpires = $True
        }
        Group 'AddToAdmin'
        {
            GroupName = 'Administrators'
            DependsOn = '[User]LocalAdmin'
            Ensure = 'Present'
            MembersToInclude = 'Admin'
        }
    }
}
Configuration DisableLocalAccounts
{
    Param([String[]]$Node='localhost')

    Import-DscResource -ModuleName 'PSDscResources'
    Node $Node
    {
        User 'Administrator'
        {
            Username = 'Administrator'
            Disabled = $True
        }
        User 'Guest'
        {
            Username = 'Guest'
            Disabled = $True
        }
        User 'DefaultAccount'
        {
            Username = 'DefaultAccount'
            Disabled = $True
        }
    }
}
Configuration AllAccounts
{
    Param([String[]]$Node='localhost',[PSCredential]$Cred)
    DisableLocalAccounts localAccount
    {
       Node = $Node
    }
    LocalAdmin localAdmin
    {
        Node = $Node
        Cred = $Cred
    }
}
Set-Location $env:UserProfile
AllAccounts -Cred (Get-Credential -UserName 'Admin') -ConfigurationData $Config
Start-DscConfiguration -ComputerName 'localhost' -Wait -Force -Verbose -Path '.\AllAccounts'
N.Gupta
  • 326
  • 1
  • 5
  • 2
    I had no idea you could call them in that way. Neat! – Maximilian Burszley Oct 31 '17 at 02:23
  • 2
    This is a great alternative as well. These are more commonly referred to as Composite _Resources_. Keep in mind that this is also done as design time; the compilation process resolves all of these into a single MOF. Also, if you're using `Invoke-DscResource` or any configuration management system that relies on that cmdlet to incorporate DSC resources, composite resources will not work (because that underlying DSC engine has no concept of composites). – briantist Nov 01 '17 at 23:04
  • 2
    This is not a Composite Resource but compilation time construct and cmdlets always deal with individual resources. Composite resource is another approach but comes with the headache of deploying the resources. – N.Gupta Nov 02 '17 at 21:08