2
0
Files
PowershellScripts/Services/Install-configure-SNMP-Service.ps1

228 lines
10 KiB
PowerShell

<#
.SYNOPSIS
Installs, configures, and secures the SNMP Service and components on a remote or local Windows Server.
.DESCRIPTION
This script is idempotent. It installs the SNMP features, sets Agent details, configures the Community String,
checks if the Allowed IP is already present before adding it, creates missing registry keys only if needed,
opens UDP 161 in the Windows Firewall, and correctly executes commands locally if the target is the local machine
(bypassing Invoke-Command for local execution).
.PARAMETER ComputerName
The name of the remote computer (Windows Server) where SNMP will be installed. Defaults to the local machine if not specified.
.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
# Run on the local machine (commands execute directly, no Invoke-Command)
.\Install-Configure-SNMP.ps1 -CommunityString "MySecureString" -AllowedIPOrHost "192.168.1.10"
.EXAMPLE
# Run on a remote machine (commands execute via Invoke-Command)
.\Install-Configure-SNMP.ps1 -ComputerName "Server01" -CommunityString "MySecureString" -AllowedIPOrHost "192.168.1.10" -AgentContact "IT Operations"
#>
param(
[Parameter(Mandatory=$false)]
[string]$ComputerName = $env: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
$IsLocal = ($ComputerName -ceq $env:COMPUTERNAME) # Check if target is the local machine (case-exact)
Write-Host "--- Starting SNMP Service installation, configuration, and firewall setup on $($ComputerName) ---"
if ($IsLocal) {
Write-Host "NOTE: Running in LOCAL execution mode (bypassing Invoke-Command). 🖥️"
} else {
Write-Host "NOTE: Running in REMOTE execution mode (using Invoke-Command). 🌐"
}
Write-Host "--------------------------------------------------------------------------------"
# --- Function to handle execution (Local or Remote) ---
function Execute-ScriptBlock {
param(
[ScriptBlock]$ScriptBlock,
[Array]$ArgumentList
)
if ($IsLocal) {
# Run locally by invoking the script block directly
& $ScriptBlock @ArgumentList
} else {
# Run remotely via Invoke-Command
Invoke-Command -ComputerName $ComputerName -ScriptBlock $ScriptBlock -ArgumentList $ArgumentList -ErrorAction Stop
}
}
# -----------------------------------------------------
try {
# 1. Install SNMP Service and WMI Provider (including RSAT-SNMP)
Write-Host "1. Installing $($SNMPFeatures -join ', ') on $($ComputerName)..."
$InstallFeaturesBlock = {
param($Features)
$InstalledFeatures = Get-WindowsFeature $Features | Where-Object { $_.Installed -eq $true }
if ($InstalledFeatures.Count -ne $Features.Count) {
Write-Host "Installing features..."
# Using -IncludeAllSubFeature to ensure all dependencies are met
$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."
}
}
Execute-ScriptBlock -ScriptBlock $InstallFeaturesBlock -ArgumentList @($SNMPFeatures)
# 2. Configure SNMP Service (Contact, Location, Community String, Allowed IPs, and Agent Services)
Write-Host "2. Configuring SNMP Service parameters on $($ComputerName)..."
$ConfigureSNMPBlock = {
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"
# Using -Force here is necessary to ensure it's created if 'SNMP' exists but 'Parameters' doesn't.
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'."
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'."
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
}
}
Execute-ScriptBlock -ScriptBlock $ConfigureSNMPBlock -ArgumentList @($CommunityString, $AllowedIPOrHost, $AgentServicesName, $AgentServicesValue, $AgentContact, $AgentLocation)
# 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)..."
$ConfigureFirewallBlock = {
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
}
Execute-ScriptBlock -ScriptBlock $ConfigureFirewallBlock -ArgumentList @($FirewallRuleName, $SNMPPort, $AllowedIPOrHost)
# 4. Restart SNMP Service
Write-Host "4. Restarting SNMP Service on $($ComputerName) to apply all changes (Configuration & Firewall)."
$RestartServiceBlock = {
Restart-Service -Name "SNMP" -ErrorAction Stop
}
Execute-ScriptBlock -ScriptBlock $RestartServiceBlock
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
}