database.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package database
  2. import (
  3. "fmt"
  4. "strconv"
  5. "sync"
  6. "time"
  7. "github.com/crowdsecurity/crowdsec/pkg/types"
  8. log "github.com/sirupsen/logrus"
  9. "github.com/jinzhu/gorm"
  10. _ "github.com/jinzhu/gorm/dialects/mysql"
  11. _ "github.com/jinzhu/gorm/dialects/sqlite"
  12. _ "github.com/mattn/go-sqlite3"
  13. "gopkg.in/tomb.v2"
  14. )
  15. type Context struct {
  16. Db *gorm.DB //Pointer to database
  17. lastCommit time.Time
  18. flush bool
  19. count int32
  20. lock sync.Mutex //booboo
  21. PusherTomb tomb.Tomb
  22. //to manage auto cleanup : max number of records *or* oldest
  23. maxEventRetention int
  24. maxDurationRetention time.Duration
  25. }
  26. func checkConfig(cfg map[string]string) error {
  27. switch dbType, _ := cfg["type"]; dbType {
  28. case "sqlite":
  29. if val, ok := cfg["db_path"]; !ok || val == "" {
  30. return fmt.Errorf("please specify a 'db_path' to SQLite db in the configuration")
  31. }
  32. case "mysql":
  33. if val, ok := cfg["db_host"]; !ok || val == "" {
  34. return fmt.Errorf("please specify a 'db_host' to MySQL db in the configuration")
  35. }
  36. if val, ok := cfg["db_username"]; !ok || val == "" {
  37. return fmt.Errorf("please specify a 'db_username' to MySQL db in the configuration")
  38. }
  39. if val, ok := cfg["db_password"]; !ok || val == "" {
  40. return fmt.Errorf("please specify a 'db_password' to MySQL db in the configuration")
  41. }
  42. if val, ok := cfg["db_name"]; !ok || val == "" {
  43. return fmt.Errorf("please specify a 'db_name' to MySQL db in the configuration")
  44. }
  45. default:
  46. return fmt.Errorf("please specify a proper 'type' to the database configuration ")
  47. }
  48. return nil
  49. }
  50. func NewDatabase(cfg map[string]string) (*Context, error) {
  51. var err error
  52. c := &Context{}
  53. if err = checkConfig(cfg); err != nil {
  54. return nil, fmt.Errorf("bad database configuration : %v", err)
  55. }
  56. if cfg["type"] == "sqlite" {
  57. c.Db, err = gorm.Open("sqlite3", cfg["db_path"]+"?_busy_timeout=10000")
  58. if err != nil {
  59. return nil, fmt.Errorf("failed to open %s : %s", cfg["db_path"], err)
  60. }
  61. }
  62. if cfg["type"] == "mysql" {
  63. gormArg := cfg["db_username"] + ":" + cfg["db_password"] + "@(" + cfg["db_host"] + ")/" + cfg["db_name"] + "?charset=utf8&parseTime=True&loc=Local"
  64. c.Db, err = gorm.Open("mysql", gormArg)
  65. if err != nil {
  66. return nil, fmt.Errorf("failed to open %s database : %s", cfg["db_name"], err)
  67. }
  68. }
  69. if v, ok := cfg["max_records"]; ok {
  70. c.maxEventRetention, err = strconv.Atoi(v)
  71. if err != nil {
  72. log.Errorf("Ignoring invalid max_records '%s' : %s", v, err)
  73. }
  74. }
  75. if v, ok := cfg["max_records_age"]; ok {
  76. c.maxDurationRetention, err = time.ParseDuration(v)
  77. if err != nil {
  78. log.Errorf("Ignoring invalid duration '%s' : %s", v, err)
  79. }
  80. }
  81. if val, ok := cfg["debug"]; ok && val == "true" {
  82. log.Infof("Enabling debug for %s", cfg["type"])
  83. c.Db.LogMode(true)
  84. }
  85. c.flush, err = strconv.ParseBool(cfg["flush"])
  86. if err != nil {
  87. return nil, fmt.Errorf("failed to parse 'flush' value %s : %s", cfg["flush"], err)
  88. }
  89. // Migrate the schema
  90. c.Db.AutoMigrate(&types.EventSequence{}, &types.SignalOccurence{}, &types.BanApplication{})
  91. c.Db.Model(&types.SignalOccurence{}).Related(&types.EventSequence{})
  92. c.Db.Model(&types.SignalOccurence{}).Related(&types.BanApplication{})
  93. c.lastCommit = time.Now()
  94. return c, nil
  95. }