Главная

Friday, 12 March 2021

Применение ресурсов в Powershell DSC.

Всем привет.

На сегодня Powershell DSC имеет 63 встроенных ресурса. Большинство из них просты и понятны из своего названия. Исключая продвинутые 37 штук имена которых начинаются с "х". В любом случае для полноценной настройки ваших систем их может быть недостаточно. Поэтому Microsoft предлагает самостоятельно создавать необходимые ресурсы. Но не спешите с выводами.

Get-DscResource | Select Name

Обычно названия ресурсов дают первое понимание с чем они работают: 

Archive - с упаковкой и распаковкой архивов;

Environment - с переменными окружения;

File - с файлами;

Group - с локальными группами пользователей;

Log - с логами;

Package - с пакетами ПО;

Registry - с ключами реестра и их состоянием;

Service - с сервисами и их состоянием;

User - с локальными учетными записями пользователей;

WindowsFeature - с компонентами Windows Server;

WindowsProcess - с процессами Windows;

и т.д.

А вот ресурс Script позволяет вставить полноценный PowerShell-скрипт в код требуемой конфигурации. Он имеет 3 отдельных блока: 

SetScript - сам PowerShell-скрипт, 

TestScript - проверочное условие, при нарушении (false) которого будет запущен SetScript, 

GetScript - возвращает текущее состояние объекта.

Как раз то что нам надо, теперь с помощью этого ресурса можно реализовать любую свою задачу.

Для убедительности ниже приведу несколько примеров как можно выполнить то или иное действие. Ну поехали.

# Set Languagae location (Script)

      Script LanguageSettings {

            SetScript = {

                    Set-Culture ru-RU

                    Set-WinSystemLocale ru-RU

                    Set-WinHomeLocation 241

            }

            GetScript = { return @{ Result = ( "Culture: " + (Get-Culture).Name + ". WinSystemLocale: " + (Get-WinSystemLocale).Name -eq "ru-RU")

                GetScript = $GetScript.Trim(); SetScript = $SetScript.Trim(); TestScript = $TestScript.Trim()

                }

            }

            TestScript = { (Get-Culture).Name -eq "ru-RU" -and (Get-WinSystemLocale).Name -eq "ru-RU" -and (Get-WinHomeLocation).GeoID -eq 241 }

        }

# Install applications from MSI (Package + Script)

        Script FarDownLoad {

            SetScript = { Invoke-WebRequest -Uri http://www.farmanager.com/files/Far30b4400.x64.20150709.msi -OutFile C:\Users\Public\Downloads\Far30b4400.x64.20150709.msi }

            GetScript = { return @{ Result = Test-Path C:\Users\Public\Downloads\Far30b4400.x64.20150709.msi

                GetScript = $GetScript; SetScript = $SetScript; TestScript = $TestScript

                }

            }

            TestScript = { Test-Path C:\Users\Public\Downloads\Far30b4400.x64.20150709.msi }

        }

        Package FarInstall {

            Ensure    = "Present"

            DependsOn = "[Script]FarDownLoad"

            Name      = "Far Manager 3 x64"

            ProductId = 'E5512F32-B7C1-48E3-B6AF-E5F962F99ED6'

            Path      = "C:\Users\Public\Downloads\Far30b4400.x64.20150709.msi"

            Arguments = ''

            LogPath   = "C:\Users\Public\Downloads\FarInstall.log"

        }


Инсталяцию MSI-пакета можно было запустить и так:

        Script FarInstall {

            SetScript = { msiexec.exe /i "C:\Users\Public\Downloads\Far30b4400.x64.20150709.msi" /q /norestart }

        ...}


# Install hotfix manually (Script)

        Script AbcUpdateNet452Install {

            SetScript = { C:\Hotfixes\ABC-Update\ABC-Update.exe /a:install /k:2934520 }

            GetScript = { return @{ Result = if ( Get-HotFix -Id KB2934520 -ErrorAction SilentlyContinue ) { "KB2934520: Installed" } else { "KB2934520: Not Found" }

                GetScript = $GetScript; SetScript = $SetScript; TestScript = $TestScript

                }

            }

            TestScript = { if ( Get-HotFix -Id KB2934520 -ErrorAction SilentlyContinue ) { $true } else { $false } }

        }


# Enables RDP access for server (Registry + Script)

    Registry EnableRDP-Step1

    {

      Ensure = "Present"

      Key = "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Terminal Server"

      ValueName = "fDenyTSConnections"

      ValueData = "0"

      ValueType = "Dword"

      Force = $true

    }

    Registry EnableRDP-Step2

    {

      Ensure = "Present"

      Key = "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"

      ValueName = "UserAuthentication"

      ValueData = "1"

      ValueType = "Dword"

      Force = $true

    }

    Script EnableRDP

    {

      SetScript = {

        Enable-NetFirewallRule -DisplayGroup "Remote Desktop"

        eventcreate /t INFORMATION /ID 2 /L APPLICATION /SO "DSC-Client" /D "Enabled Remote Desktop access"

      }

      TestScript = {

        if ((Get-NetFirewallRule -Name "RemoteDesktop-UserMode-In-TCP").Enabled -ne "True") {

          $false

        } else {

          $true

        }

      }

      GetScript = {

        # Do Nothing

      }

    }

# Verifies WinRM is configured (Script)

    Script EnableWinrm

    {

      SetScript = {

        Set-WSManQuickConfig -Force -SkipNetworkProfileCheck

        eventcreate /t INFORMATION /ID 4 /L APPLICATION /SO "DSC-Client" /D "Enabled Windows Remote Management"

      }

      TestScript = {

        try{

          # Use to remove a listener for testing

          # Remove-WSManInstance winrm/config/Listener -selectorset @{Address="*";Transport="http"}

          Get-WsmanInstance winrm/config/listener -selectorset @{Address="*";Transport="http"}

          return $true

        } catch {

          #$wsmanOutput = "WinRM doesn't seem to be configured or enabled."

          return $false

        }

      }

      GetScript = {

        # Do Nothing

      }

    }

 

# Disables checking for updates (Script)

    Script DisableUpdates

    {

      SetScript = {

        $WUSettings = (New-Object -com "Microsoft.Update.AutoUpdate").Settings

        $WUSettings.NotificationLevel = 2

        $WUSettings.IncludeRecommendedUpdates=$true

        $WUSettings.Save()

        eventcreate /t INFORMATION /ID 3 /L APPLICATION /SO "DSC-Client" /D "Disabled Checking for Updates"

      }

      TestScript = {

        $WUSettings = (New-Object -com "Microsoft.Update.AutoUpdate").Settings

        if ($WUSettings.NotificationLevel -eq 2 -and $WUSettings.IncludeRecommendedUpdates -eq $true) {

          $true

        } else {

          $false

        }

      }

      GetScript = {

        # Do Nothing

      }

    }

# Write a timestamp in EventLog indicating the last time this script was run on the host (Script)

    Script LeaveTimestamp

    {

      SetScript = {

        $currentTime = Get-Date

        $currentTimeString = $currentTime.ToUniversalTime().ToString()

        [Environment]::SetEnvironmentVariable("DSCClientRun","Last DSC-Client run (UTC): $currentTimeString","Machine")

        eventcreate /t INFORMATION /ID 1 /L APPLICATION /SO "DSC-Client" /D "Last DSC-Client run (UTC): $currentTimeString"

      }

      TestScript = {

        $false

      }

      GetScript = {

        # Do Nothing

      }

    }


Если ваш скрипт зависит от выполнения другого то надо указать ссылку на него в параметре DependsOn.

Например:

          Script AbcfolderCreate 

{...}

          Script LeaveTimestamp

            DependsOn = "[Script]AbcfolderCreate"

Т.е. выполенение текущего скрипта LeaveTimestamp зависит от результата AbcfolderCreate.


И напоследок еще пару полезных примеров с другими ресурсами.

# Extract files from ZIP-arhive (Archive)

       Archive UnpackNetworkingDsc {

           Ensure = "Present"

           Path = "C:\Install\PSModules\NetworkingDsc.zip"

           Destination = "C:\Program Files\WindowsPowerShell\Modules\"

       }


# Set DNS-suffix (Registry)

      Registry PrimaryDomainSuffix {

            Key = "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\"

            ValueName = "My cloud company"

            Ensure = "Present"

            ValueData = "forza.com"

            ValueType = "String"

        }

На сегодня все. Успехов.

No comments:

Post a Comment

А что вы думаете по этому поводу?