mirror of
https://github.com/jsiebens/ionscale.git
synced 2026-03-31 15:07:49 +01:00
feat: add support for certmagic
This commit is contained in:
@@ -2,6 +2,7 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/caddyserver/certmagic"
|
||||
"github.com/jsiebens/ionscale/internal/util"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"gopkg.in/yaml.v3"
|
||||
@@ -42,6 +43,10 @@ const (
|
||||
tlsDisableKey = "IONSCALE_TLS_DISABLE"
|
||||
tlsCertFileKey = "IONSCALE_TLS_CERT_FILE"
|
||||
tlsKeyFileKey = "IONSCALE_TLS_KEY_FILE"
|
||||
tlsCertMagicCAKey = "IONSCALE_TLS_CERT_MAGIC_CA"
|
||||
tlsCertMagicDomainKey = "IONSCALE_TLS_CERT_MAGIC_DOMAIN"
|
||||
tlsCertMagicEmailKey = "IONSCALE_TLS_CERT_MAGIC_EMAIL"
|
||||
tlsCertMagicStoragePath = "IONSCALE_TLS_CERT_MAGIC_STORAGE_PATH"
|
||||
metricsListenAddrKey = "IONSCALE_METRICS_LISTEN_ADDR"
|
||||
loggingLevelKey = "IONSCALE_LOGGING_LEVEL"
|
||||
loggingFormatKey = "IONSCALE_LOGGING_FORMAT"
|
||||
@@ -63,9 +68,13 @@ func defaultConfig() *Config {
|
||||
Url: GetString(databaseUrlKey, "ionscale.db"),
|
||||
},
|
||||
Tls: Tls{
|
||||
Disable: GetBool(tlsDisableKey, false),
|
||||
CertFile: GetString(tlsCertFileKey, ""),
|
||||
KeyFile: GetString(tlsKeyFileKey, ""),
|
||||
Disable: GetBool(tlsDisableKey, false),
|
||||
CertFile: GetString(tlsCertFileKey, ""),
|
||||
KeyFile: GetString(tlsKeyFileKey, ""),
|
||||
CertMagicCA: GetString(tlsCertMagicCAKey, certmagic.LetsEncryptProductionCA),
|
||||
CertMagicDomain: GetString(tlsCertMagicDomainKey, ""),
|
||||
CertMagicEmail: GetString(tlsCertMagicEmailKey, ""),
|
||||
CertMagicStoragePath: GetString(tlsCertMagicStoragePath, ""),
|
||||
},
|
||||
Logging: Logging{
|
||||
Level: GetString(loggingLevelKey, "info"),
|
||||
@@ -93,9 +102,13 @@ type Config struct {
|
||||
}
|
||||
|
||||
type Tls struct {
|
||||
Disable bool `yaml:"disable"`
|
||||
CertFile string `yaml:"cert_file"`
|
||||
KeyFile string `yaml:"key_file"`
|
||||
Disable bool `yaml:"disable"`
|
||||
CertFile string `yaml:"cert_file"`
|
||||
KeyFile string `yaml:"key_file"`
|
||||
CertMagicDomain string `yaml:"cert_magic_domain"`
|
||||
CertMagicEmail string `yaml:"cert_magic_email"`
|
||||
CertMagicCA string `yaml:"cert_magic_ca"`
|
||||
CertMagicStoragePath string `yaml:"cert_magic_storage_path"`
|
||||
}
|
||||
|
||||
type Logging struct {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/caddyserver/certmagic"
|
||||
"github.com/jsiebens/ionscale/internal/config"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net"
|
||||
@@ -8,18 +9,30 @@ import (
|
||||
)
|
||||
|
||||
func HttpRedirectHandler(tls config.Tls) echo.HandlerFunc {
|
||||
if tls.CertMagicDomain != "" {
|
||||
cfg := certmagic.NewDefault()
|
||||
if len(cfg.Issuers) > 0 {
|
||||
if am, ok := cfg.Issuers[0].(*certmagic.ACMEIssuer); ok {
|
||||
handler := am.HTTPChallengeHandler(http.HandlerFunc(httpRedirectHandler))
|
||||
return echo.WrapHandler(handler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if tls.Disable {
|
||||
return IndexHandler(http.StatusNotFound)
|
||||
}
|
||||
|
||||
return func(c echo.Context) error {
|
||||
r := c.Request()
|
||||
toURL := "https://"
|
||||
requestHost := hostOnly(r.Host)
|
||||
toURL += requestHost
|
||||
toURL += r.URL.RequestURI()
|
||||
return c.Redirect(http.StatusMovedPermanently, toURL)
|
||||
}
|
||||
return echo.WrapHandler(http.HandlerFunc(httpRedirectHandler))
|
||||
}
|
||||
|
||||
func httpRedirectHandler(w http.ResponseWriter, r *http.Request) {
|
||||
toURL := "https://"
|
||||
requestHost := hostOnly(r.Host)
|
||||
toURL += requestHost
|
||||
toURL += r.URL.RequestURI()
|
||||
w.Header().Set("Connection", "close")
|
||||
http.Redirect(w, r, toURL, http.StatusMovedPermanently)
|
||||
}
|
||||
|
||||
func hostOnly(hostport string) string {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"github.com/caddyserver/certmagic"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/improbable-eng/grpc-web/go/grpcweb"
|
||||
"github.com/jsiebens/ionscale/internal/bind"
|
||||
@@ -16,6 +19,8 @@ import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/patrickmn/go-cache"
|
||||
"github.com/soheilhy/cmux"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/h2c"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"log"
|
||||
"net"
|
||||
@@ -52,6 +57,24 @@ func Start(config *config.Config) error {
|
||||
go offlineTimers.Start()
|
||||
go reaper.Start()
|
||||
|
||||
// prepare CertMagic
|
||||
if config.Tls.CertMagicDomain != "" {
|
||||
certmagic.DefaultACME.Agreed = true
|
||||
certmagic.DefaultACME.Email = config.Tls.CertMagicEmail
|
||||
certmagic.DefaultACME.CA = config.Tls.CertMagicCA
|
||||
if config.Tls.CertMagicStoragePath != "" {
|
||||
certmagic.Default.Storage = &certmagic.FileStorage{Path: config.Tls.CertMagicStoragePath}
|
||||
}
|
||||
|
||||
cfg := certmagic.NewDefault()
|
||||
if err := cfg.ManageSync(context.Background(), []string{config.Tls.CertMagicDomain}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.HttpListenAddr = fmt.Sprintf(":%d", certmagic.HTTPPort)
|
||||
config.HttpsListenAddr = fmt.Sprintf(":%d", certmagic.HTTPSPort)
|
||||
}
|
||||
|
||||
createPeerHandler := func(p key.MachinePublic) http.Handler {
|
||||
registrationHandlers := handlers.NewRegistrationHandlers(bind.DefaultBinder(p), config, repository, pendingMachineRegistrationRequests)
|
||||
pollNetMapHandler := handlers.NewPollNetMapHandler(bind.DefaultBinder(p), brokers, repository, offlineTimers)
|
||||
@@ -134,12 +157,12 @@ func Start(config *config.Config) error {
|
||||
httpL := mux.Match(cmux.Any())
|
||||
|
||||
grpcWebHandler := grpcweb.WrapServer(grpcServer)
|
||||
|
||||
http2Server := &http2.Server{}
|
||||
g := new(errgroup.Group)
|
||||
|
||||
g.Go(func() error { return grpcServer.Serve(grpcL) })
|
||||
g.Go(func() error { return http.Serve(grpcWebL, grpcWebHandler) })
|
||||
g.Go(func() error { return http.Serve(httpL, tlsAppHandler) })
|
||||
g.Go(func() error { return http.Serve(grpcWebL, h2c.NewHandler(grpcWebHandler, http2Server)) })
|
||||
g.Go(func() error { return http.Serve(httpL, h2c.NewHandler(tlsAppHandler, http2Server)) })
|
||||
g.Go(func() error { return http.Serve(metricsL, metricsHandler) })
|
||||
g.Go(func() error { return mux.Serve() })
|
||||
|
||||
@@ -147,12 +170,15 @@ func Start(config *config.Config) error {
|
||||
g.Go(func() error { return http.Serve(nonTlsL, nonTlsAppHandler) })
|
||||
}
|
||||
|
||||
if config.Tls.Disable {
|
||||
logger.Warn("TLS is disabled")
|
||||
logger.Info("Server is running", "http_addr", config.HttpListenAddr, "metrics_addr", config.MetricsListenAddr)
|
||||
} else {
|
||||
if config.Tls.CertMagicDomain != "" {
|
||||
logger.Info("TLS is enabled with CertMagic", "domain", config.Tls.CertMagicDomain)
|
||||
logger.Info("Server is running", "http_addr", config.HttpListenAddr, "https_addr", config.HttpsListenAddr, "metrics_addr", config.MetricsListenAddr)
|
||||
} else if !config.Tls.Disable {
|
||||
logger.Info("TLS is enabled", "cert", config.Tls.CertFile)
|
||||
logger.Info("Server is running", "http_addr", config.HttpListenAddr, "https_addr", config.HttpsListenAddr, "metrics_addr", config.MetricsListenAddr)
|
||||
} else {
|
||||
logger.Warn("TLS is disabled")
|
||||
logger.Info("Server is running", "http_addr", config.HttpListenAddr, "metrics_addr", config.MetricsListenAddr)
|
||||
}
|
||||
|
||||
return g.Wait()
|
||||
@@ -163,6 +189,13 @@ func metricsListener(config *config.Config) (net.Listener, error) {
|
||||
}
|
||||
|
||||
func tlsListener(config *config.Config) (net.Listener, error) {
|
||||
if config.Tls.CertMagicDomain != "" {
|
||||
cfg := certmagic.NewDefault()
|
||||
tlsConfig := cfg.TLSConfig()
|
||||
tlsConfig.NextProtos = append([]string{"h2", "http/1.1"}, tlsConfig.NextProtos...)
|
||||
return tls.Listen("tcp", config.HttpsListenAddr, tlsConfig)
|
||||
}
|
||||
|
||||
if !config.Tls.Disable {
|
||||
cer, err := tls.LoadX509KeyPair(config.Tls.CertFile, config.Tls.KeyFile)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user