root/src/modules-lua/noit/module/tcp.lua

Revision 91e019b9ab8d8a173d846a8b0c0cde78960d15ab, 8.9 kB (checked in by Dan Di Spaltro <dan@cloudkick.com>, 2 years ago)

Keep it more consistent like with body_match.

  • Property mode set to 100644
Line 
1 -- Copyright (c) 2009, OmniTI Computer Consulting, Inc.
2 -- All rights reserved.
3 --
4 -- Redistribution and use in source and binary forms, with or without
5 -- modification, are permitted provided that the following conditions are
6 -- met:
7 --
8 --     * Redistributions of source code must retain the above copyright
9 --       notice, this list of conditions and the following disclaimer.
10 --     * Redistributions in binary form must reproduce the above
11 --       copyright notice, this list of conditions and the following
12 --       disclaimer in the documentation and/or other materials provided
13 --       with the distribution.
14 --     * Neither the name OmniTI Computer Consulting, Inc. nor the names
15 --       of its contributors may be used to endorse or promote products
16 --       derived from this software without specific prior written
17 --       permission.
18 --
19 -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 -- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 -- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 -- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 -- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 -- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 -- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 -- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 -- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 -- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 module(..., package.seeall)
32
33 function onload(image)
34   image.xml_description([=[
35 <module>
36   <name>tcp</name>
37   <description><para>TCP metrics check.</para></description>
38   <loader>lua</loader>
39   <object>noit.module.tcp</object>
40   <moduleconfig />
41   <checkconfig>
42     <parameter name="port" required="required"
43                allowed="\d+">Specifies the port on which the management interface can be reached.</parameter>
44     <parameter name="banner_match" required="optional"
45               allowed=".+">This regular expression is matched against the response banner.  If a match is not found, the check will be marked as bad.</parameter>
46   <parameter name="send_body" required="optional"
47             allowed=".+">Data to send on the socket once connected and optionally SSL is negotiated, but before the body match is tested.</parameter>
48   <parameter name="body_match" required="optional"
49             allowed=".+">This regular expression is matched against the body (the leftover data up to 1024 bytes) after the banner.</parameter>
50     <parameter name="use_ssl" required="optional" allowed="^(?:true|false|on|off)$" default="false">Upgrade TCP connection to use SSL.</parameter>
51     <parameter name="ca_chain"
52                required="optional"
53                allowed=".+">A path to a file containing all the certificate authorities that should be loaded to validat
54 e the remote certificate (for SSL checks).</parameter>
55     <parameter name="certificate_file"
56                required="optional"
57                allowed=".+">A path to a file containing the client certificate that will be presented to the remote serv
58 er (for SSL checks).</parameter>
59     <parameter name="key_file"
60                required="optional"
61                allowed=".+">A path to a file containing key to be used in conjunction with the cilent certificate (for S
62 SL checks).</parameter>
63     <parameter name="ciphers"
64                required="optional"
65                allowed=".+">A list of ciphers to be used in the SSL protocol (for SSL checks).</parameter>
66   </checkconfig>
67   <examples>
68     <example>
69       <title>Checking TCP connection.</title>
70       <para>This example checks IMAP connection with and without SSL.</para>
71       <programlisting><![CDATA[
72       <noit>
73         <modules>
74           <loader image="lua" name="lua">
75             <config><directory>/opt/reconnoiter/libexec/modules-lua/?.lua</directory></config>
76           </loader>
77           <module loader="lua" name="tcp" object="noit.module.tcp" />
78         </modules>
79         <checks>
80           <imaps target="10.0.7.2" module="tcp" period="10000" timeout="5000">
81             <check uuid="79ba881e-ad2e-11de-9fb0-a322e3288ca7" name="imap">
82               <config>
83                 <port>143</port>
84                 <banner_match>^\* OK</banner_match>
85               </config>
86             </check>
87             <check uuid="a18659c2-add8-11de-bd01-7ff0e1a67246" name="imaps">
88               <config>
89                 <port>993</port>
90                 <banner_match>^\* OK</banner_match>
91                 <use_ssl>true</use_ssl>
92               </config>
93             </check>
94           </imaps>
95         </checks>
96       </noit>
97     ]]></programlisting>
98     </example>
99   </examples>
100
101 </module>
102 ]=]);
103   return 0
104 end
105
106 function init(module)
107   return 0
108 end
109
110 function config(module, options)
111   return 0
112 end
113
114 function elapsed(check, name, starttime, endtime)
115     local elapsedtime = endtime - starttime
116     local seconds = string.format('%.3f', noit.timeval.seconds(elapsedtime))
117     check.metric_uint32(name, math.floor(seconds * 1000 + 0.5))
118     return seconds
119 end
120
121 function initiate(module, check)
122   local starttime = noit.timeval.now()
123   local max_len = 80
124   check.bad()
125   check.unavailable()
126   check.status("unknown error")
127   local good = false
128   local status = ""
129   local use_ssl = false
130
131   if check.config.port == nil then
132     check.status("port is not specified")
133     return
134   end
135
136   -- SSL
137   if check.config.use_ssl == "true" or check.config.use_ssl == "on" then
138     use_ssl = true
139   end
140
141   local e = noit.socket(check.target_ip)
142   local rv, err = e:connect(check.target_ip, check.config.port)
143
144   if rv ~= 0 then
145     check.status(err or "connect error")
146     return
147   end
148
149   if use_ssl == true then
150     rv, err = e:ssl_upgrade_socket(check.config.certificate_file,
151                                         check.config.key_file,
152                                         check.config.ca_chain,
153                                         check.config.ciphers)
154   end
155
156   local connecttime = noit.timeval.now()
157   elapsed(check, "tt_connect", starttime, connecttime)
158   if rv ~= 0 then
159     check.status(err or "connection failed")
160     return
161   end
162
163   status = "connected"
164   check.available()
165   good = true
166
167   -- ssl metrics
168   local ssl_ctx = e:ssl_ctx()
169   if ssl_ctx ~= nil then
170     if ssl_ctx.error ~= nil then status = status .. ',sslerror' end
171     check.metric_string("cert_error", ssl_ctx.error)
172     check.metric_string("cert_issuer", ssl_ctx.issuer)
173     check.metric_string("cert_subject", ssl_ctx.subject)
174     check.metric_uint32("cert_start", ssl_ctx.start_time)
175     check.metric_uint32("cert_end", ssl_ctx.end_time)
176     check.metric_int32("cert_end_in", ssl_ctx.end_time - os.time())
177     if noit.timeval.seconds(starttime) > ssl_ctx.end_time then
178       good = false
179       status = status .. ',ssl=expired'
180     end
181   end
182
183   if check.config.send_body ~= nil then
184     if e:write(check.config.send_body) < 0 then
185       check.bad()
186       check.status("send_body: received hangup")
187       return
188     end
189   end
190
191   -- match banner
192   if check.config.banner_match ~= nil then
193     str = e:read("\n")
194     local firstbytetime = noit.timeval.now()
195     elapsed(check, "tt_firstbyte", starttime, firstbytetime)
196
197     local bannerre = noit.pcre(check.config.banner_match)
198     if bannerre ~= nil then
199       local rv, m, m1 = bannerre(str)
200       if rv then
201         m = m1 or m or str
202         if string.len(m) > max_len then
203           m = string.sub(m,1,max_len)
204         end
205         status = status .. ',banner_match=matched'
206         check.metric_string('banner_match',m)
207       else
208         good = false
209         status = status .. ',banner_match=failed'
210         check.metric_string('banner_match','')
211       end
212     end
213     if string.len(str) > max_len then
214       str = string.sub(str,1,max_len)
215     end
216     check.metric_string('banner',str)
217   end
218
219   -- match body
220   if check.config.body_match ~= nil then
221     str = e:read(1024)
222     if str == nil then
223       check.status("bad body length " .. (str and str:len() or "0"))
224       return
225     end
226     local bodybytetime = noit.timeval.now()
227     elapsed(check, "tt_body", starttime, bodybytetime)
228
229     local exre = noit.pcre(check.config.body_match)
230     local rv = true
231     local found = false
232     local m = nil
233     while rv and m ~= '' do
234       rv, m, key, value = exre(str or '', { limit = pcre_match_limit })
235       if rv then
236         found = true
237         if key ~= nil then
238           check.metric(key, value)
239         end
240       end
241     end
242
243     if found then
244       status = status .. ',body_match=matched'
245     else
246       good = false
247       status = status .. ',body_match=failed'
248     end
249
250     check.metric_string('body',str)
251   end
252
253   -- turnaround time
254   local endtime = noit.timeval.now()
255   local seconds = elapsed(check, "duration", starttime, endtime)
256   status = status .. ',rt=' .. seconds .. 's'
257   if good then check.good() else check.bad() end
258   check.status(status)
259
260 end
261
Note: See TracBrowser for help on using the browser.