Files
arc-evilsocket/cmd/arc/setup.go
2024-04-06 17:19:48 -04:00

223 lines
5.8 KiB
Go

package main
import (
"flag"
"net/http"
"os"
"strings"
"time"
assetfs "github.com/elazarl/go-bindata-assetfs"
"github.com/evilsocket/arc/backup"
"github.com/evilsocket/arc/config"
"github.com/evilsocket/arc/controllers"
"github.com/evilsocket/arc/db"
"github.com/evilsocket/arc/events"
"github.com/evilsocket/arc/middlewares"
"github.com/evilsocket/arc/scheduler"
"github.com/evilsocket/arc/tls"
"github.com/evilsocket/arc/updater"
"github.com/evilsocket/arc/utils"
"github.com/evilsocket/arc/webui"
"github.com/evilsocket/islazy/log"
"github.com/evilsocket/islazy/tui"
"github.com/gin-gonic/contrib/static"
"github.com/gin-gonic/gin"
)
var (
signals = make(chan os.Signal, 1)
confFile = ""
debug = false
logfile = ""
noColors = false
noAuth = false
noUpdates = false
export = false
importFrom = ""
output = "arc.tar"
dbIsNew = false
tlsFingerprint = ""
router = (*gin.Engine)(nil)
)
func init() {
flag.StringVar(&confFile, "config", "/etc/arc/config.toml", "Configuration file.")
flag.BoolVar(&noAuth, "no-auth", noAuth, "Disable authentication.")
flag.BoolVar(&noUpdates, "no-updates", noUpdates, "Disable updates check.")
flag.BoolVar(&debug, "debug", debug, "Enable debug logs.")
flag.StringVar(&logfile, "log", logfile, "Log messages to this file instead of standard error.")
flag.StringVar(&importFrom, "import", importFrom, "Import stores from this TAR export file.")
flag.BoolVar(&export, "export", export, "Export store to a TAR archive, requires --output parameter.")
flag.StringVar(&output, "output", output, "Export file name.")
}
func setupLogging() {
if logfile != "" {
log.Output = logfile
}
if debug {
log.Level = log.DEBUG
} else {
log.Level = log.INFO
}
log.DateFormat = "06-Jan-02"
log.TimeFormat = "15:04:05"
log.DateTimeFormat = "2006-01-02 15:04:05"
log.Format = "{datetime} {level:color}{level:name}{reset} {message}"
if err := log.Open(); err != nil {
panic(err)
}
}
func setupDatabase() {
var err error
if dbIsNew, err = db.Setup(); err != nil {
log.Fatal("%v", err)
}
if export {
started := time.Now()
if err = db.Export(output); err != nil {
log.Fatal("%v", err)
}
log.Info("Archived %s of data in %s to %s.", utils.FormatBytes(db.Size), time.Since(started), tui.Bold(output))
os.Exit(0)
} else if importFrom != "" {
started := time.Now()
if err = db.Import(importFrom); err != nil {
log.Fatal("%v", err)
}
log.Info("Imported %s of data in %s.", utils.FormatBytes(db.Size), time.Since(started))
os.Exit(0)
}
}
func setupScheduler() {
if config.Conf.Scheduler.Enabled {
if err := events.Setup(); err != nil {
log.Fatal("%v", err)
}
log.Debug("Starting scheduler with a period of %ds ...", config.Conf.Scheduler.Period)
scheduler.Start(config.Conf.Scheduler.Period)
} else {
log.Warning("Scheduler is disabled.")
}
}
func setupBackups() {
if config.Conf.Backups.Enabled {
log.Debug("Starting backup task with a period of %ds ...", config.Conf.Backups.Period)
backup.Start(config.Conf.Backups.Period, config.Conf.Backups.Folder, config.Conf.Backups.Run)
} else {
log.Warning("Backups are disabled.")
}
}
func setupUpdates() {
if !noUpdates {
updater.Start(config.APP_VERSION)
}
}
func setupTLS() {
var err error
if config.Conf.Certificate, err = utils.ExpandPath(config.Conf.Certificate); err != nil {
log.Fatal("%v", err)
} else if config.Conf.Key, err = utils.ExpandPath(config.Conf.Key); err != nil {
log.Fatal("%v", err)
}
if !utils.Exists(config.Conf.Certificate) || !utils.Exists(config.Conf.Key) {
log.Warning("TLS certificate files not found, generating new ones ...")
if err = tls.Generate(&config.Conf); err != nil {
log.Fatal("%v", err)
}
log.Info("New RSA key and certificate have been generated, remember to add them as exceptions to your browser!")
}
tlsFingerprint, err = tls.Fingerprint(config.Conf.Certificate)
if err != nil {
log.Fatal("%v", err)
}
log.Warning("TLS certificate fingerprint is %s", tui.Bold(tlsFingerprint))
}
type binaryFileSystem struct {
fs http.FileSystem
}
func (b *binaryFileSystem) Open(name string) (http.File, error) {
return b.fs.Open(name)
}
func (b *binaryFileSystem) Exists(prefix string, filepath string) bool {
if p := strings.TrimPrefix(filepath, prefix); len(p) < len(filepath) {
if _, err := b.fs.Open(p); err != nil {
return false
}
return true
}
return false
}
func BinaryFileSystem(root string) *binaryFileSystem {
fs := &assetfs.AssetFS{
Asset: webui.Asset,
AssetDir: webui.AssetDir,
Prefix: root}
return &binaryFileSystem{
fs,
}
}
func setupRouter() *gin.Engine {
gin.SetMode(gin.ReleaseMode)
router = gin.New()
router.Use(middlewares.Security(tlsFingerprint))
router.Use(static.Serve("/", BinaryFileSystem("webui")))
// router.Use(middlewares.ServeStatic("/", webapp.Path, webapp.Manifest.Index))
api := router.Group("/api")
router.POST("/auth", controllers.Auth)
if !noAuth {
api.Use(middlewares.AuthHandler())
} else {
log.Warning("API authentication is disabled.")
}
api.GET("/status", controllers.GetStatus)
api.GET("/config", controllers.GetConfig)
api.GET("/events/clear", controllers.ClearEvents)
api.GET("/stores", controllers.ListStores)
api.POST("/stores", controllers.CreateStore)
api.GET("/store/:id", controllers.GetStore)
api.PUT("/store/:id", controllers.UpdateStore)
api.DELETE("/store/:id", controllers.DeleteStore)
api.GET("/store/:id/records", controllers.ListRecords)
api.POST("/store/:id/records", controllers.CreateRecord)
api.GET("/store/:id/record/:r_id", controllers.GetRecord)
api.GET("/store/:id/record/:r_id/buffer", controllers.GetRecordBuffer)
api.PUT("/store/:id/record/:r_id", controllers.UpdateRecord)
api.DELETE("/store/:id/record/:r_id", controllers.DeleteRecord)
return router
}