Create a DSC SMB Pull Server with DSC and separate the Environmental Config from the Structural Config

The machines used in this blog article are running Windows 8.1 and Windows Server 2012 R2. Both have the default version of PowerShell installed that shipped with those operating systems which is PowerShell version 4.

The following configuration uses the xSmbShare and the PowerShellAccessControl DSC resources which can be downloaded from GitHub. These resources must exist on the machine where you're authoring the DSC configuration and on the node that the configuration is being applied to. They should be placed in the following path:

1"$env:ProgramFiles\WindowsPowerShell\Modules"

Keep in mind that any DSC Resources that do not reside in the following path have to be imported using Import-DscResource in your DSC configuration.

1"$PSHOME\Modules"

Don't even think about placing your DSC resources in the $PSHOME path shown in the previous example. I'm my opinion, only Microsoft should be placing things in that path.

The configuration shown in the following example is very static and both the environmental config and the structural config are specified together:

 1configuration DSCSMB {
 2
 3    Import-DscResource -Module xSmbShare, PowerShellAccessControl
 4
 5    Node dc01 {
 6
 7        File CreateFolder {
 8
 9            DestinationPath = 'C:\DSCSMB'
10            Type = 'Directory'
11            Ensure = 'Present'
12
13        }
14
15        xSMBShare CreateShare {
16
17            Name = 'DSCSMB'
18            Path = 'C:\DSCSMB'
19            FullAccess = 'mikefrobbins\domain admins'
20            ReadAccess = 'mikefrobbins\domain computers'
21            FolderEnumerationMode = 'AccessBased'
22            Ensure = 'Present'
23            DependsOn = '[File]CreateFolder'
24
25        }
26
27        cAccessControlEntry AssignPermissions {
28
29            Path = 'C:\DSCSMB'
30            ObjectType = 'Directory'
31            AceType = 'AccessAllowed'
32            Principal = 'mikefrobbins\domain computers'
33            AccessMask = [System.Security.AccessControl.FileSystemRights]::ReadAndExecute
34            DependsOn = '[File]CreateFolder'
35
36        }
37
38    }
39
40}

The DSCSMB configuration shown in the previous code example has been loaded into memory and when it's called, a MOF file is created which will be used to configure DC01:

1DSCSMB

dscsmb1a.jpg

The MOF file is applied to DC01 using the DSC push configuration mode:

1Start-DscConfiguration -Wait -Path .\DSCSMB -Verbose

dscsmb2a.jpg

The following example only contains the structural config and the environmental config has been removed:

 1configuration DSCSMB {
 2
 3    Import-DscResource -Module xSmbShare, PowerShellAccessControl
 4
 5    Node $AllNodes.NodeName {
 6
 7        File CreateFolder {
 8
 9            DestinationPath = $Node.Path
10            Type = 'Directory'
11            Ensure = 'Present'
12
13        }
14
15        xSMBShare CreateShare {
16
17            Name = $Node.ShareName
18            Path = $Node.Path
19            FullAccess = $node.FullAccess
20            ReadAccess = $node.ReadAccess
21            FolderEnumerationMode = 'AccessBased'
22            Ensure = 'Present'
23            DependsOn = '[File]CreateFolder'
24
25        }
26
27        cAccessControlEntry AssignPermissions {
28
29            Path = $Node.Path
30            ObjectType = 'Directory'
31            AceType = 'AccessAllowed'
32            Principal = $Node.ReadAccess
33            AccessMask = [System.Security.AccessControl.FileSystemRights]::ReadAndExecute
34            DependsOn = '[File]CreateFolder'
35
36        }
37
38    }
39
40}

The environmental config is now defined in a hash table:

 1$ConfigData = @{
 2    AllNodes = @(
 3        @{
 4            NodeName = 'DC01'
 5            ShareName = 'DSCSMB'
 6            Path = 'C:\DSCSMB'
 7            FullAccess = 'mikefrobbins\domain admins'
 8            ReadAccess = 'mikefrobbins\domain computers'
 9        }
10    )
11}

The variable that contains the hash table has to be specified via the ConfigurationData parameter when calling the configuration otherwise the MOF file won't be created:

1DSCSMB -ConfigurationData $ConfigData

dscsmb3a.jpg

There are no changes as far as how the MOF file is applied to DC01:

1DSCSMB -ConfigurationData $ConfigData

dscsmb4a.jpg

Instead of storing the environmental data in a variable, you could also store it in a file:

 1@{
 2    AllNodes = @(
 3        @{
 4            NodeName = 'DC01'
 5            ShareName = 'DSCSMB'
 6            Path = 'C:\DSCSMB'
 7            FullAccess = 'mikefrobbins\domain admins'
 8            ReadAccess = 'mikefrobbins\domain computers'
 9        }
10    )
11}

It must be a file with a PSD1 extension otherwise the MOF file will fail to be created:

1DSCSMB -ConfigurationData .\configdata-dscsmb.txt -Verbose

dscsmb5a.jpg

1DSCSMB : Cannot process argument transformation on parameter ‘ConfigurationData’. Cannot resolve the path
2‘.\configdata-dscsmb.txt’ to a single .psd1 file.
3At line:1 char:27
4+ DSCSMB -ConfigurationData .\configdata-dscsmb.txt -Verbose
5+ ~~~~~~~~~~~~~~~~~~~~~~~
6+ CategoryInfo : InvalidData: (:) [DSCSMB], ParameterBindingArgumentTransformationException
7+ FullyQualifiedErrorId : ParameterArgumentTransformationError,DSCSMB

Saving the file with a PSD1 extension allows the MOF file to be created successfully:

1DSCSMB -ConfigurationData .\configdata-dscsmb.psd1 -Verbose

dscsmb6a.jpg

Once again, there are no changes as far as how the MOF file is applied to DC01:

dscsmb7a.jpg

You can run commands to dynamically generate the configuration data hash table when it's stored in a variable, but if you store the configuration data in a PSD1 file, it has to contain static values otherwise an error will be generated when you try to create the MOF file.

Did you notice that domain computers was assigned access to the SMB file share as well as NTFS permissions to the folder that was created? This is because the DSC LCM (Local Configuration Manager) runs as the system account by default and once the LCM on the target nodes is configured to pull their configuration from this SMB file share, they will have access, that is if they're members of the domain computers group. Did you know that not all computers that are a member of a domain are a member of the domain computers group? Domain controllers are not members of the domain computers group.

µ