diff --git a/.env.example b/.env.example deleted file mode 100644 index 0c9e6fa..0000000 --- a/.env.example +++ /dev/null @@ -1,8 +0,0 @@ -GOMA_LISTEN_ADDR=0.0.0.0:80 -GOMA_WRITE_TIMEOUT=15 -GOMA_READ_TIMEOUT=15 -GOMA_IDLE_TIMEOUT=30 -GOMA_RATE_LIMITER=10 -GOMA_ACCESS_LOG=/dev/Stdout -GOMA_ERROR_LOG=/dev/stderr -GOMA_CONFIG_FILE=/config/goma.yml diff --git a/internal/handler.go b/internal/handler.go index 59d0a68..f18317c 100644 --- a/internal/handler.go +++ b/internal/handler.go @@ -75,6 +75,7 @@ func (heathRoute HealthCheckRoute) HealthCheckHandler(w http.ResponseWriter, r * var routes []HealthCheckRouteResponse for _, route := range heathRoute.Routes { go func() { + defer wg.Done() if route.HealthCheck != "" { err := HealthCheck(route.Destination + route.HealthCheck) if err != nil { @@ -90,7 +91,6 @@ func (heathRoute HealthCheckRoute) HealthCheckHandler(w http.ResponseWriter, r * logger.Warn("Route %s's healthCheck is undefined", route.Name) routes = append(routes, HealthCheckRouteResponse{Name: route.Name, Status: "undefined", Error: ""}) } - defer wg.Done() }() } @@ -109,7 +109,7 @@ func (heathRoute HealthCheckRoute) HealthCheckHandler(w http.ResponseWriter, r * func (heathRoute HealthCheckRoute) HealthReadyHandler(w http.ResponseWriter, r *http.Request) { logger.Info("%s %s %s %s", r.Method, r.RemoteAddr, r.URL, r.UserAgent()) response := HealthCheckRouteResponse{ - Name: "Goma Gateway", + Name: "Service Gateway", Status: "healthy", Error: "", } diff --git a/internal/helpers.go b/internal/helpers.go index a568def..e8fcbaa 100644 --- a/internal/helpers.go +++ b/internal/helpers.go @@ -10,11 +10,14 @@ You may get a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 */ import ( + "crypto/tls" "fmt" "github.com/jedib0t/go-pretty/v6/table" + "github.com/jkaninda/goma-gateway/pkg/logger" "net/http" ) +// printRoute prints routes func printRoute(routes []Route) { t := table.NewWriter() t.AppendHeader(table.Row{"Name", "Route", "Rewrite", "Destination"}) @@ -23,6 +26,8 @@ func printRoute(routes []Route) { } fmt.Println(t.Render()) } + +// getRealIP gets user real IP func getRealIP(r *http.Request) string { if ip := r.Header.Get("X-Real-IP"); ip != "" { return ip @@ -32,3 +37,19 @@ func getRealIP(r *http.Request) string { } return r.RemoteAddr } + +// loadTLS loads TLS Certificate +func loadTLS(cert, key string) (*tls.Config, error) { + if cert == "" && key == "" { + return nil, fmt.Errorf("no certificate or key file provided") + } + serverCert, err := tls.LoadX509KeyPair(cert, key) + if err != nil { + logger.Error("Error loading server certificate: %v", err) + return nil, err + } + tlsConfig := &tls.Config{ + Certificates: []tls.Certificate{serverCert}, + } + return tlsConfig, nil +} diff --git a/internal/server.go b/internal/server.go index fbe0dc4..3508a1a 100644 --- a/internal/server.go +++ b/internal/server.go @@ -17,6 +17,7 @@ limitations under the License. */ import ( "context" + "crypto/tls" "fmt" "github.com/jkaninda/goma-gateway/pkg/logger" "net/http" @@ -29,12 +30,24 @@ func (gatewayServer GatewayServer) Start(ctx context.Context) error { logger.Info("Initializing routes...") route := gatewayServer.Initialize() logger.Info("Initializing routes...done") + tlsConfig := &tls.Config{} + var listenWithTLS = false + if cert := gatewayServer.gateway.SSLCertFile; cert != "" && gatewayServer.gateway.SSLKeyFile != "" { + tlsConf, err := loadTLS(cert, gatewayServer.gateway.SSLKeyFile) + if err != nil { + return err + } + tlsConfig = tlsConf + listenWithTLS = true + + } srv := &http.Server{ Addr: gatewayServer.gateway.ListenAddr, WriteTimeout: time.Second * time.Duration(gatewayServer.gateway.WriteTimeout), ReadTimeout: time.Second * time.Duration(gatewayServer.gateway.ReadTimeout), IdleTimeout: time.Second * time.Duration(gatewayServer.gateway.IdleTimeout), Handler: route, // Pass our instance of gorilla/mux in. + TLSConfig: tlsConfig, } if !gatewayServer.gateway.DisableDisplayRouteOnStart { printRoute(gatewayServer.gateway.Routes) @@ -42,10 +55,16 @@ func (gatewayServer GatewayServer) Start(ctx context.Context) error { // Set KeepAlive srv.SetKeepAlivesEnabled(!gatewayServer.gateway.DisableKeepAlive) go func() { - logger.Info("Started Goma Gateway server on %v", gatewayServer.gateway.ListenAddr) - if err := srv.ListenAndServe(); err != nil { - logger.Error("Error starting Goma Gateway server: %v", err) + if listenWithTLS { + logger.Info("Server is running securely over HTTPS on %v ", gatewayServer.gateway.ListenAddr) + if err := srv.ListenAndServeTLS("", ""); err != nil { + logger.Fatal("Error starting Goma Gateway server: %v", err) + } + } else { + if err := srv.ListenAndServe(); err != nil { + logger.Fatal("Error starting Goma Gateway server: %v", err) + } } }() var wg sync.WaitGroup diff --git a/internal/types.go b/internal/types.go index 53d2a7e..dc7bce8 100644 --- a/internal/types.go +++ b/internal/types.go @@ -136,7 +136,9 @@ type Gateway struct { // ListenAddr Defines the server listenAddr // //e.g: localhost:8080 - ListenAddr string `yaml:"listenAddr" env:"GOMA_LISTEN_ADDR, overwrite"` + ListenAddr string `yaml:"listenAddr" env:"GOMA_LISTEN_ADDR, overwrite"` + SSLCertFile string `yaml:"sslCertFile" env:"GOMA_SSL_CERT_FILE, overwrite"` + SSLKeyFile string `yaml:"sslKeyFile" env:"GOMA_SSL_KEY_FILE, overwrite"` // WriteTimeout defines proxy write timeout WriteTimeout int `yaml:"writeTimeout" env:"GOMA_WRITE_TIMEOUT, overwrite"` // ReadTimeout defines proxy read timeout