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
The MOF file is applied to DC01 using the DSC push configuration mode:
1Start-DscConfiguration -Wait -Path .\DSCSMB -Verbose
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
There are no changes as far as how the MOF file is applied to DC01:
1DSCSMB -ConfigurationData $ConfigData
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
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
Once again, there are no changes as far as how the MOF file is applied to DC01:
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.
µ