diff --git a/go.mod b/go.mod index 2802a369b..ff2f3415b 100644 --- a/go.mod +++ b/go.mod @@ -40,6 +40,7 @@ require ( github.com/hashicorp/go-version v1.6.0 github.com/libp2p/go-netroute v0.2.0 github.com/magiconair/properties v1.8.5 + github.com/mattn/go-sqlite3 v1.14.16 github.com/miekg/dns v1.1.41 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/prometheus/client_golang v1.13.0 diff --git a/go.sum b/go.sum index 707d7c808..65e1cdfc3 100644 --- a/go.sum +++ b/go.sum @@ -432,6 +432,8 @@ github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcME github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43/go.mod h1:+t7E0lkKfbBsebllff1xdTmyJt8lH37niI6kwFk9OTo= diff --git a/management/server/audit/event.go b/management/server/audit/event.go new file mode 100644 index 000000000..4599fc425 --- /dev/null +++ b/management/server/audit/event.go @@ -0,0 +1,32 @@ +package audit + +import "time" + +const ( + // DeviceEvent describes an event that happened of a device (e.g, connected/disconnected) + DeviceEvent EventType = "device" + // ManagementEvent describes an event that happened on a Management service (e.g., user added) + ManagementEvent EventType = "management" +) + +type EventType string + +// EventSink provides an interface to store or stream events. +type EventSink interface { + // Add an event to the sink. + Add(event *Event) error + // Close the sink flushing events if necessary + Close() error +} + +// Event represents a network activity. +type Event struct { + // Timestamp of the event + Timestamp time.Time + // Message of the event + Message string + // ID of the event (can be empty, meaning that it wasn't yet generated) + ID string + // Type of the event + Type EventType +} diff --git a/management/server/audit/sqlite.go b/management/server/audit/sqlite.go new file mode 100644 index 000000000..a59c642de --- /dev/null +++ b/management/server/audit/sqlite.go @@ -0,0 +1,66 @@ +package audit + +import ( + "database/sql" + "fmt" + _ "github.com/mattn/go-sqlite3" +) + +const ( + SQLiteEventSinkDB = "events.db" + createTableQuery = "CREATE TABLE IF NOT EXISTS events " + + "(id UNSIGNED BIG INT PRIMARY KEY AUTOINCREMENT, message TEXT, timestamp DATETIME);" +) + +type SQLiteSink struct { + db *sql.DB +} + +// NewSQLiteSink creates a new SQLiteSink with an event table if not exists. +func NewSQLiteSink(dbPath string) (*SQLiteSink, error) { + db, err := sql.Open("sqlite3", dbPath) + if err != nil { + return nil, err + } + + _, err = db.Exec(createTableQuery) + if err != nil { + return nil, err + } + + return &SQLiteSink{db: db}, nil +} + +// Add an event to the SQLite table +func (sink *SQLiteSink) Add(event *Event) error { + + _, err := sink.db.Exec(createTableQuery) + if err != nil { + return err + } + + stmt, err := sink.db.Prepare("INSERT INTO events(message, timestamp) values(?, ?)") + if err != nil { + return err + } + + result, err := stmt.Exec(event.Message, event.Timestamp) + if err != nil { + if err == sql.ErrNoRows { + // Handle the case of no rows returned. + } + return album, err + } + + fmt.Println(result) + + return nil +} + +// Close the SQLiteSink +func (sink *SQLiteSink) Close() error { + if sink.db != nil { + return sink.db.Close() + } + return nil +}