File Coverage

blib/lib/Search/ESsearcher/Templates/httpAccess.pm
Criterion Covered Total %
statement 8 12 66.6
branch n/a
condition n/a
subroutine 3 7 42.8
pod 0 4 0.0
total 11 23 47.8


line stmt bran cond sub pod time code
1             package Search::ESsearcher::Templates::httpAccess;
2              
3 1     1   66805 use 5.006;
  1         10  
4 1     1   6 use strict;
  1         1  
  1         32  
5 1     1   7 use warnings;
  1         2  
  1         350  
6              
7             =head1 NAME
8              
9             Search::ESsearcher::Templates::httpAccess - Provicdes support for HTTP access logs sucked down via beats.
10              
11             =head1 VERSION
12              
13             Version 0.0.0
14              
15             =cut
16              
17             our $VERSION = '0.0.0';
18              
19             =head1 LOGSTASH / FILEBEAT
20              
21             This uses a logstath beasts input akin to below.
22              
23             The important bit below is setting the "type" to "beats" and "fields.log" to "apache-access".
24              
25             If you are using something different than "type" and "beats" you can specify that via "--field" and
26             "--fieldv" respectively.
27              
28             If you are using something different than "fields.log" and "apache-access" you can specify that via "--field2" and
29             "--field2v" respectively.
30              
31             input {
32             beats {
33             host => "192.168.14.3"
34             port => 5044
35             type => "beats"
36             }
37             }
38            
39             filter {
40             if [fields][log] == "apache-access" {
41             grok {
42             match => {
43             "message" => "%{HTTPD_COMBINEDLOG}+%{GREEDYDATA:extra_fields}"
44             }
45             overwrite => [ "message" ]
46             }
47            
48             mutate {
49             convert => ["response", "integer"]
50             convert => ["bytes", "integer"]
51             convert => ["responsetime", "float"]
52             }
53             geoip {
54             source => "clientip"
55             target => "geoip"
56             add_tag => [ "apache-geoip" ]
57             }
58             date {
59             match => [ "timestamp" , "dd/MMM/YYYY:HH:mm:ss Z" ]
60             remove_field => [ "timestamp" ]
61             }
62             useragent {
63             source => "agent"
64             }
65             }
66             }
67            
68             output {
69             if [type] == "beats" {
70             elasticsearch {
71             hosts => [ "127.0.0.1:9200" ]
72             }
73             }
74             }
75              
76             Then for file beats, something akin to below. The really important bits here the various
77             values for "fields".
78              
79             For "fields.vhost" and "fields.vhost_port" if you are using somethind different, you can
80             specify that via "--field3" and "--field4" respectively.
81              
82             - type: log
83             enabled: true
84             paths:
85             - /var/log/apache/foo.bar:80-access.log
86             fields:
87             log: apache-access
88             vhost: foo.bar
89             vhost_port: 80
90              
91              
92             =head1 Options
93              
94             =head2 --host <host>
95              
96             The machine beasts is running on feeding info to logstash/ES.
97              
98             =head2 --response <code>
99              
100             The response code from the HTTP server.
101              
102             =head2 --verb <verb>
103              
104             The verb used with the request.
105              
106             =head2 --vhost <vhost>
107              
108             The domain served up.
109              
110             =head2 --port <port>
111              
112             The port for the vhost.
113              
114             =head2 --ip <ip>
115              
116             The client IP that made the request.
117              
118             =head2 --os <os>
119              
120             The supplied OS value that made the request.
121              
122             =head2 --showos
123              
124             Shows the OS value.
125              
126             =head2 --req <req>
127              
128             The HTTP request.
129              
130             =head2 --ref <ref>
131              
132             The supplied referrer for the request.
133              
134             =head2 --agent <agent>
135              
136             The supplied agent value that made the request.
137              
138             =head2 --noagent
139              
140             Do not show the agent field.
141              
142             =head2 --auth <auth>
143              
144             The authed user for the request.
145              
146             =head2 --bgt <bytes>
147              
148             Response bytes greater than.
149              
150             =head2 --bgte <bytes>
151              
152             Response bytes greater than or equal to.
153              
154             =head2 --blt <bytes>
155              
156             Response bytes less than.
157              
158             =head2 --blte <bytes>
159              
160             Response bytes less than or equal to.
161              
162             =head2 --geoip
163              
164             Require GEO IP to have worked.
165              
166             =head2 --country <country>
167              
168             The 2 letter country code.
169              
170             =head2 --showcountry
171              
172             Show country code.
173              
174             =head2 --region <state>
175              
176             The state/province/etc to search for.
177              
178             =head2 --showregion
179              
180             Show region code.
181              
182             =head2 --postal <zipcode>
183              
184             The postal code to search for.
185              
186             =head2 --showpostal
187              
188             Show postal code.
189              
190             =head2 --city <cide>
191              
192             The city to search for.
193              
194             =head2 --showcity
195              
196             Show city name.
197              
198             =head2 --size <count>
199              
200             The number of items to return.
201              
202             =head2 --dgt <date>
203              
204             Date greater than.
205              
206             =head2 --dgte <date>
207              
208             Date greater than or equal to.
209              
210             =head2 --dlt <date>
211              
212             Date less than.
213              
214             =head2 --dlte <date>
215              
216             Date less than or equal to.
217              
218             =head2 --msg <message>
219              
220             Messages to match.
221              
222             =head1 AND, OR, or NOT shortcut
223              
224             , OR
225             + AND
226             ! NOT
227              
228             A list seperated by any of those will be transformed
229              
230             These may be used with program, facility, pid, or host.
231              
232             example: --program postfix,spamd
233            
234             results: postfix OR spamd
235              
236             =head1 date
237              
238             date
239              
240             /^-/ appends "now" to it. So "-5m" becomes "now-5m".
241              
242             /^u\:/ takes what is after ":" and uses Time::ParseDate to convert it to a
243             unix time value.
244              
245             Any thing not matching maching any of the above will just be passed on.
246              
247             =cut
248              
249              
250             sub search{
251 0     0 0   return '
252             [% USE JSON ( pretty => 1 ) %]
253             [% DEFAULT o.size = "50" %]
254             [% DEFAULT o.field = "type" %]
255             [% DEFAULT o.fieldv = "beats" %]
256             [% DEFAULT o.field2 = "fields.log" %]
257             [% DEFAULT o.field2v = "apache-access" %]
258             [% DEFAULT o.field3 = "fields.vhost" %]
259             [% DEFAULT o.field4 = "fields.vhost_port" %]
260             {
261             "index": "logstash-*",
262             "body": {
263             "size": [% o.size.json %],
264             "query": {
265             "bool": {
266             "must": [
267             {
268             "term": { [% o.field.json %]: [% o.fieldv.json %] }
269             },
270             {"query_string": {
271             "default_field": [% o.field2.json %],
272             "query": [% o.field2v.json %]
273             }
274             },
275             [% IF o.country %]
276             {"query_string": {
277             "default_field": "geoip.country_code2",
278             "query": [% aon( o.country ).json %]
279             }
280             },
281             [% END %]
282             [% IF o.region %]
283             {"query_string": {
284             "default_field": "geoip.region_code",
285             "query": [% aon( o.region ).json %]
286             }
287             },
288             [% END %]
289             [% IF o.city %]
290             {"query_string": {
291             "default_field": "geoip.city_name",
292             "query": [% aon( o.city ).json %]
293             }
294             },
295             [% END %]
296             [% IF o.postal %]
297             {"query_string": {
298             "default_field": "geoip.postal_code",
299             "query": [% aon( o.postal ).json %]
300             }
301             },
302             [% END %]
303             [% IF o.host %]
304             {"query_string": {
305             "default_field": "host",
306             "query": [% aon( o.host ).json %]
307             }
308             },
309             [% END %]
310             [% IF o.msg %]
311             {"query_string": {
312             "default_field": "message",
313             "query": [% o.msg.json %]
314             }
315             },
316             [% END %]
317             [% IF o.response %]
318             {"query_string": {
319             "default_field": "response",
320             "query": [% aon( o.response ).json %]
321             }
322             },
323             [% END %]
324             [% IF o.geoip %]
325             {"query_string": {
326             "default_field": "geoip.country_code2",
327             "query": "*"
328             }
329             },
330             [% END %]
331             [% IF o.verb %]
332             {"query_string": {
333             "default_field": "verb",
334             "query": [% aon( o.verb ).json %]
335             }
336             },
337             [% END %]
338             [% IF o.vhost %]
339             {"query_string": {
340             "default_field": "fields.vhost",
341             "query": [% aon( o.vhost ).json %]
342             }
343             },
344             [% END %]
345             [% IF o.port %]
346             {"query_string": {
347             "default_field": "fields.vhost_port",
348             "query": [% aon( o.port ).json %]
349             }
350             },
351             [% END %]
352             [% IF o.os %]
353             {"query_string": {
354             "default_field": "os",
355             "query": [% aon( o.os ).json %]
356             }
357             },
358             [% END %]
359             [% IF o.agent %]
360             {"query_string": {
361             "default_field": "agent",
362             "query": [% aon( o.agent ).json %]
363             }
364             },
365             [% END %]
366             [% IF o.ip %]
367             {"query_string": {
368             "default_field": "clientip",
369             "query": [% aon( o.ip ).json %]
370             }
371             },
372             [% END %]
373             [% IF o.auth %]
374             {"query_string": {
375             "default_field": "auth",
376             "query": [% aon( o.auth ).json %]
377             }
378             },
379             [% END %]
380             [% IF o.req %]
381             {"query_string": {
382             "default_field": "request",
383             "query": [% aon( o.req ).json %]
384             }
385             },
386             [% END %]
387             [% IF o.ref %]
388             {"query_string": {
389             "default_field": "referrer",
390             "query": [% aon( o.ref ).json %]
391             }
392             },
393             [% END %]
394             [% IF o.bgt %]
395             {"range": {
396             "bytes": {
397             "gt": [% pd( o.bgt ).json %]
398             }
399             }
400             },
401             [% END %]
402             [% IF o.bgte %]
403             {"range": {
404             "bytes": {
405             "gte": [% pd( o.bgte ).json %]
406             }
407             }
408             },
409             [% END %]
410             [% IF o.blt %]
411             {"range": {
412             "bytes": {
413             "lt": [% pd( o.blt ).json %]
414             }
415             }
416             },
417             [% END %]
418             [% IF o.blte %]
419             {"range": {
420             "bytes": {
421             "lte": [% pd( o.blte ).json %]
422             }
423             }
424             },
425             [% END %]
426              
427             [% IF o.dgt %]
428             {"range": {
429             "@timestamp": {
430             "gt": [% pd( o.dgt ).json %]
431             }
432             }
433             },
434             [% END %]
435             [% IF o.dgte %]
436             {"range": {
437             "@timestamp": {
438             "gte": [% pd( o.dgte ).json %]
439             }
440             }
441             },
442             [% END %]
443             [% IF o.dlt %]
444             {"range": {
445             "@timestamp": {
446             "lt": [% pd( o.dlt ).json %]
447             }
448             }
449             },
450             [% END %]
451             [% IF o.dlte %]
452             {"range": {
453             "@timestamp": {
454             "lte": [% pd( o.dlte ).json %]
455             }
456             }
457             },
458             [% END %]
459             ]
460             }
461             },
462             "sort": [
463             {
464             "@timestamp": {"order" : "desc"}}
465             ]
466             }
467             }
468             ';
469             }
470              
471             sub options{
472 0     0 0   return '
473             host=s
474             response=s
475             verb=s
476             vhost=s
477             port=s
478             ip=s
479             os=s
480             agent=s
481             auth=s
482             req=s
483             showos
484             geoip
485             country=s
486             ref=s
487             bgt=s
488             bgte=s
489             blt=s
490             blte=s
491             showcountry
492             showregion
493             showpostal
494             showcity
495             region=s
496             postal=s
497             city=s
498             msg=s
499             size=s
500             field=s
501             fieldv=s
502             field2=s
503             field2v=s
504             field3=s
505             field4=s
506             noagent
507             dgt=s
508             dgte=s
509             dlt=s
510             dlte=s
511             ';
512             }
513              
514             sub output{
515 0     0 0   return '[% c("cyan") %][% f.timestamp %] '.
516             '[% c("bright_blue") %][% f.fields.vhost %][% c("bright_yellow") %]:[% c("bright_magenta") %][% f.fields.vhost_port %] '.
517             '[% c("bright_cyan") %][% f.clientip %]'.
518              
519             '[% IF o.showcountry %]'.
520             '[% IF f.geoip.country_code2 %]'.
521             '[% c("yellow") %]('.
522             '[% c("bright_green") %][% f.geoip.country_code2 %]'.
523             '[% c("yellow") %])'.
524             '[% END %]'.
525             '[% END %]'.
526              
527             '[% IF o.showregion %]'.
528             '[% IF f.geoip.region_code %]'.
529             '[% c("yellow") %]('.
530             '[% c("bright_green") %][% f.geoip.region_code %]'.
531             '[% c("yellow") %])'.
532             '[% END %]'.
533             '[% END %]'.
534              
535             '[% IF o.showcity %]'.
536             '[% IF f.geoip.city_name %]'.
537             '[% c("yellow") %]('.
538             '[% c("bright_green") %][% f.geoip.city_name %]'.
539             '[% c("yellow") %])'.
540             '[% END %]'.
541             '[% END %]'.
542              
543             '[% IF o.showpostal %]'.
544             '[% IF f.geoip.postal_code %]'.
545             '[% c("yellow") %]('.
546             '[% c("bright_green") %][% f.geoip.postal_code %]'.
547             '[% c("yellow") %])'.
548             '[% END %]'.
549             '[% END %]'.
550              
551             ' [% c("bright_red") %][% f.auth %] '.
552             '[% c("bright_yellow") %][% f.verb %] '.
553             '[% c("bright_magenta") %][% f.request %] '.
554             '[% c("bright_blue") %][% f.response %] '.
555             '[% c("bright_green") %][% f.bytes %] '.
556             '[% c("cyan") %][% f.referrer %] '.
557              
558             '[% IF o.showos %]'.
559             '[% c("green") %][% f.os %] '.
560             '[% END %]'.
561              
562             '[% IF ! o.noagent %]'.
563             '[% c("magenta") %][% f.agent %]'.
564             '[% END %]'.
565             ''
566             ;
567             }
568              
569             sub help{
570 0     0 0   return '
571              
572              
573              
574             --host <log host> The system beats in question is running on.
575             --response <code> The response code from the HTTP server.
576             --verb <verb> The verb used with the request.
577             --vhost <vhost> The domain served up.
578             --port <port> The port for the vhost.
579             --ip <ip> The client IP that made the request.
580             --os <os> The supplied OS value that made the request.
581             --showos Shows the OS value.
582             --req <req> The HTTP request.
583             --ref <ref> The supplied referrer for the request.
584             --agent <agent> The supplied agent value that made the request.
585             --noagent Do not show the agent field.
586             --auth <auth> The authed user for the request.
587              
588             --bgt <bytes> Response bytes greater than.
589             --bgte <bytes> Response bytes greater than or equal to.
590             --blt <bytes> Response bytes less than.
591             --blte <bytes> Response bytes less than or equal to.
592              
593             --geoip Require GEO IP to have worked.
594             --country <country> The 2 letter country code.
595             --showcountry Show country code.
596             --region <state> The state/province/etc to search for.
597             --showregion Show region code.
598             --postal <zipcode> The postal code to search for.
599             --showpostal Show postal code.
600             --city <cide> The city to search for.
601             --showcity Show city name.
602              
603             --dgt <date> Date greater than.
604             --dgte <date> Date greater than or equal to.
605             --dlt <date> Date less than.
606             --dlte <date> Date less than or equal to.
607              
608             --msg <message> Messages to match.
609             --size <size> The max number of matches to return.
610              
611             --field <field> The term field to use for matching them all.
612             --field2 <field2> The term field to use for what beats is setting.
613             --fieldv <fieldv> The value of the term field to matching them all.
614             --field2v <field2v> The value to look for in the field beats is setting.
615              
616              
617              
618             AND, OR, or NOT shortcut
619             , OR
620             + AND
621             ! NOT
622              
623             A list seperated by any of those will be transformed
624              
625             These may be used with host, country, jail, region, postal, city, and ip.
626              
627             example: --country CN,RU
628              
629              
630              
631             field and fieldv
632              
633             The search template is written with the expectation that logstash is setting
634             "type" with a value of "syslog". If you are using like "tag" instead of "type"
635             or the like, this allows you to change the field and value.
636              
637              
638              
639             date
640              
641             /^-/ appends "now" to it. So "-5m" becomes "now-5m".
642              
643             /^u\:/ takes what is after ":" and uses Time::ParseDate to convert it to a
644             unix time value.
645              
646             Any thing not matching maching any of the above will just be passed on.
647             ';
648              
649              
650             }