package provider import ( "net/http" "os" "os/signal" "golang.org/x/sys/unix" "edge-infra.dev/pkg/edge/iam/barcode" "edge-infra.dev/pkg/edge/iam/cloud" "edge-infra.dev/pkg/edge/iam/config" "edge-infra.dev/pkg/edge/iam/device" "edge-infra.dev/pkg/edge/iam/errors" "edge-infra.dev/pkg/edge/iam/identity" "edge-infra.dev/pkg/edge/iam/middleware" "edge-infra.dev/pkg/edge/iam/oauth2" "edge-infra.dev/pkg/edge/iam/pin" "edge-infra.dev/pkg/edge/iam/prometheus" "edge-infra.dev/pkg/edge/iam/storage/database" "github.com/gin-contrib/secure" "github.com/gin-gonic/gin" "github.com/go-logr/logr" "github.com/prometheus/client_golang/prometheus/promhttp" ) func Serve(log logr.Logger) error { log = log.WithName("provider") // registering the metrics of the provider server metrics := prometheus.NewMetrics() log.Info("registered all the metrics") // get a place to store data storage, err := database.NewProviderStore(log) if err != nil { return err } // create and configure a new Gin router router := newGin(log) // serve up our main capabilities oauth2.NewOAuth2(router, storage.Sessions, storage) identity.NewIdentity(router, storage.Sessions, storage) cloud.NewCloud(router, log, storage.Sessions, storage, metrics) // initialize device login capabilities, irrespective of feature flag being enabled, as this piece of code is run only once during startup. deviceService := device.NewCloudService(config.DeviceBaseURL(), config.OrganizationID(), config.SiteID()) device.NewAuthMethod(router, deviceService, storage.Sessions, storage, metrics) // keep the PIN capabilities, even with device login enabled, no usage is expected with device login enabled. pin.NewPIN(router, storage.Sessions, storage, metrics) barcode.NewEmergency(router, storage.Sessions, storage, metrics) errors.NewEsodError(router) router.GET("/metrics", gin.WrapH(promhttp.Handler())) if config.ProxyToWeb() { log.Info("Proxying to the react web server, only for dev purpose.") } else { log.Info("serving up the UI from local filesystem") } // TODO:* handle errors // TODO:* look into graceful shutdown, can use termination handler process to perform graceful shutdown. log.Info("encryption", "enabled", config.EncryptionEnabled()) log.Info("starting the http router", "mode", gin.Mode()) log.Info("serving up Edge ID..") term := make(chan os.Signal, 1) signal.Notify(term, unix.SIGINT, unix.SIGTERM) go func() { signal := <-term log.Info("got termination signal", "signal", signal) }() return router.Run(config.Addr()) } func newGin(logger logr.Logger) *gin.Engine { if config.IsProduction() { gin.SetMode(gin.ReleaseMode) } router := gin.New() router.Use(middleware.SetOperationInContext()) router.Use(middleware.IntoContext(logger)) router.Use(middleware.RequestLogger(logger)) router.Use(secure.New(secure.Config{ ContentTypeNosniff: true, CustomFrameOptionsValue: "SAMEORIGIN", BrowserXssFilter: true, IENoOpen: true, // ContentSecurityPolicy: "default-src 'self' 'unsafe-inline'; img-src *; connect-src 'self' ws:", })) // for now router.GET("/live", func(c *gin.Context) { c.Status(http.StatusOK) }) router.GET("/ready", func(c *gin.Context) { c.Status(http.StatusOK) }) // recover from panics router.Use(gin.Recovery()) return router }