cmd

package
v5.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 22, 2025 License: GPL-3.0 Imports: 30 Imported by: 0

Documentation

Index

Constants

View Source
const RollingLogDaysToKeep = 15

for rolling datasets, limit the logs that are imported to the past 14 (to match the snapshot tables) + 1 (for good luck) days

Variables

View Source
var DeleteCommand = &cli.Command{
	Name:        "delete",
	Usage:       "delete a dataset",
	UsageText:   "delete [NAME]",
	Description: "if <dataset name> ends in a wildcard, all datasets with that prefix will be deleted",
	Args:        false,
	Flags: []cli.Flag{
		&cli.BoolFlag{
			Name:     "non-interactive",
			Aliases:  []string{"ni"},
			Usage:    "does not prompt for confirmation of deletion",
			Value:    false,
			Required: false,
		},
		ConfigFlag(false),
	},
	Action: func(cCtx *cli.Context) error {

		if cCtx.NArg() > 1 {
			return ErrTooManyArguments
		}

		if !cCtx.Args().Present() {
			return ErrMissingDatabaseName
		}

		input := cCtx.Args().First()

		trimmedName, err := TrimWildcards(input)
		if err != nil {
			return err
		}

		afs := afero.NewOsFs()

		if err := ValidateDatabaseName(trimmedName); err != nil {
			return err
		}

		prompt := true
		if cCtx.Bool("non-interactive") {
			prompt = false
		}

		cfg, err := config.ReadFileConfig(afs, cCtx.String("config"))
		if err != nil {
			return err
		}

		if err := RunDeleteCmd(cfg, input, trimmedName, prompt); err != nil {
			return err
		}

		if err := CheckForUpdate(cfg); err != nil {
			return err
		}

		return nil
	},
}
View Source
var ErrCheckingForUpdate = errors.New("error checking for newer version of RITA")
View Source
var ErrCurrentVersionEmpty = errors.New("current version unset")
View Source
var ErrDatabaseNotFound = errors.New("database not found")
View Source
var ErrIncompatibleFileExtension = errors.New("incompatible file extension")
View Source
var ErrInsufficientReadPermissions = errors.New("file does not have readable permission or does not exist")

util.Max(1, runtime.NumCPU()/2)

View Source
var ErrInvalidConfig = errors.New("encountered invalid configuration values")
View Source
var ErrInvalidConfigObject = errors.New("config was nil or invalid")
View Source
var ErrInvalidLogHourFormat = errors.New("could not parse hour from log file name - invalid format")
View Source
var ErrInvalidLogHourRange = errors.New("could not parse hour from log file name - hour out of range")
View Source
var ErrInvalidLogType = errors.New("incompatible log type")
View Source
var ErrInvalidViewLimit = errors.New("limit must be a positive interger greater than 0")
View Source
var ErrMissingConfigPath = errors.New("config path parameter is required")
View Source
var ErrMissingDatabaseName = errors.New("database name is required")
View Source
var ErrMissingLimitStdout = errors.New("cannot apply limit without --stdout")
View Source
var ErrMissingLogDirectory = errors.New("log directory flag is required")
View Source
var ErrMissingSearchStdout = errors.New("cannot apply search without --stdout")
View Source
var ErrMissingSearchValue = errors.New("search value cannot be empty")
View Source
var ErrNoValidFilesFound = errors.New("no valid log files found")
View Source
var ErrSkippedDuplicateLog = errors.New("encountered file with same name but different extension, skipping file due to older last modified time")
View Source
var ErrTooManyArguments = errors.New("too many arguments provided")
View Source
var ErrTrimmedNameEmpty = errors.New("trimmed name cannot contain wildcards or be empty")
View Source
var ImportCommand = &cli.Command{
	Name:      "import",
	Usage:     "import zeek logs into a target database",
	UsageText: "rita import [--database NAME] [-logs DIRECTORY] [--rolling] [--rebuild]",
	Flags: []cli.Flag{
		&cli.StringFlag{
			Name:     "database",
			Aliases:  []string{"d"},
			Usage:    "target database; database name should start with a lowercase letter, should contain only alphanumeric and underscores, and not end with an underscore",
			Required: true,
			Action: func(_ *cli.Context, name string) error {
				return ValidateDatabaseName(name)
			},
		},
		&cli.StringFlag{
			Name:     "logs",
			Aliases:  []string{"l"},
			Usage:    "path to log directory",
			Required: false,
			Action: func(_ *cli.Context, path string) error {
				return ValidateLogDirectory(afero.NewOsFs(), path)
			},
		},
		&cli.BoolFlag{
			Name:     "rolling",
			Aliases:  []string{"r"},
			Usage:    "indicates rolling import, which builds on and removes data to maintain a fixed length of time",
			Value:    false,
			Required: false,
		},
		&cli.BoolFlag{
			Name:     "rebuild",
			Aliases:  []string{"x"},
			Usage:    "destroys existing database and imports given files",
			Value:    false,
			Required: false,
		},
		ConfigFlag(false),
	},
	Action: func(cCtx *cli.Context) error {
		afs := afero.NewOsFs()

		cfg, err := config.ReadFileConfig(afs, cCtx.String("config"))
		if err != nil {
			return err
		}

		startTime := time.Now()

		_, err = RunImportCmd(startTime, cfg, afs, cCtx.String("logs"), cCtx.String("database"), cCtx.Bool("rolling"), cCtx.Bool("rebuild"))
		if err != nil {
			return err
		}

		if err := CheckForUpdate(cfg); err != nil {
			return err
		}

		return nil
	},
}
View Source
var ListCommand = &cli.Command{
	Name:        "list",
	Usage:       "list available datasets",
	UsageText:   "list",
	Description: "lists available datasets",
	Args:        false,
	Flags: []cli.Flag{
		ConfigFlag(false),
	},
	Action: func(cCtx *cli.Context) error {

		if cCtx.NArg() > 0 {
			return ErrTooManyArguments
		}

		afs := afero.NewOsFs()

		cfg, err := config.ReadFileConfig(afs, cCtx.String("config"))
		if err != nil {
			return err
		}

		if err := runListCmd(cfg); err != nil {
			return err
		}

		if err := CheckForUpdate(cfg); err != nil {
			return err
		}

		return nil
	},
}
View Source
var ValidateConfigCommand = &cli.Command{
	Name:      "validate",
	Usage:     "validate a configuration file",
	UsageText: "validate [--config FILE]",
	Args:      false,
	Flags: []cli.Flag{
		ConfigFlag(false),
	},
	Action: func(cCtx *cli.Context) error {

		if cCtx.String("config") == "" {
			return ErrMissingConfigPath
		}

		if cCtx.NArg() > 0 {
			return ErrTooManyArguments
		}

		afs := afero.NewOsFs()

		cfg, err := RunValidateConfigCommand(afs, cCtx.String("config"))
		if err != nil {
			fmt.Printf("\n\t[!] Configuration file is not valid...")
			return err
		}

		if err := CheckForUpdate(cfg); err != nil {
			return err
		}

		return nil
	},
}
View Source
var ViewCommand = &cli.Command{
	Name:  "view",
	Usage: "view <dataset name>",
	Flags: []cli.Flag{
		&cli.BoolFlag{
			Name:     "stdout",
			Aliases:  []string{"o"},
			Usage:    "pipe comma-delimited data to stdout",
			Required: false,
		},
		&cli.StringFlag{
			Name:     "search",
			Aliases:  []string{"s"},
			Usage:    `search criteria to apply to results piped to stdout, only works with --stdout/-o flag, format: -s="field:value, field:value, ..."`,
			Required: false,
		},
		&cli.IntFlag{
			Name:     "limit",
			Aliases:  []string{"l"},
			Usage:    "limit the number of results to display",
			Required: false,
		},
		ConfigFlag(false),
	},
	Action: func(cCtx *cli.Context) error {

		if !cCtx.Args().Present() {
			return ErrMissingDatabaseName
		}

		if err := ValidateDatabaseName(cCtx.Args().First()); err != nil {
			return err
		}

		if cCtx.IsSet("search") {
			if !cCtx.Bool("stdout") {
				return ErrMissingSearchStdout
			}

			if cCtx.String("search") == "" {
				return ErrMissingSearchValue
			}
		}

		if cCtx.IsSet("limit") {
			if !cCtx.Bool("stdout") {
				return ErrMissingLimitStdout
			}

			if cCtx.Int("limit") <= 0 {
				return ErrInvalidViewLimit
			}
		}

		afs := afero.NewOsFs()

		cfg, err := config.ReadFileConfig(afs, cCtx.String("config"))
		if err != nil {
			return err
		}

		if err := runViewCmd(cfg, cCtx.Args().First(), cCtx.Bool("stdout"), cCtx.String("search"), cCtx.Int("limit")); err != nil {
			return err
		}

		if err := CheckForUpdate(cfg); err != nil {
			return err
		}

		return nil
	},
}
View Source
var ZoneTransferCommand = &cli.Command{
	Name:        "zone-transfer",
	Usage:       "perform a zone transfer on the configured domain",
	UsageText:   "zone-transfer",
	Description: "performs a zone transfer on the configured domain",
	Args:        false,
	Flags: []cli.Flag{
		ConfigFlag(false),
	},
	Action: func(cCtx *cli.Context) error {

		if cCtx.NArg() > 0 {
			return ErrTooManyArguments
		}

		afs := afero.NewOsFs()

		cfg, err := config.ReadFileConfig(afs, cCtx.String("config"))
		if err != nil {
			return err
		}

		if err := runZoneTransferCmd(cfg); err != nil {
			return err
		}

		if err := CheckForUpdate(cfg); err != nil {
			return err
		}

		return nil
	},
}

Functions

func CheckForUpdate

func CheckForUpdate(cfg *config.Config) error

func Commands

func Commands() []*cli.Command

func ConfigFlag

func ConfigFlag(required bool) *cli.StringFlag

func FormatListTable

func FormatListTable(dbs []database.ImportDatabase) *table.Table

func ParseFolderDate added in v5.0.5

func ParseFolderDate(folder string) (time.Time, error)

ParseFolderDate extracts the date from a given folder name

func ParseHourFromFilename

func ParseHourFromFilename(filename string) (int, error)

ParseHourFromFilename extracts the hour from a given filename

func RunDeleteCmd added in v5.0.5

func RunDeleteCmd(cfg *config.Config, entry string, trimmedName string, ask bool) error

func RunValidateConfigCommand

func RunValidateConfigCommand(afs afero.Fs, configPath string) (*config.Config, error)

func TrimWildcards

func TrimWildcards(dbName string) (string, error)

TrimWildcards removes leading and trailing wildcards from a database name

func ValidateConfigPath

func ValidateConfigPath(afs afero.Fs, configPath string) error

func ValidateDatabaseName

func ValidateDatabaseName(name string) error

func ValidateLogDirectory

func ValidateLogDirectory(afs afero.Fs, logDir string) error

func WalkFiles

func WalkFiles(afs afero.Fs, root string, rolling bool) ([]HourlyZeekLogs, []WalkError, error)

WalkFiles starts a goroutine to walk the directory tree at root and send the path of each regular file on the string channel. It sends the result of the walk on the error channel. If done is closed, WalkFiles abandons its work.

Types

type HourlyZeekLogs

type HourlyZeekLogs []map[string][]string

func GatherDailyLogs added in v5.1.0

func GatherDailyLogs(logMap map[time.Time]HourlyZeekLogs, days []time.Time, rolling bool) []HourlyZeekLogs

type ImportResults

type ImportResults struct {
	i.ResultCounts
	ImportID         []util.FixedString
	ImportTimestamps []ImportTimestamps
}

func RunImportCmd

func RunImportCmd(startTime time.Time, cfg *config.Config, afs afero.Fs, logDir string, dbName string, rolling bool, rebuild bool) (ImportResults, error)

type ImportTimestamps

type ImportTimestamps struct {
	MinTS       time.Time
	MaxTS       time.Time
	MinTSBeacon time.Time
	// contains filtered or unexported fields
}

type WalkError

type WalkError struct {
	Path  string
	Error error
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL