@@ -2,6 +2,7 @@ package logparser
2
2
3
3
import (
4
4
"fmt"
5
+ "html/template"
5
6
"log"
6
7
"math"
7
8
"os"
@@ -83,7 +84,7 @@ func (s *SshdParser) Parse(logline string) error {
83
84
// Check if dates are the same
84
85
if oldest != dstr {
85
86
// Check who is the oldest
86
- parsedOldest , _ := time .Parse ("2006-01-02 " , oldest )
87
+ parsedOldest , _ := time .Parse ("20060102 " , oldest )
87
88
if parsedTime .Before (parsedOldest ) {
88
89
r .Do ("SET" , "oldest" , dstr )
89
90
}
@@ -101,7 +102,7 @@ func (s *SshdParser) Parse(logline string) error {
101
102
// Check if dates are the same
102
103
if newest != dstr {
103
104
// Check who is the newest
104
- parsedNewest , _ := time .Parse ("2006-01-02 " , newest )
105
+ parsedNewest , _ := time .Parse ("20060102 " , newest )
105
106
if parsedTime .After (parsedNewest ) {
106
107
r .Do ("SET" , "newest" , dstr )
107
108
}
@@ -228,6 +229,95 @@ func (s *SshdParser) Compile() error {
228
229
}
229
230
}
230
231
232
+ // Write html file for navigating plots
233
+ const tpl = `
234
+ <!DOCTYPE html>
235
+ <html>
236
+ <head>
237
+ <meta charset="UTF-8">
238
+ <title>{{.Title}}</title>
239
+ <script>
240
+ var currentType = "statsusername";
241
+ var currentDay = {{.MaxDate}};
242
+ </script>
243
+ <script src="load.js"></script>
244
+ <style>
245
+ body {
246
+ background: white
247
+ }
248
+ #imageholder {
249
+ background: black;
250
+ color: white;
251
+ padding: 1em;
252
+ position: absolute;
253
+ top: 50%;
254
+ left: 50%;
255
+ margin-right: -50%;
256
+ transform: translate(-50%, -40%)
257
+ }
258
+ span {
259
+ float: left;
260
+ clear: left;
261
+ }
262
+ </style>
263
+ </head>
264
+ <body onload="loadImage({{.Current}}, currentType)">
265
+ <span>
266
+ <label for="statsday">Statistics for: </label>
267
+ <input id="statsday" type="date" value="{{.MaxDate}}" min="{{.MinDate}}" max="{{.MaxDate}}" onchange="currentDay = this.value.replace(/-/g, ''); loadImage(currentDay, currentType)"/>
268
+ </span>
269
+ <span>
270
+ <label for="statstype">Type: </label>
271
+ <select selected="statsusername" onchange="currentType = this.value; loadImage(currentDay.replace(/-/g, ''), currentType)">
272
+ <option value="statsusername">Usernames</option>
273
+ <option value="statssrc">Sources</option>
274
+ <option value="statshost">Hosts</option>
275
+ </select>
276
+ </span>
277
+ <span id="imageholder"></span>
278
+ </body>
279
+ </html>`
280
+
281
+ // Get oldest / newest entries
282
+ var newest string
283
+ var oldest string
284
+ if newest , err = redis .String (r .Do ("GET" , "newest" )); err == redis .ErrNil {
285
+ r .Close ()
286
+ return err
287
+ }
288
+ if oldest , err = redis .String (r .Do ("GET" , "oldest" )); err == redis .ErrNil {
289
+ r .Close ()
290
+ return err
291
+ }
292
+ parsedOldest , _ := time .Parse ("20060102" , oldest )
293
+ parsedNewest , _ := time .Parse ("20060102" , newest )
294
+ parsedOldestStr := parsedOldest .Format ("2006-01-02" )
295
+ parsedNewestStr := parsedNewest .Format ("2006-01-02" )
296
+
297
+ check := func (err error ) {
298
+ if err != nil {
299
+ log .Fatal (err )
300
+ }
301
+ }
302
+ t , err := template .New ("webpage" ).Parse (tpl )
303
+ check (err )
304
+
305
+ data := struct {
306
+ Title string
307
+ Current string
308
+ MinDate string
309
+ MaxDate string
310
+ }{
311
+ Title : "sshd failed logins statistics" ,
312
+ MinDate : parsedOldestStr ,
313
+ MaxDate : parsedNewestStr ,
314
+ Current : newest ,
315
+ }
316
+ f , err := os .OpenFile ("statistics.html" , os .O_RDWR | os .O_CREATE , 0666 )
317
+ defer f .Close ()
318
+ err = t .Execute (f , data )
319
+ check (err )
320
+
231
321
return nil
232
322
}
233
323
@@ -286,23 +376,29 @@ func plotStats(s *SshdParser, v string) error {
286
376
p .NominalY (keys ... )
287
377
288
378
// Create folder to store plots
289
-
290
379
if _ , err := os .Stat ("data" ); os .IsNotExist (err ) {
291
380
err := os .Mkdir ("data" , 0700 )
292
381
if err != nil {
293
382
return err
294
383
}
295
384
}
296
385
297
- if _ , err := os .Stat (filepath .Join ("data" , stype [0 ])); os .IsNotExist (err ) {
298
- err := os .Mkdir (filepath .Join ("data" , stype [0 ]), 0700 )
386
+ if _ , err := os .Stat (filepath .Join ("data" , "sshd" )); os .IsNotExist (err ) {
387
+ err := os .Mkdir (filepath .Join ("data" , "sshd" ), 0700 )
388
+ if err != nil {
389
+ return err
390
+ }
391
+ }
392
+
393
+ if _ , err := os .Stat (filepath .Join ("data" , "sshd" , stype [0 ])); os .IsNotExist (err ) {
394
+ err := os .Mkdir (filepath .Join ("data" , "sshd" , stype [0 ]), 0700 )
299
395
if err != nil {
300
396
return err
301
397
}
302
398
}
303
399
304
400
xsize := 3 + vg .Length (math .Round (float64 (len (keys )/ 2 )))
305
- if err := p .Save (15 * vg .Centimeter , xsize * vg .Centimeter , filepath .Join ("data" , stype [0 ], fmt .Sprintf ("%v.svg" , v ))); err != nil {
401
+ if err := p .Save (15 * vg .Centimeter , xsize * vg .Centimeter , filepath .Join ("data" , "sshd" , stype [0 ], fmt .Sprintf ("%v.svg" , v ))); err != nil {
306
402
return err
307
403
}
308
404
0 commit comments