PowerShell

DSC

DSC came out in PowerShell version 4 and it will work with Windows 7 and 2008R2 providing they have WMF4 or 5 installed.

DSC can be used in both pull and push modes. So far I have only used push mode outside of the lab. I kind of prefer to be in control.

Configurations are declarations of what you want the machine to look like. The make it so document.

It is the local configuration manager that actually does the work needed to make it so. This is in push mode by default but needs to be configured if you want to use a pull server.

Also by default it is set to apply and monitor. If you are using a pull server it will need to be set to autoconfig.

Setting The LCM PowerShell v4


        Configuration LCMPUSH {
            Node $ComputerName {
                LocalConfigurationManager{
                    AllowModuleOverwrite = $true
                    ConfigurationMode = 'ApplyAndAutoCorrect'
                    RefreshMode = 'Push'
                }
            }
        }
    
        $ComputerName = "svr1","svr2"
        

Setting The LCM in PowerShell v5


        [DscLocalConfigurationManager()]
        Configuration LCMPUSH{
            Node $ComputerName{
                Settings{
                    AllowModuleOverwrite = $true
                    ConfigurationMode = 'ApplyAndAutoCorrect'
                    RefreshMode = 'Push'
                }
            }
        }
        $ComputerName = "svr1","svr2"
        LCMPUSH -outputpath c:\DSC\LCM
        break; #This will create svr1.meta.mof and svr2.meta.mof 
        #finally run
        Set-DscLocalConfigurationManager -ComputerName $computername -Path c:\dsc\lcm -Verbose
        

A list of DSC commands


        PS C:\> Get-Command -Module PSDesiredStateConfiguration | ft commandtype,name -AutoSize
    
        CommandType Name
        ----------- ----
        Function Configuration
        Function Disable-DscDebug
        Function Enable-DscDebug
        Function Get-DscConfiguration
        Function Get-DscConfigurationStatus
        Function Get-DscLocalConfigurationManager
        Function Get-DscResource
        Function New-DscChecksum
        Function Remove-DscConfigurationDocument
        Function Restore-DscConfiguration
        Function Stop-DscConfiguration
        Cmdlet   Invoke-DscResource
        Cmdlet   Publish-DscConfiguration
        Cmdlet   Set-DscLocalConfigurationManager
        Cmdlet   Start-DscConfiguration
        Cmdlet   Test-DscConfiguration
        Cmdlet   Update-DscConfiguration
    
        Function        Find-DscResource    PowerShellGet
         

When DSC first came out it had 12 built in resources it now has 25 as of June 2020

        PS C:\> (Get-DscResource).name
        File
        SignatureValidation
        PackageManagement
        PackageManagementSource
        Archive
        Environment
        Group
        GroupSet
        Log
        Package
        ProcessSet
        Registry
        Script
        Service
        ServiceSet
        User
        WaitForAll
        WaitForAny
        WaitForSome
        WindowsFeature
        WindowsFeatureSet
        WindowsOptionalFeature
        WindowsOptionalFeatureSet
        WindowsPackageCab
        WindowsProcess
        PS C:\> (Get-DscResource).count
        25
        

The Basic structure of a DSC configuration is:


        configuration Testconfig {
            node s1 {
                windowsfeature webserver {
    
                }
            }
        }
        

Find-DscResource can be used to search all of the resourses in the PSGallery

You can find the syntax for DSC resources by using Get-DscResource [name] -Syntax


        PS C:\> Get-DscResource file -Syntax
        File [String] #ResourceName
        {
            DestinationPath = [string]
            [Attributes = [string[]]{ Archive | Hidden | ReadOnly | System }]
            [Checksum = [string]{ CreatedDate | ModifiedDate | SHA-1 | SHA-256 | SHA-512 }]
            [Contents = [string]]
            [Credential = [PSCredential]]
            [DependsOn = [string[]]]
            [Ensure = [string]{ Absent | Present }]
            [Force = [bool]]
            [MatchSource = [bool]]
            [PsDscRunAsCredential = [PSCredential]]
            [Recurse = [bool]]
            [SourcePath = [string]]
            [Type = [string]{ Directory | File }]
        }
        

addSecGroups

This script is designed to create two security groups for the nominated machine SEC_machineName_Admin and SEC_machineName_RDP it then uses DSC to place these security groups into the administrators group and the Remote Desktop Users group as appropriate.

This script is meant to be run from the ISE with Domain Admin priveleges. The variable $node needs to be changed to the name of the server you want to do this to and when the script has been executed and the mof file has been created, hightlight the line after the break statement and press f8
Start-DscConfiguration -Path C:\dsc\config -ComputerName $node -Verbose -wait -force


    configuration addSecGroups{
    
        Import-DscResource -ModuleName PSDesiredStateConfiguration
        node $node{     
            
            Group RemoteDesktopUsers {
                GroupName = "Remote Desktop Users"
                Members = $rdp
                            
            }
            Group Administrators {
                GroupName = "Administrators"
                MembersToInclude = $admins
                            
            }
    }
                
    }
                
    
    function new-PF_SecGroup{
        [cmdletbinding()]
        param(
        [Parameter(Mandatory=$true)]
        $name,
        [Parameter(Mandatory=$true)]
        [ValidateSet("Admin", "RDP")]
        $type
        )
                
        if($type -eq "Admin"){
        $ending = "_Admin"
        $path = "OU=Server-Admin,OU=Security,DC=company,DC=pri"
        }else{
        $ending="_RDP"
        $path = "OU=Server-RDP,OU=Security,DC=company,DC=pri"
        }
                
        $gname = "SEC_" + $name + "$ending"
        new-adgroup -Name $gname -Path $path -GroupScope Global -GroupCategory Security
    }
    $node = "Server01"
    $rdp = "company\SEC_" + $node + "_RDP"
    $admins = "company\SEC_" + $node + "_Admin"
    $rdpt = "SEC_" + $node + "_RDP"
    $admint = "SEC_" + $node + "_Admin"
    #region test for security groups and make them if necessary
    try{
        Get-ADGroup $rdpt -ErrorAction Stop | Out-Null
                    
    }
    catch{
                
        new-PF_SecGroup -name $node -type rdp
                
    }
    try{
        Get-ADGroup $admint -ErrorAction Stop | Out-Null
                    
    }
    catch{
                
    new-PF_SecGroup -name $node -type Admin
                
    }
    #endregion
                
                
    addSecGroups -outputpath c:\dsc\config 
                
    break;
    Start-DscConfiguration -Path C:\dsc\config -ComputerName $node  -Verbose -wait -force
    

Installing chrome


    Install-module xchrome -force
    
    
    configuration InstallChrome {
        Import-DSCResource -Module xchrome -Name msft_xchrome
    
        node $computername {
            msft_xchrome installme
            {
                language = 'en'
            }
            
    
        }
    
    }
    $computername = hostname
    
    InstallChrome -outputpath c:\dsc\config
    break
    Start-DscConfiguration -Path C:\dsc\config -ComputerName $computername  -Verbose -wait -force
    Test-DscConfiguration -ComputerName $computername
    

IE Enhanced Security

The following configuration can be used to turn off the annoying enhansed security settings for Internet Explorer


    configuration IES {
        Import-DSCResource -Module xSystemSecurity -Name xIEEsc
    
        node $computername {
            xIEEsc EnableIEEscAdmin
            {
                IsEnabled = $False
                UserRole  = "Administrators"
            }
            xIEEsc EnableIEEscUser
            {
                IsEnabled = $True
                UserRole  = "Users"
            }    
    
        }
    
    }
    $computername = hostname
    
    IES -outputpath c:\dsc\config
    Start-DscConfiguration -Path C:\dsc\config -ComputerName $computername  -Verbose -wait -force
    Test-DscConfiguration -ComputerName $computername
    

This can also be done by using the registry resource (I havn't tested this one lately it may needs some tweeks to work but the structure is sound.)


    configuration enhanced
    {
        # One can evaluate expressions to get the node list
        # E.g: $AllNodes.Where("Role -eq Web").NodeName
        node $computername
        {
          registry ESC {
          key = 'HKEY_local_machine\software\microsoft\active setup\installed components\{A509B1A7-37EF-4b3f-8CFC-4F3A74704073}\'
          valuename = "isinstalled"
          valuedata = 0
          valuetype = "dword"
          
          }  
          registry ESC1 {
          key = 'HKEY_local_machine\software\microsoft\active setup\installed components\{A509B1A8-37EF-4b3f-8CFC-4F3A74704073}\'
          valuename = "isinstalled"
          valuedata = 0
          valuetype = "dword"
          
          }           
        }
    }
    $computername = hostname
    
    enhanced -outputpath c:\dsc\config
    Start-DscConfiguration -Path C:\dsc\config -ComputerName $computername  -Verbose -wait -force
    Test-DscConfiguration -ComputerName $computername
    

Finding product number for package resource

In order to install programs with the DSC package resource you need the product number.

You can do that by going to a machine that already has the package installed and running the following command:


    gwmi win32_product |select name,identifyingnumber 
    
    name                 identifyingnumber 
    
    ----                 ----------------- 
    
    Google Chrome        {25D02A91-99C1-38B7-8A36-2C5B1836C4CB} 
    
    Google Update Helper {60EC980A-BDA2-4CB6-A427-B07A5498B4CA} 
    

In order to package you need:


    package productName { 
    
        Name = [string] 
    
        Path = [string] 
    
        ProductId = [string]         
    
    } 
    
The full syntax is as follows:
    PS C:\WINDOWS\system32> Get-DscResource package -Syntax 
    
    Package [String] #ResourceName 
    
    { 
    
        Name = [string] 
    
        Path = [string] 
    
        ProductId = [string] 
    
        [Arguments = [string]] 
    
        [Credential = [PSCredential]] 
    
        [DependsOn = [string[]]] 
    
        [Ensure = [string]{ Absent | Present }] 
    
        [LogPath = [string]] 
    
        [PsDscRunAsCredential = [PSCredential]] 
    
        [ReturnCode = [UInt32[]]] 
    
    }