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 }