package sqlite import ( "fmt" "strconv" "time" "github.com/crowdsecurity/crowdsec/pkg/types" "github.com/jinzhu/gorm" log "github.com/sirupsen/logrus" ) func (c *Context) GetStats(since time.Duration) ([]map[string]string, error) { sos := []types.SignalOccurence{} stats := make([]map[string]string, 0) as_stats := make(map[string]string) scenar_stats := make(map[string]string) country_stats := make(map[string]string) /*get records that are younger than 'since' */ records := c.Db.Order("updated_at desc").Where(`strftime("%s", created_at) >= strftime("%s", ?)`, time.Now().Add(-since)).Find(&sos) if records.Error != nil { return nil, records.Error } for _, ld := range sos { /*by scenario*/ if ld.Scenario == "" { ld.Scenario = "unknown" } if _, ok := scenar_stats[ld.Scenario]; !ok { scenar_stats[ld.Scenario] = "1" } else { nv, err := strconv.Atoi(scenar_stats[ld.Scenario]) if err != nil { log.Fatalf("Unable to update internal stats : %v", err) } scenar_stats[ld.Scenario] = fmt.Sprintf("%d", nv+1) } /*by country*/ if ld.Source_Country == "" { ld.Source_Country = "unknown" } if _, ok := country_stats[ld.Source_Country]; !ok { country_stats[ld.Source_Country] = "1" } else { nv, err := strconv.Atoi(country_stats[ld.Source_Country]) if err != nil { log.Fatalf("Unable to update internal stats : %v", err) } country_stats[ld.Source_Country] = fmt.Sprintf("%d", nv+1) } /*by AS*/ if ld.Source_AutonomousSystemNumber == "" { ld.Source_AutonomousSystemNumber = "unknown" } if _, ok := as_stats[ld.Source_AutonomousSystemNumber]; !ok { as_stats[ld.Source_AutonomousSystemNumber] = "1" } else { nv, err := strconv.Atoi(as_stats[ld.Source_AutonomousSystemNumber]) if err != nil { log.Fatalf("Unable to update internal stats : %v", err) } as_stats[ld.Source_AutonomousSystemNumber] = fmt.Sprintf("%d", nv+1) } } stats = append(stats, as_stats) stats = append(stats, scenar_stats) stats = append(stats, country_stats) return stats, nil } //GetBansAt returns the IPs that were banned at a given time func (c *Context) GetBansAt(at time.Time) ([]map[string]string, error) { bas := []types.BanApplication{} rets := make([]map[string]string, 0) /*get non-expired records*/ //c.Db.LogMode(true) records := c.Db.Order("updated_at desc").Where(`strftime("%s", until) >= strftime("%s", ?) AND strftime("%s", created_at) < strftime("%s", ?)`, at, at).Group("ip_text").Find(&bas) /*.Count(&count)*/ if records.Error != nil { return nil, records.Error } for _, ba := range bas { var count int /* fetch count of bans for this specific ip_text */ ret := c.Db.Table("ban_applications").Order("updated_at desc").Where(`ip_text = ? AND strftime("%s", until) >= strftime("%s", ?) AND strftime("%s", created_at) < strftime("%s", ?) AND deleted_at is NULL`, ba.IpText, at, at).Count(&count) if ret.Error != nil { return nil, fmt.Errorf("Failed to fetch records count for %s : %v", ba.IpText, ret.Error) } sOs := []types.SignalOccurence{} nbSo := 0 records := c.Db.Where(`source_ip = ?`, ba.IpText).Group("id").Find(&sOs).Count(&nbSo) if records.Error != nil { //record not found can be ok if gorm.IsRecordNotFoundError(records.Error) { bancom := make(map[string]string) bancom["iptext"] = ba.IpText bancom["bancount"] = fmt.Sprintf("%d", count) bancom["as"] = ba.TargetASName bancom["asnum"] = fmt.Sprintf("%d", ba.TargetAS) bancom["cn"] = ba.TargetCN bancom["scenario"] = "?" bancom["source"] = ba.MeasureSource bancom["events_count"] = "0" bancom["action"] = ba.MeasureType bancom["until"] = fmt.Sprintf("%s", ba.Until.Sub(time.Now()).Round(time.Second)) bancom["reason"] = ba.Reason rets = append(rets, bancom) continue } } evtCount := 0 for _, s := range sOs { evtCount += s.Events_count } so := types.SignalOccurence{} records = c.Db.Where(`id = ?`, ba.SignalOccurenceID).Find(&so) if records.Error != nil { //record not found can be ok if gorm.IsRecordNotFoundError(records.Error) { bancom := make(map[string]string) bancom["iptext"] = ba.IpText bancom["bancount"] = fmt.Sprintf("%d", count) bancom["as"] = ba.TargetASName bancom["asnum"] = fmt.Sprintf("%d", ba.TargetAS) bancom["cn"] = ba.TargetCN bancom["source"] = ba.MeasureSource bancom["scenario"] = "?" bancom["events_count"] = "0" bancom["action"] = ba.MeasureType bancom["until"] = fmt.Sprintf("%s", ba.Until.Sub(time.Now()).Round(time.Second)) bancom["reason"] = ba.Reason rets = append(rets, bancom) continue } fmt.Printf("err : %v", records.Error) return nil, records.Error } if records.RowsAffected != 1 { log.Errorf("more than one signal_occurence for local_decision, discard") break } bancom := make(map[string]string) bancom["iptext"] = ba.IpText bancom["as"] = so.Source_AutonomousSystemNumber + " " + so.Source_AutonomousSystemOrganization bancom["cn"] = so.Source_Country bancom["bancount"] = fmt.Sprintf("%d", nbSo) bancom["scenario"] = so.Scenario bancom["events_count"] = fmt.Sprintf("%d", evtCount) bancom["action"] = ba.MeasureType bancom["source"] = ba.MeasureSource bancom["until"] = fmt.Sprintf("%s", ba.Until.Sub(time.Now()).Round(time.Second)) bancom["reason"] = so.Scenario rets = append(rets, bancom) } return rets, nil }