<# .SYNOPSIS Installs, configures, and secures the SNMP Service and components on a remote Windows Server. It includes optional parameters for setting Agent Contact and Location details. .DESCRIPTION This script is idempotent. It installs the SNMP features, uses the RFC1156Agent key to set sysServices, sysContact, and sysLocation, configures the Community String (Read Only), checks if the Allowed IP is already present before adding it to the Permitted Managers, creates missing registry keys only if needed, and opens UDP 161 in the Windows Firewall. .PARAMETER ComputerName The name of the remote computer (Windows Server) where SNMP will be installed. .PARAMETER CommunityString The custom community string to be configured for the SNMP Service. .PARAMETER AllowedIPOrHost The IP address, IP range, or hostname allowed to query the SNMP Service. This is used for both SNMP service configuration and the Firewall rule. Use "0.0.0.0" for any host. .PARAMETER AgentContact Optional. The contact person or email address for the SNMP agent (written to sysContact). .PARAMETER AgentLocation Optional. The physical location of the SNMP agent (written to sysLocation). .EXAMPLE .\Install-Configure-SNMP.ps1 -ComputerName "Server01" -CommunityString "MySecureString" -AllowedIPOrHost "192.168.1.10" -AgentContact "IT Operations" -AgentLocation "Server Room A" .EXAMPLE .\Install-Configure-SNMP.ps1 -ComputerName "TestServer" -CommunityString "PublicAccess" -AllowedIPOrHost "0.0.0.0" #> param( [Parameter(Mandatory=$true)] [string]$ComputerName, [Parameter(Mandatory=$true)] [string]$CommunityString, [Parameter(Mandatory=$true)] [string]$AllowedIPOrHost, [Parameter(Mandatory=$false)] [string]$AgentContact, [Parameter(Mandatory=$false)] [string]$AgentLocation ) # Define the features to install and the firewall details $SNMPFeatures = "SNMP-Service", "SNMP-WMI-Provider", "RSAT-SNMP" $FirewallRuleName = "Allow-SNMP-Inbound-UDP161" $SNMPPort = 161 $AgentServicesName = "sysServices" $AgentServicesValue = 79 Write-Host "--- Starting SNMP Service installation, configuration, and firewall setup on $($ComputerName) ---" try { # 1. Install SNMP Service and WMI Provider (including RSAT-SNMP) remotely Write-Host "1. Installing $($SNMPFeatures -join ', ') on $($ComputerName)..." Invoke-Command -ComputerName $ComputerName -ScriptBlock { param($Features) # Install the features if not already present $InstalledFeatures = Get-WindowsFeature $Features | Where-Object { $_.Installed -eq $true } if ($InstalledFeatures.Count -ne $Features.Count) { Write-Host "Installing features..." $InstallationResult = Install-WindowsFeature -Name $Features -IncludeAllSubFeature -ErrorAction Stop if (-not $InstallationResult.Success) { throw "Feature installation failed. Details: $($InstallationResult | Out-String)" } } else { Write-Host "SNMP features are already installed." } } -ArgumentList $SNMPFeatures -ErrorAction Stop # 2. Configure SNMP Service remotely (Contact, Location, Community String, Allowed IPs, and Agent Services) Write-Host "2. Configuring SNMP Service parameters on $($ComputerName)..." Invoke-Command -ComputerName $ComputerName -ScriptBlock { param($Community, $IPOrHost, $ServicesName, $ServicesValue, $Contact, $Location) # Define Registry paths $SNMPRegBase = "HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters" $RFC1156AgentRegKey = "$SNMPRegBase\RFC1156Agent" $ValidCommunitiesRegKey = "$SNMPRegBase\ValidCommunities" $PermittedManagersRegKey = "$SNMPRegBase\PermittedManagers" # --- Ensure required registry keys exist recursively and create only if missing --- Write-Host " -> Ensuring required registry keys exist..." # Check and create the parent 'Parameters' key if it's missing (needed for subsequent checks) if (-not (Test-Path $SNMPRegBase)) { Write-Host " -> Creating base Parameters key: $SNMPRegBase" New-Item -Path $SNMPRegBase -Type Directory -Force -ErrorAction Stop | Out-Null } # Array of subkeys to check and create $SubKeysToCreate = @( $RFC1156AgentRegKey, $ValidCommunitiesRegKey, $PermittedManagersRegKey ) foreach ($KeyPath in $SubKeysToCreate) { if (-not (Test-Path $KeyPath)) { Write-Host " -> Creating missing subkey: $KeyPath" New-Item -Path $KeyPath -Type Directory -ErrorAction Stop | Out-Null } } # --- Configure Agent Contact (sysContact) --- if (-not [string]::IsNullOrEmpty($Contact)) { Write-Host " -> Setting Agent Contact (sysContact) to '$Contact'." # Use Type STRING (RegSZ) for text fields Set-ItemProperty -Path $RFC1156AgentRegKey -Name "sysContact" -Value $Contact -Type String -Force -ErrorAction Stop } else { Write-Host " -> Agent Contact parameter was empty, skipping sysContact configuration." } # --- Configure Agent Location (sysLocation) --- if (-not [string]::IsNullOrEmpty($Location)) { Write-Host " -> Setting Agent Location (sysLocation) to '$Location'." # Use Type STRING (RegSZ) for text fields Set-ItemProperty -Path $RFC1156AgentRegKey -Name "sysLocation" -Value $Location -Type String -Force -ErrorAction Stop } else { Write-Host " -> Agent Location parameter was empty, skipping sysLocation configuration." } # --- Community String Configuration --- Write-Host " -> Setting Community String to '$Community' (Read Only, Value=4)." Set-ItemProperty -Path $ValidCommunitiesRegKey -Name $Community -Value 4 -Type DWORD -Force -ErrorAction Stop # --- Enable All Agent Services --- Write-Host " -> Enabling all services under the SNMP Agent tab (Key: '$ServicesName', Value: $($ServicesValue))." Set-ItemProperty -Path $RFC1156AgentRegKey -Name $ServicesName -Value $ServicesValue -Type DWORD -Force -ErrorAction Stop # --- Allowed IP/Host Configuration (Idempotent Check) --- Write-Host " -> Checking if host '$IPOrHost' is already in the Permitted Managers list..." $ExistingManagers = Get-ItemProperty -Path $PermittedManagersRegKey | Select-Object -Property * -ExcludeProperty PS* | Out-String if ($ExistingManagers -like "*$IPOrHost*") { Write-Host " -> Host '$IPOrHost' already exists. Skipping addition." } else { $Index = 2 do { $RegValue = Get-ItemProperty -Path $PermittedManagersRegKey -Name $Index -ErrorAction SilentlyContinue if ($RegValue) { $Index++ } } while ($RegValue) Write-Host " -> Host '$IPOrHost' not found. Adding as index $Index." Set-ItemProperty -Path $PermittedManagersRegKey -Name $Index -Value $IPOrHost -Type STRING -Force -ErrorAction Stop } } -ArgumentList $CommunityString, $AllowedIPOrHost, $AgentServicesName, $AgentServicesValue, $AgentContact, $AgentLocation -ErrorAction Stop # 3. Configure Windows Firewall Rule (Idempotent: removes and re-creates) Write-Host "3. Configuring Windows Firewall to allow UDP port $($SNMPPort) from $($AllowedIPOrHost) on $($ComputerName)..." Invoke-Command -ComputerName $ComputerName -ScriptBlock { param($RuleName, $Port, $IPOrHost) # Remove existing rule if it exists (for clean updates) if (Get-NetFirewallRule -DisplayName $RuleName -ErrorAction SilentlyContinue) { Write-Host " -> Removing existing rule '$RuleName'." Remove-NetFirewallRule -DisplayName $RuleName -Confirm:$false -ErrorAction SilentlyContinue } # Create the new firewall rule Write-Host " -> Creating new inbound rule '$RuleName' for UDP $Port." New-NetFirewallRule -DisplayName $RuleName ` -Direction Inbound ` -Action Allow ` -Protocol UDP ` -LocalPort $Port ` -RemoteAddress $IPOrHost ` -Profile Any ` -ErrorAction Stop } -ArgumentList $FirewallRuleName, $SNMPPort, $AllowedIPOrHost -ErrorAction Stop # 4. Restart SNMP Service Write-Host "4. Restarting SNMP Service on $($ComputerName) to apply all changes (Configuration & Firewall)." Invoke-Command -ComputerName $ComputerName -ScriptBlock { Restart-Service -Name "SNMP" -ErrorAction Stop } -ErrorAction Stop Write-Host "--- SNMP installation, configuration, and firewall setup on $($ComputerName) is complete! ✅ ---" } catch { Write-Error "An error occurred during execution on $($ComputerName). Error details: $($_.Exception.Message)" exit 1 }