package main import ( "flag" "fmt" "net/http" "os" "strconv" "strings" "time" "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/cookie" "github.com/gin-gonic/gin" "chaitin.cn/patronus/safeline-2/management/webserver/api" "chaitin.cn/patronus/safeline-2/management/webserver/cmd" "chaitin.cn/patronus/safeline-2/management/webserver/middleware" "chaitin.cn/patronus/safeline-2/management/webserver/model" "chaitin.cn/patronus/safeline-2/management/webserver/pkg/config" "chaitin.cn/patronus/safeline-2/management/webserver/pkg/constants" "chaitin.cn/patronus/safeline-2/management/webserver/pkg/cron" "chaitin.cn/patronus/safeline-2/management/webserver/pkg/database" "chaitin.cn/patronus/safeline-2/management/webserver/pkg/fvm" "chaitin.cn/patronus/safeline-2/management/webserver/pkg/log" "chaitin.cn/patronus/safeline-2/management/webserver/rpc" ) var ( logger = log.GetLogger("main") version = "undefined" githash = "undefined" buildstamp = "undefined" goVersion = "undefined" ) func init() { // do something that do not raise error } func main() { log.SetLogFormatter() fs := flag.NewFlagSet("webserver", flag.ExitOnError) showVersion := fs.Bool("v", false, "show version") cfgFile := fs.String("c", constants.ConfigFilePath, "config file path") genCerts := fs.Bool("gen_certs", false, "generate certs") showFSL := fs.Bool("show_fsl", false, "show full selectors") push_fsl := fs.Bool("push_fsl", false, "compile and push fsl") fakeLogs := fs.Bool("fake_logs", false, "fake logs") resetUsername := fs.String("reset_user", "", "reset user") if err := fs.Parse(os.Args[1:]); err != nil { logger.Fatalln("Failed to parse args: ", err) } if *showVersion { i, _ := strconv.Atoi(buildstamp) t := time.Unix(int64(i), 0).Format("2006-01-02 15:04:05") fmt.Println("Version: ", version) fmt.Println("Githash: ", githash) fmt.Println("Build: ", t) fmt.Println("Go version: ", goVersion) return } constants.Version = version // init configs if err := config.InitConfigs(*cfgFile); err != nil { logger.Fatalln("Failed to init configs: ", err) } if err := log.InitLogger(); err != nil { logger.Fatalln("Failed to init db: ", err) } if *genCerts { if err := cmd.GenCerts(); err != nil { logger.Fatalln("Failed to generate certs: ", err) } return } logger.Info("Init database") if err := database.InitDB(); err != nil { logger.Fatalln("Failed to init db: ", err) } if *showFSL { if fullFSL, err := cmd.ShowFSL(); err != nil { logger.Fatalln("Failed to generate fsl: ", err) } else { logger.Info(strings.ReplaceAll(strings.ReplaceAll(fullFSL, ";", ";\n"), "CREATE", "\nCREATE")) } return } logger.Info("Init models") if err := model.InitModels(); err != nil { logger.Fatalln("Failed to init models: ", err) } if len(*resetUsername) > 0 { logger.Infoln("reset user:", *resetUsername) cmd.ResetUser(*resetUsername) logger.Infoln("success!") return } if *fakeLogs { logger.Infoln("faking logs...") cmd.FakeLogs() logger.Infoln("success!") return } if *push_fsl { logger.Infoln("push fsl...") if err := cmd.PushFSL(); err != nil { logger.Fatalln("Failed to generate fsl: ", err) } logger.Infoln("success!") return } logger.Info("Init FVM bytecode") fvm.InitFVMBytecode() if err := cron.StartCron(); err != nil { logger.Fatalln("Failed to start cron: ", err) } if err := rpc.StartGRPCSever(); err != nil { logger.Fatalln("Failed to start gRPC server: ", err) } gin.SetMode(gin.ReleaseMode) r := gin.Default() var option model.Options database.GetDB().Where(&model.Options{Key: constants.SecretKey}).First(&option) logger.Debugf("Secret: %s", option.Value) store := cookie.NewStore([]byte(option.Value)) r.Use(sessions.Sessions("session", store)) publicRouters := r.Group("/api") publicRouters.POST(api.Login, api.PostLogin) publicRouters.POST(api.Logout, api.PostLogout) publicRouters.POST(api.Behaviour, api.PostBehaviour) publicRouters.POST(api.FalsePositives, api.PostFalsePositives) publicRouters.GET(api.OTPUrl, api.GetOTPUrl) publicRouters.GET(api.Version, api.GetVersion) publicRouters.GET(api.UpgradeTips, api.GetUpgradeTips) // test use publicRouters.GET("/Ping", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "pong", }) }) limitedRouters := r.Group("/api") noAuth, existed := os.LookupEnv("NO_AUTH") if existed && len(noAuth) >= 0 { logger.Warn("No auth") } else { limitedRouters.Use(middleware.AuthRequired) } readOnly, existed := os.LookupEnv("READ_ONLY") if existed && len(readOnly) >= 0 { logger.Warn("Read only") limitedRouters.Use(middleware.ReadOnly) } limitedRouters.GET(api.User, api.GetUser) limitedRouters.GET(api.CurrentUser, api.GetCurrentUser) // Admin-only user management adminRouters := limitedRouters.Group("") adminRouters.Use(middleware.RequireRole("admin")) adminRouters.GET(api.Users, api.GetUsers) adminRouters.POST(api.Users, api.PostUser) adminRouters.PUT(api.Users+"/:id", api.PutUser) adminRouters.DELETE(api.Users+"/:id", api.DeleteUser) adminRouters.POST(api.Users+"/:id/reset-password", api.PostResetPassword) // Operator and above (read + policy management) operatorRouters := limitedRouters.Group("") operatorRouters.Use(middleware.RequireRole("admin", "operator")) operatorRouters.GET(api.DetectLogList, api.GetDetectLogList) operatorRouters.GET(api.DetectLogDetail, api.GetDetectLogDetail) operatorRouters.POST(api.Website, api.PostWebsite) operatorRouters.PUT(api.Website, api.PutWebsite) operatorRouters.DELETE(api.Website, api.DeleteWebsite) operatorRouters.GET(api.Website, api.GetWebsite) operatorRouters.POST(api.UploadSSLCert, api.PostUploadSSLCert) operatorRouters.POST(api.SSLCert, api.PostSSLCert) operatorRouters.POST(api.PolicyRule, api.PostPolicyRule) operatorRouters.PUT(api.PolicyRule, api.PutPolicyRule) operatorRouters.DELETE(api.PolicyRule, api.DeletePolicyRule) operatorRouters.GET(api.PolicyRule, api.GetPolicyRule) operatorRouters.PUT(api.SwitchPolicyRule, api.PutSwitchPolicyRule) // All authenticated users can access dashboard and view policies limitedRouters.GET(api.DashboardCounts, api.GetDashboardCounts) limitedRouters.GET(api.DashboardSites, api.GetDashboardSites) limitedRouters.GET(api.DashboardQps, api.GetDashboardQps) limitedRouters.GET(api.DashboardRequests, api.GetDashboardRequests) limitedRouters.GET(api.DashboardIntercepts, api.GetDashboardIntercepts) limitedRouters.GET(api.PolicyGroupGlobal, api.GetPolicyGroupGlobal) limitedRouters.PUT(api.PolicyGroupGlobal, api.PutPolicyGroupGlobal) limitedRouters.POST(api.PolicyGroupPreset, api.PostPolicyGroupPreset) limitedRouters.GET(api.SrcIPConfig, api.GetSrcIPConfig) limitedRouters.PUT(api.SrcIPConfig, api.PutSrcIPConfig) logger.Info("Staring...") if err := r.Run(config.GlobalConfig.Server.ListenAddr); err != nil { logger.Fatalln("Error occurred when running web server: ", err) } }