bitbucket.org/Aishee/synsec@v0.0.0-20210414005726-236fc01a153d/cmd/synsec/main.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"os"
     7  	"strings"
     8  
     9  	_ "net/http/pprof"
    10  	"time"
    11  
    12  	"sort"
    13  
    14  	"bitbucket.org/Aishee/synsec/pkg/acquisition"
    15  	"bitbucket.org/Aishee/synsec/pkg/csconfig"
    16  	"bitbucket.org/Aishee/synsec/pkg/cwhub"
    17  	"bitbucket.org/Aishee/synsec/pkg/cwversion"
    18  	leaky "bitbucket.org/Aishee/synsec/pkg/leakybucket"
    19  	"bitbucket.org/Aishee/synsec/pkg/parser"
    20  	"bitbucket.org/Aishee/synsec/pkg/types"
    21  
    22  	log "github.com/sirupsen/logrus"
    23  
    24  	"gopkg.in/tomb.v2"
    25  )
    26  
    27  var (
    28  	/*tombs for the parser, buckets and outputs.*/
    29  	acquisTomb   tomb.Tomb
    30  	parsersTomb  tomb.Tomb
    31  	bucketsTomb  tomb.Tomb
    32  	outputsTomb  tomb.Tomb
    33  	apiTomb      tomb.Tomb
    34  	synsecTomb tomb.Tomb
    35  
    36  	flags *Flags
    37  
    38  	/*the state of acquisition*/
    39  	dataSources []acquisition.DataSource
    40  	/*the state of the buckets*/
    41  	holders         []leaky.BucketFactory
    42  	buckets         *leaky.Buckets
    43  	outputEventChan chan types.Event //the buckets init returns its own chan that is used for multiplexing
    44  	/*settings*/
    45  	lastProcessedItem time.Time /*keep track of last item timestamp in time-machine. it is used to GC buckets when we dump them.*/
    46  )
    47  
    48  type Flags struct {
    49  	ConfigFile             string
    50  	TraceLevel             bool
    51  	DebugLevel             bool
    52  	InfoLevel              bool
    53  	PrintVersion           bool
    54  	SingleFilePath         string
    55  	SingleJournalctlFilter string
    56  	SingleFileType         string
    57  	SingleFileJsonOutput   string
    58  	TestMode               bool
    59  	DisableAgent           bool
    60  	DisableAPI             bool
    61  }
    62  
    63  type parsers struct {
    64  	ctx             *parser.UnixParserCtx
    65  	povfwctx        *parser.UnixParserCtx
    66  	stageFiles      []parser.Stagefile
    67  	povfwStageFiles []parser.Stagefile
    68  	nodes           []parser.Node
    69  	povfwnodes      []parser.Node
    70  	enricherCtx     []parser.EnricherCtx
    71  }
    72  
    73  // Return new parsers
    74  // nodes and povfwnodes are already initialized in parser.LoadStages
    75  func newParsers() *parser.Parsers {
    76  	parsers := &parser.Parsers{
    77  		Ctx:             &parser.UnixParserCtx{},
    78  		Povfwctx:        &parser.UnixParserCtx{},
    79  		StageFiles:      make([]parser.Stagefile, 0),
    80  		PovfwStageFiles: make([]parser.Stagefile, 0),
    81  	}
    82  	for _, itemType := range []string{cwhub.PARSERS, cwhub.PARSERS_OVFLW} {
    83  		for _, hubParserItem := range cwhub.GetItemMap(itemType) {
    84  			if hubParserItem.Installed {
    85  				stagefile := parser.Stagefile{
    86  					Filename: hubParserItem.LocalPath,
    87  					Stage:    hubParserItem.Stage,
    88  				}
    89  				if itemType == cwhub.PARSERS {
    90  					parsers.StageFiles = append(parsers.StageFiles, stagefile)
    91  				}
    92  				if itemType == cwhub.PARSERS_OVFLW {
    93  					parsers.PovfwStageFiles = append(parsers.PovfwStageFiles, stagefile)
    94  				}
    95  			}
    96  		}
    97  	}
    98  	if parsers.StageFiles != nil {
    99  		sort.Slice(parsers.StageFiles, func(i, j int) bool {
   100  			return parsers.StageFiles[i].Filename < parsers.StageFiles[j].Filename
   101  		})
   102  	}
   103  	if parsers.PovfwStageFiles != nil {
   104  		sort.Slice(parsers.PovfwStageFiles, func(i, j int) bool {
   105  			return parsers.PovfwStageFiles[i].Filename < parsers.PovfwStageFiles[j].Filename
   106  		})
   107  	}
   108  
   109  	return parsers
   110  }
   111  
   112  func LoadBuckets(cConfig *csconfig.Config) error {
   113  
   114  	var (
   115  		err   error
   116  		files []string
   117  	)
   118  	for _, hubScenarioItem := range cwhub.GetItemMap(cwhub.SCENARIOS) {
   119  		if hubScenarioItem.Installed {
   120  			files = append(files, hubScenarioItem.LocalPath)
   121  		}
   122  	}
   123  	buckets = leaky.NewBuckets()
   124  
   125  	log.Infof("Loading %d scenario files", len(files))
   126  	holders, outputEventChan, err = leaky.LoadBuckets(cConfig.Synsec, files, &bucketsTomb, buckets)
   127  
   128  	if err != nil {
   129  		return fmt.Errorf("Scenario loading failed : %v", err)
   130  	}
   131  
   132  	if cConfig.Prometheus != nil && cConfig.Prometheus.Enabled {
   133  		for holderIndex := range holders {
   134  			holders[holderIndex].Profiling = true
   135  		}
   136  	}
   137  	return nil
   138  }
   139  
   140  func LoadAcquisition(cConfig *csconfig.Config) error {
   141  	var err error
   142  
   143  	if flags.SingleFilePath != "" || flags.SingleJournalctlFilter != "" {
   144  
   145  		tmpCfg := acquisition.DataSourceCfg{}
   146  		tmpCfg.Mode = acquisition.CAT_MODE
   147  		tmpCfg.Labels = map[string]string{"type": flags.SingleFileType}
   148  
   149  		if flags.SingleFilePath != "" {
   150  			tmpCfg.Filename = flags.SingleFilePath
   151  		} else if flags.SingleJournalctlFilter != "" {
   152  			tmpCfg.JournalctlFilters = strings.Split(flags.SingleJournalctlFilter, " ")
   153  		}
   154  
   155  		datasrc, err := acquisition.DataSourceConfigure(tmpCfg)
   156  		if err != nil {
   157  			return fmt.Errorf("while configuring specified file datasource : %s", err)
   158  		}
   159  		if dataSources == nil {
   160  			dataSources = make([]acquisition.DataSource, 0)
   161  		}
   162  		dataSources = append(dataSources, datasrc)
   163  	} else {
   164  		dataSources, err = acquisition.LoadAcquisitionFromFile(cConfig.Synsec)
   165  		if err != nil {
   166  			log.Fatalf("While loading acquisition configuration : %s", err)
   167  		}
   168  	}
   169  
   170  	return nil
   171  }
   172  
   173  func (f *Flags) Parse() {
   174  
   175  	flag.StringVar(&f.ConfigFile, "c", "/etc/synsec/config.yaml", "configuration file")
   176  	flag.BoolVar(&f.TraceLevel, "trace", false, "VERY verbose")
   177  	flag.BoolVar(&f.DebugLevel, "debug", false, "print debug-level on stdout")
   178  	flag.BoolVar(&f.InfoLevel, "info", false, "print info-level on stdout")
   179  	flag.BoolVar(&f.PrintVersion, "version", false, "display version")
   180  	flag.StringVar(&f.SingleFilePath, "file", "", "Process a single file in time-machine")
   181  	flag.StringVar(&f.SingleJournalctlFilter, "jfilter", "", "Process a single journalctl output in time-machine")
   182  	flag.StringVar(&f.SingleFileType, "type", "", "Labels.type for file in time-machine")
   183  	flag.BoolVar(&f.TestMode, "t", false, "only test configs")
   184  	flag.BoolVar(&f.DisableAgent, "no-cs", false, "disable synsec agent")
   185  	flag.BoolVar(&f.DisableAPI, "no-api", false, "disable local API")
   186  
   187  	flag.Parse()
   188  }
   189  
   190  // LoadConfig return configuration parsed from configuration file
   191  func LoadConfig(cConfig *csconfig.Config) error {
   192  
   193  	if !flags.DisableAgent {
   194  		if err := cConfig.LoadSynsec(); err != nil {
   195  			return err
   196  		}
   197  	}
   198  
   199  	if !flags.DisableAPI {
   200  		if err := cConfig.LoadAPIServer(); err != nil {
   201  			return err
   202  		}
   203  	}
   204  
   205  	if !cConfig.DisableAgent && (cConfig.API == nil || cConfig.API.Client == nil || cConfig.API.Client.Credentials == nil) {
   206  		log.Fatalf("missing local API credentials for synsec agent, abort")
   207  	}
   208  
   209  	if cConfig.DisableAPI && cConfig.DisableAgent {
   210  		log.Fatalf("You must run at least the API Server or synsec")
   211  	}
   212  
   213  	if flags.SingleFilePath != "" {
   214  		if flags.SingleFileType == "" {
   215  			return fmt.Errorf("-file requires -type")
   216  		}
   217  	}
   218  
   219  	if flags.SingleJournalctlFilter != "" {
   220  		if flags.SingleFileType == "" {
   221  			return fmt.Errorf("-jfilter requires -type")
   222  		}
   223  	}
   224  
   225  	if flags.DebugLevel {
   226  		logLevel := log.DebugLevel
   227  		cConfig.Common.LogLevel = &logLevel
   228  	}
   229  	if flags.InfoLevel || cConfig.Common.LogLevel == nil {
   230  		logLevel := log.InfoLevel
   231  		cConfig.Common.LogLevel = &logLevel
   232  	}
   233  	if flags.TraceLevel {
   234  		logLevel := log.TraceLevel
   235  		cConfig.Common.LogLevel = &logLevel
   236  	}
   237  
   238  	if flags.TestMode && !cConfig.DisableAgent {
   239  		cConfig.Synsec.LintOnly = true
   240  	}
   241  
   242  	if flags.SingleFilePath != "" || flags.SingleJournalctlFilter != "" {
   243  		cConfig.API.Server.OnlineClient = nil
   244  		/*if the api is disabled as well, just read file and exit, don't daemonize*/
   245  		if flags.DisableAPI {
   246  			cConfig.Common.Daemonize = false
   247  		}
   248  		cConfig.Common.LogMedia = "stdout"
   249  		log.Infof("single file mode : log_media=%s daemonize=%t", cConfig.Common.LogMedia, cConfig.Common.Daemonize)
   250  	}
   251  
   252  	return nil
   253  }
   254  
   255  func main() {
   256  	var (
   257  		cConfig *csconfig.Config
   258  		err     error
   259  	)
   260  
   261  	defer types.CatchPanic("synsec/main")
   262  
   263  	// Handle command line arguments
   264  	flags = &Flags{}
   265  	flags.Parse()
   266  	if flags.PrintVersion {
   267  		cwversion.Show()
   268  		os.Exit(0)
   269  	}
   270  
   271  	cConfig, err = csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI)
   272  	if err != nil {
   273  		log.Fatalf(err.Error())
   274  	}
   275  	if err := LoadConfig(cConfig); err != nil {
   276  		log.Fatalf(err.Error())
   277  	}
   278  	// Configure logging
   279  	if err = types.SetDefaultLoggerConfig(cConfig.Common.LogMedia, cConfig.Common.LogDir, *cConfig.Common.LogLevel); err != nil {
   280  		log.Fatal(err.Error())
   281  	}
   282  
   283  	log.Infof("Synsec %s", cwversion.VersionStr())
   284  
   285  	// Enable profiling early
   286  	if cConfig.Prometheus != nil {
   287  		go registerPrometheus(cConfig.Prometheus)
   288  	}
   289  
   290  	if err := Serve(cConfig); err != nil {
   291  		log.Fatalf(err.Error())
   292  	}
   293  
   294  }