database.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package database
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "time"
  7. "github.com/crowdsecurity/crowdsec/pkg/csconfig"
  8. "github.com/crowdsecurity/crowdsec/pkg/database/ent"
  9. "github.com/crowdsecurity/crowdsec/pkg/types"
  10. "github.com/go-co-op/gocron"
  11. _ "github.com/go-sql-driver/mysql"
  12. _ "github.com/lib/pq"
  13. _ "github.com/mattn/go-sqlite3"
  14. "github.com/pkg/errors"
  15. log "github.com/sirupsen/logrus"
  16. )
  17. type Client struct {
  18. Ent *ent.Client
  19. CTX context.Context
  20. Log *log.Logger
  21. }
  22. func NewClient(config *csconfig.DatabaseCfg) (*Client, error) {
  23. var client *ent.Client
  24. var err error
  25. if config == nil {
  26. return &Client{}, fmt.Errorf("DB config is empty")
  27. }
  28. switch config.Type {
  29. case "sqlite":
  30. /*if it's the first startup, we want to touch and chmod file*/
  31. if _, err := os.Stat(config.DbPath); os.IsNotExist(err) {
  32. f, err := os.OpenFile(config.DbPath, os.O_CREATE|os.O_RDWR, 0600)
  33. if err != nil {
  34. return &Client{}, errors.Wrapf(err, "failed to create SQLite database file %q", config.DbPath)
  35. }
  36. if err := f.Close(); err != nil {
  37. return &Client{}, errors.Wrapf(err, "failed to create SQLite database file %q", config.DbPath)
  38. }
  39. } else { /*ensure file perms*/
  40. if err := os.Chmod(config.DbPath, 0600); err != nil {
  41. return &Client{}, fmt.Errorf("unable to set perms on %s: %v", config.DbPath, err)
  42. }
  43. }
  44. client, err = ent.Open("sqlite3", fmt.Sprintf("file:%s?_busy_timeout=100000&_fk=1", config.DbPath))
  45. if err != nil {
  46. return &Client{}, fmt.Errorf("failed opening connection to sqlite: %v", err)
  47. }
  48. case "mysql":
  49. client, err = ent.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?parseTime=True", config.User, config.Password, config.Host, config.Port, config.DbName))
  50. if err != nil {
  51. return &Client{}, fmt.Errorf("failed opening connection to mysql: %v", err)
  52. }
  53. case "postgres", "postgresql":
  54. client, err = ent.Open("postgres", fmt.Sprintf("host=%s port=%d user=%s dbname=%s password=%s", config.Host, config.Port, config.User, config.DbName, config.Password))
  55. if err != nil {
  56. return &Client{}, fmt.Errorf("failed opening connection to postgres: %v", err)
  57. }
  58. default:
  59. return &Client{}, fmt.Errorf("unknown database type")
  60. }
  61. /*The logger that will be used by db operations*/
  62. clog := log.New()
  63. if err := types.ConfigureLogger(clog); err != nil {
  64. return nil, errors.Wrap(err, "while configuring db logger")
  65. }
  66. if config.LogLevel != nil {
  67. clog.SetLevel(*config.LogLevel)
  68. if *config.LogLevel >= log.TraceLevel {
  69. log.Debugf("Enabling request debug")
  70. client = client.Debug()
  71. }
  72. }
  73. if err = client.Schema.Create(context.Background()); err != nil {
  74. return nil, fmt.Errorf("failed creating schema resources: %v", err)
  75. }
  76. return &Client{Ent: client, CTX: context.Background(), Log: clog}, nil
  77. }
  78. func (c *Client) StartFlushScheduler(config *csconfig.FlushDBCfg) (*gocron.Scheduler, error) {
  79. maxItems := 0
  80. maxAge := ""
  81. if config.MaxItems != nil && *config.MaxItems <= 0 {
  82. return nil, fmt.Errorf("max_items can't be zero or negative number")
  83. }
  84. if config.MaxItems != nil {
  85. maxItems = *config.MaxItems
  86. }
  87. if config.MaxAge != nil && *config.MaxAge != "" {
  88. maxAge = *config.MaxAge
  89. }
  90. // Init & Start cronjob every minute
  91. scheduler := gocron.NewScheduler(time.UTC)
  92. scheduler.Every(1).Minute().Do(c.FlushAlerts, maxAge, maxItems)
  93. scheduler.StartAsync()
  94. return scheduler, nil
  95. }