Send-ZabbixTrap.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

<#PSScriptInfo
 
.VERSION 1.2
 
.GUID 18bf0803-2626-46f5-b0d0-54e694985078
 
.AUTHOR saw-friendship
 
.COMPANYNAME
 
.COPYRIGHT saw-friendship
 
.TAGS Zabbix Sender OverTCP Json Send Trap
 
.LICENSEURI
 
.PROJECTURI https://sawfriendship.wordpress.com/
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
#>


<#
 
.DESCRIPTION
 Send-ZabbixTrap send data to zabbix server over TCP without zabbix_sender.exe
 
.LINK
 https://sawfriendship.wordpress.com/
 
.EXAMPLE
 Send-ZabbixTrap -z 172.16.5.2 -p 10051 -s Srv1 -k trap -o OK
  
 You can use parameter aliases as in zabbix_sender.exe
 z = zabbix server
 p = port
 s = host
 k = key
 o = value
 
.EXAMPLE
 Send-ZabbixTrap -z 172.16.5.2 -p 10051 -s Srv1 -k trap -o OK -OnlyPreview
 
 Only generating Json string for preview
  
.EXAMPLE
 Send-ZabbixTrap -Server 172.16.5.2 -Port 10051 -JsonString $json
  
 Json format example:
  
 [pscustomobject][ordered]@{
    'request' = 'sender data';
    'data' = @(
        1..3 | % {
            [pscustomobject][ordered]@{
                'host' = 'HOST'
                'key' = 'KEY'
                'value' = 'VALUE'
            }
        }
    )
} | ConvertTo-Json
 
 
.EXAMPLE
 Send-ZabbixTrap -Server 172.16.5.2 -Port 10051 -InputObject (Import-Csv -Encoding utf8 -Delimiter ';' -Path $home\srv.csv) -Header ComputerName,Service,Status
 
 The PropertyNames of the input objects must be "host, key, value" or be specified in the header parameter
 
#>
 



[CmdletBinding(DefaultParameterSetName="Set0")]
param(
    [alias("z")]
    [string]$Server = '172.16.5.2',
    
    [alias("p")]
    [ValidateRange(1,65535)]
    [int]$Port = '10051',
    
    [parameter(ParameterSetName="Set1")]
    [alias("s")]
    [string]$HostName,
    
    [parameter(ParameterSetName="Set1")]
    [alias("k")]
    [string]$Key,
    
    [parameter(ParameterSetName="Set1")]
    [alias("o")]
    [string]$Value,
    
    [parameter(ParameterSetName="Set2")]$InputObject,
    
    [parameter(ParameterSetName="Set2",HelpMessage='Enter 3 string values for mapping object property to json headers. Default "host","key","value"')]
    [ValidateCount(3,3)]
    [string[]]$Header = @('host','key','value'),
    
    [parameter(ParameterSetName="Set3")]
    [string]$JsonString,
    
    [parameter(HelpMessage='On generating Json-string for preview')]
    [switch]$OnlyPreview
)

if ( [bool]($HostName -or $Key -or $Value) ) {
        if(! [bool]($HostName -and $Key -and $Value) ) {
            Write-Error 'HostName, Key and Value must not be null';
            break
        } else {
            $Json = [pscustomobject][ordered]@{
                'request' = 'sender data' ;
                'data' = @([pscustomobject][ordered]@{'host' = $HostName;'key' = $Key;'value' = $Value})
            } | ConvertTo-Json -Compress

    }
} elseif ($InputObject) {
    $Json = [pscustomobject][ordered]@{
                'request' = 'sender data' ;
                'data' = @(
                    $InputObject | Select-Object -Property @(
                        @{'Name' = 'host'; Expression = {$_.$($Header[0])}},
                        @{'Name' = 'key'; Expression = {$_.$($Header[1])}},
                        @{'Name' = 'value'; Expression = {$_.$($Header[2])}}
                    )
                )
            } | ConvertTo-Json -Compress
} elseif ($JsonString) {
    $Json = $JsonString | ConvertFrom-Json | ConvertTo-Json -Compress
} else {
    Write-Error 'Input data not found';
    break
}

if(!$Json){
    Write-Error 'Can not convert InputData to Json string';
    break
}

if($OnlyPreview){
    $Json | ConvertFrom-Json | ConvertTo-Json;
    break
}

try {
    [byte[]]$Header = @([System.Text.Encoding]::ASCII.GetBytes('ZBXD')) + [byte]1
    [byte[]]$Length = @([System.BitConverter]::GetBytes($([long]$Json.Length)))
    [byte[]]$Data = @([System.Text.Encoding]::ASCII.GetBytes($Json))
    
    $All = $Header + $Length + $Data
    
} catch {
    Write-Error 'Can not convert Json string to byte';
    break
}

try {
    $Socket = New-Object System.Net.Sockets.Socket ([System.Net.Sockets.AddressFamily]::InterNetwork, [System.Net.Sockets.SocketType]::Stream, [System.Net.Sockets.ProtocolType]::Tcp)
    $Socket.Connect($Server,$Port)
    $Socket.Send($All) | Out-Null
    [byte[]]$Buffer = New-Object System.Byte[] 1000
    [int]$ReceivedLength = $Socket.Receive($Buffer)
    $Socket.Close()
} catch {
    Write-Error 'TCP-level Error connecting, sending or receiving';
    break
}

$Received = [System.Text.Encoding]::ASCII.GetString(@($Buffer[13 .. ($ReceivedLength - 1)]))

try{
    $Received | ConvertFrom-Json
} catch {
    Write-Warning 'It is not possible to convert the output to a Json string, maybe the server has rejected invalid data'
    $Received
}