package database import ( "fmt" "time" "github.com/crowdsecurity/crowdsec/pkg/types" "github.com/jinzhu/gorm" log "github.com/sirupsen/logrus" ) //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*/ records := c.Db.Order("updated_at desc").Where("until >= ?", 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 until >= ? AND deleted_at is NULL`, ba.IpText, 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"] = time.Until(ba.Until).Round(time.Second).String() 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"] = time.Until(ba.Until).Round(time.Second).String() 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"] = time.Until(ba.Until).Round(time.Second).String() bancom["reason"] = so.Scenario rets = append(rets, bancom) } return rets, nil } func (c *Context) GetNewBan() ([]types.BanApplication, error) { var bas []types.BanApplication //select the news bans banRecords := c.Db. Order("updated_at desc"). /*Get non expired (until) bans*/ Where(`until >= ?`, time.Now()). /*Only get one ban per unique ip_text*/ Group("ip_text"). Find(&bas) if banRecords.Error != nil { return nil, fmt.Errorf("failed when selection bans : %v", banRecords.Error) } return bas, nil } func (c *Context) GetNewBanSince(since time.Time) ([]types.BanApplication, error) { var bas []types.BanApplication //select the news bans banRecords := c.Db. Order("updated_at desc"). /*Get non expired (until) bans*/ Where(`until >= ?`, time.Now()). /*That were added since last tick*/ Where(`updated_at >= ?`, since). /*Only get one ban per unique ip_text*/ Group("ip_text"). Find(&bas) /*.Count(&count)*/ if banRecords.Error != nil { return nil, fmt.Errorf("failed when selection bans : %v", banRecords.Error) } return bas, nil } func (c *Context) GetDeletedBanSince(since time.Time) ([]types.BanApplication, error) { var bas []types.BanApplication deletedRecords := c.Db. /*ignore the soft delete*/ Unscoped(). Order("updated_at desc"). /*ban that were deleted since since or bans that expired since since*/ Where(`deleted_at >= ? OR (until >= ? AND until <= ?)`, since.Add(1*time.Second), since.Add(1*time.Second), time.Now()). /*Only get one ban per unique ip_text*/ Group("ip_text"). Find(&bas) /*.Count(&count)*/ if deletedRecords.Error != nil { return nil, fmt.Errorf("failed when selection deleted bans : %v", deletedRecords.Error) } return bas, nil }