mercredi 7 décembre 2016

Setting up or Updating SNMP via Powershell on a Windows Server 2012 R2

A little while ago, I had to write a Powershell function to update the SNMP settings from a bunch of servers running Windows 2012 R2 Server.

The following cases had to be handled:
 - The SNMP feature could be missing or present
 - The SNMP settings could be existing (Managers / Communities)
 - The SNMP settings could be wiped depending on the servers (Managers / Communities)

So here's what I came up with. Note that we rely on WSMan to make things easier when we're dealing with more than one server and that a new community is always added as Read-Only.

Function Set-SNMPProperties {

    #requires -version 3


<#

    .SYNOPSIS

            This function will install SNMP if needed and configure the Permitted Managers along with

            the desired communities in read-only via WSMan

    .DESCRIPTION

            This function will install SNMP if needed and configure the Permitted Managers along with

            the desired communities in read-only via WSMan

    .PARAMETER  Computer

            Specifies which computer(s) will be processed

    .PARAMETER  SNMPPermittedManager

            Specifies which Managers are allowed

    .PARAMETER  SNMPCommunity

            Specifies which Communities are allowed

    .PARAMETER  SNMPClear

            Specifies whether the existing Managers/Communities should be cleared or not

    .EXAMPLE

            Set-SNMPProperties -Computer "lab-fs001.katalykt.lan" `

                -SNMPPermittedManager "lab-centreon001.katalykt.lan" `

                -SNMPCommunity "katalyktRO"


            PSComputerName           SNMPManagers                   SNMPCommunities

            --------------           ------------                   ---------------

            lab-fs001.katalykt.lan   lab-centreon001.katalykt.lan   katalyktRO

    .EXAMPLE

            Set-SNMPProperties -Computer "lab-fs001.katalykt.lan", "lab-fs002.katalykt.lan" `

                -SNMPPermittedManager "lab-centreon001.katalykt.lan", "lab-centreon002.katalykt.lan" `

                -SNMPCommunity "katalyktRO", "labRO"


            PSComputerName           SNMPManagers                                         SNMPCommunities

            --------------           ------------                                         ---------------

            lab-fs001.katalykt.lan   {lab-centreon001.katalykt.lan, lab-centreon002...}   {katalyktRO, labRO}

            lab-fs002.katalykt.lan   {lab-centreon001.katalykt.lan, lab-centreon002...}   {katalyktRO, labRO}

    .EXAMPLE

            # Assuming the CSV contains one column with the title "Computer"

            Import-Csv -Path D:\Scripts\PSv3\Set-SNMPProperties.csv | ForEach-Object {$_.Computer} | `

                Set-SNMPProperties -SNMPPermittedManager "lab-centreon001.katalykt.lan" `

                    -SNMPCommunity "katalyktRO" `

                    -SNMPClear


            PSComputerName           SNMPManagers                   SNMPCommunities

            --------------           ------------                   ---------------

            lab-fs001.katalykt.lan   lab-centreon001.katalykt.lan   katalyktRO

            lab-fs002.katalykt.lan   lab-centreon001.katalykt.lan   katalyktRO

            lab-fs003.katalykt.lan   lab-centreon001.katalykt.lan   katalyktRO

            lab-fs004.katalykt.lan   lab-centreon001.katalykt.lan   katalyktRO

    .NOTES

            NAME:     Set-SNMPProperties

            AUTHOR:   ROULEAU Benjamin

            LASTEDIT: 2016-11-17

    .LINKS

            http://katalykt.blogspot.fr/

#>

    [CmdletBinding()]

    PARAM(

        [Parameter(

            Mandatory,

            ValueFromPipeline,

            ValueFromPipelineByPropertyName)]

        $Computer,

        

        $SNMPPermittedManager,


        $SNMPCommunity,


        [switch]$SNMPClear

    )


    BEGIN {


    }


    PROCESS {

        $Computer | ForEach-Object {

            Try {

                Write-Verbose -Message "[PROCESS - Set-SNMPProperties] Processing computer [$_]"


                If (Test-WSMan -ComputerName $_ -ErrorAction SilentlyContinue) {

                    Invoke-Command -ComputerName $_ -ErrorAction Stop -ErrorVariable ErrInvoke -ScriptBlock {

                        $VerbosePreference = $Using:VerbosePreference

                        

                        # Install the SNMP Service with the WMI provider if needed

                        If ((Get-WindowsFeature -Name "SNMP-Service").Installed -eq "True") {

                            Write-Verbose -Message "[PROCESS - Set-SNMPProperties] The SNMP-Service Windows Feature is already installed"

                        } Else {

                            Write-Verbose -Message "[PROCESS - Set-SNMPProperties] Installing the SNMP-Service Windows Feature"

                            

                            Get-WindowsFeature -Name "SNMP-Service" | Add-WindowsFeature -IncludeAllSubFeature -IncludeManagementTools

                        }


                        # Clear the existing managers/communities if specified

                        If ($SNMPClear) {

                            Write-Verbose -Message "[PROCESS - Set-SNMPProperties] Clearing up the existing Managers and Communities"


                            "PermittedManagers", "ValidCommunities" | ForEach-Object {

                                $Subkey = $_

                                (Get-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\$Subkey").GetValueNames() |  ForEach-Object {

                                    Write-Verbose -Message "[PROCESS - Set-SNMPProperties] Clearing up existing registry record: HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\$Subkey\$_"


                                    Remove-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\$Subkey" -Name $_

                                }

                            }

                        }


                        # Check if the given permitted managers are defined or not

                        Write-Verbose -Message "[PROCESS - Set-SNMPProperties] Checking up Permitted Managers..."


                        $LocalManagers = $using:SNMPPermittedManager

                        If ($LocalManagers) {

                            $PermittedManagers = Get-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\PermittedManagers"

                            $Index = ($PermittedManagers.ValueCount)+1

    

                            $PermittedManagers.GetValueNames() | ForEach-Object {

                                # If this manager is located within the manager array, we remove it from it

                                $Item = (Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\PermittedManagers" -Name $_).$_

                            

                                If ($Item -in $LocalManagers) {

                                    Write-Verbose -Message "[PROCESS - Set-SNMPProperties] Skipping Manager $Item since it's already present"

                                    $LocalManagers = $LocalManagers | Where-Object {$_ -ne $Item}

                                }

                            }


                            # Add the missing managers if needed

                            $LocalManagers | ForEach-Object {

                                Write-Verbose -Message "[PROCESS - Set-SNMPProperties] Adding Manager $_ in the Permitted list with Index $Index"


                                New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\PermittedManagers" -Name $Index -Value $_

                                $Index++

                            }

                        }


                        # Check if the community exists, if not we add it

                        Write-Verbose -Message "[PROCESS - Set-SNMPProperties] Checking up the communities..."


                        $using:SNMPCommunity | ForEach-Object {

                            If (-not(Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\ValidCommunities" -Name $_ -ErrorAction SilentlyContinue)) {

                                Write-Verbose -Message "[PROCESS - Set-SNMPProperties] Adding Community $_"


                                New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\ValidCommunities" -Name $_ -Value 4 -PropertyType DWORD

                            } Else {

                                Write-Verbose -Message "[PROCESS - Set-SNMPProperties] Skipping Community $_ since it's already present"

                            }

                        }


                        # Return the new SNMP settings for this host

                        New-Object -TypeName PSObject -Property @{

                            SNMPCommunities = (Get-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\ValidCommunities").GetValueNames()

                            SNMPManagers = (Get-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\PermittedManagers").GetValueNames() | ForEach-Object {(Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\PermittedManagers" -Name $_).$_}

                        }

                    }

                } Else {

                    Write-Warning -Message "[PROCESS - Set-SNMPProperties] Computer [$_] could not be contacted via WSMan"

                }

            } Catch {

                If ($ErrInvoke) { Write-Warning -Message ("[PROCESS - Set-SNMPProperties] Invoke-Command failed for computer [{0}] with error {1}" -f $Error[0].OriginInfo, $Error[0].Exception.Message) }

            }

        } | Select PSComputerName, SNMPManagers, SNMPCommunities

    }


    END {


    }

}