feat: TLS support (#3862)

* feat: TLS support

* add comment

* fix comment
This commit is contained in:
Livio Spring
2022-06-24 14:38:22 +02:00
committed by GitHub
parent 70a108deeb
commit ed5721d39e
12 changed files with 186 additions and 19 deletions

View File

@@ -9,6 +9,7 @@ import (
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/cmd/admin/key"
"github.com/zitadel/zitadel/cmd/admin/tls"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/migration"
@@ -28,6 +29,9 @@ func New() *cobra.Command {
Requirements:
- cockroachdb`,
Run: func(cmd *cobra.Command, args []string) {
err := tls.ModeFromFlag(cmd)
logging.OnError(err).Fatal("invalid tlsMode")
config := MustNewConfig(viper.GetViper())
steps := MustNewSteps(viper.New())
@@ -46,6 +50,7 @@ Requirements:
func Flags(cmd *cobra.Command) {
cmd.PersistentFlags().StringArrayVar(&stepFiles, "steps", nil, "paths to step files to overwrite default steps")
key.AddMasterKeyFlag(cmd)
tls.AddTLSModeFlag(cmd)
}
func Setup(config *Config, steps *Steps, masterKey string) {

View File

@@ -16,6 +16,7 @@ import (
auth_es "github.com/zitadel/zitadel/internal/auth/repository/eventsourcing"
"github.com/zitadel/zitadel/internal/command"
"github.com/zitadel/zitadel/internal/config/hook"
"github.com/zitadel/zitadel/internal/config/network"
"github.com/zitadel/zitadel/internal/config/systemdefaults"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/database"
@@ -31,6 +32,7 @@ type Config struct {
ExternalPort uint16
ExternalDomain string
ExternalSecure bool
TLS network.TLS
HTTP2HostHeader string
HTTP1HostHeader string
WebAuthNName string

View File

@@ -5,14 +5,17 @@ import (
"github.com/spf13/viper"
"github.com/zitadel/zitadel/cmd/admin/key"
"github.com/zitadel/zitadel/cmd/admin/tls"
)
var tlsMode *string
func startFlags(cmd *cobra.Command) {
bindUint16Flag(cmd, "port", "port to run ZITADEL on")
bindStringFlag(cmd, "externalDomain", "domain ZITADEL will be exposed on")
bindStringFlag(cmd, "externalPort", "port ZITADEL will be exposed on")
bindBoolFlag(cmd, "externalSecure", "if ZITADEL will be served on HTTPS")
tls.AddTLSModeFlag(cmd)
key.AddMasterKeyFlag(cmd)
}

View File

@@ -2,6 +2,7 @@ package start
import (
"context"
"crypto/tls"
"database/sql"
_ "embed"
"fmt"
@@ -21,6 +22,7 @@ import (
"golang.org/x/net/http2/h2c"
"github.com/zitadel/zitadel/cmd/admin/key"
cmd_tls "github.com/zitadel/zitadel/cmd/admin/tls"
admin_es "github.com/zitadel/zitadel/internal/admin/repository/eventsourcing"
"github.com/zitadel/zitadel/internal/api"
"github.com/zitadel/zitadel/internal/api/assets"
@@ -57,6 +59,10 @@ func New() *cobra.Command {
Requirements:
- cockroachdb`,
RunE: func(cmd *cobra.Command, args []string) error {
err := cmd_tls.ModeFromFlag(cmd)
if err != nil {
return err
}
config := MustNewConfig(viper.GetViper())
masterKey, err := key.MasterKey(cmd)
if err != nil {
@@ -136,14 +142,18 @@ func startZitadel(config *Config, masterKey string) error {
notification.Start(config.Notification, config.ExternalPort, config.ExternalSecure, commands, queries, dbClient, assets.HandlerPrefix, config.SystemDefaults.Notifications.FileSystemPath, keys.User, keys.SMTP, keys.SMS)
router := mux.NewRouter()
err = startAPIs(ctx, router, commands, queries, eventstoreClient, dbClient, config, storage, authZRepo, keys, config.SystemAPIUsers)
tlsConfig, err := config.TLS.Config()
if err != nil {
return err
}
return listen(ctx, router, config.Port)
err = startAPIs(ctx, router, commands, queries, eventstoreClient, dbClient, config, storage, authZRepo, keys)
if err != nil {
return err
}
return listen(ctx, router, config.Port, tlsConfig)
}
func startAPIs(ctx context.Context, router *mux.Router, commands *command.Commands, queries *query.Queries, eventstore *eventstore.Eventstore, dbClient *sql.DB, config *Config, store static.Storage, authZRepo authz_repo.Repository, keys *encryptionKeys, systemAPIKeys map[string]*internal_authz.SystemAPIUser) error {
func startAPIs(ctx context.Context, router *mux.Router, commands *command.Commands, queries *query.Queries, eventstore *eventstore.Eventstore, dbClient *sql.DB, config *Config, store static.Storage, authZRepo authz_repo.Repository, keys *encryptionKeys) error {
repo := struct {
authz_repo.Repository
*query.Queries
@@ -151,9 +161,12 @@ func startAPIs(ctx context.Context, router *mux.Router, commands *command.Comman
authZRepo,
queries,
}
verifier := internal_authz.Start(repo, http_util.BuildHTTP(config.ExternalDomain, config.ExternalPort, config.ExternalSecure), systemAPIKeys)
apis := api.New(config.Port, router, queries, verifier, config.InternalAuthZ, config.ExternalSecure, config.HTTP2HostHeader, config.HTTP1HostHeader)
verifier := internal_authz.Start(repo, http_util.BuildHTTP(config.ExternalDomain, config.ExternalPort, config.ExternalSecure), config.SystemAPIUsers)
tlsConfig, err := config.TLS.Config()
if err != nil {
return err
}
apis := api.New(config.Port, router, queries, verifier, config.InternalAuthZ, config.ExternalSecure, tlsConfig, config.HTTP2HostHeader, config.HTTP1HostHeader)
authRepo, err := auth_es.Start(config.Auth, config.SystemDefaults, commands, queries, dbClient, keys.OIDC, keys.User)
if err != nil {
return fmt.Errorf("error starting auth repo: %w", err)
@@ -215,9 +228,9 @@ func startAPIs(ctx context.Context, router *mux.Router, commands *command.Comman
return nil
}
func listen(ctx context.Context, router *mux.Router, port uint16) error {
func listen(ctx context.Context, router *mux.Router, port uint16, tlsConfig *tls.Config) error {
http2Server := &http2.Server{}
http1Server := &http.Server{Handler: h2c.NewHandler(router, http2Server)}
http1Server := &http.Server{Handler: h2c.NewHandler(router, http2Server), TLSConfig: tlsConfig}
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
return fmt.Errorf("tcp listener on %d failed: %w", port, err)
@@ -227,7 +240,12 @@ func listen(ctx context.Context, router *mux.Router, port uint16) error {
go func() {
logging.Infof("server is listening on %s", lis.Addr().String())
errCh <- http1Server.Serve(lis)
if tlsConfig != nil {
//we don't need to pass the files here, because we already initialized the TLS config on the server
errCh <- http1Server.ServeTLS(lis, "", "")
} else {
errCh <- http1Server.Serve(lis)
}
}()
shutdown := make(chan os.Signal, 1)

View File

@@ -8,6 +8,7 @@ import (
"github.com/zitadel/zitadel/cmd/admin/initialise"
"github.com/zitadel/zitadel/cmd/admin/key"
"github.com/zitadel/zitadel/cmd/admin/setup"
"github.com/zitadel/zitadel/cmd/admin/tls"
)
func NewStartFromInit() *cobra.Command {
@@ -22,6 +23,9 @@ Last ZITADEL starts.
Requirements:
- cockroachdb`,
Run: func(cmd *cobra.Command, args []string) {
err := tls.ModeFromFlag(cmd)
logging.OnError(err).Fatal("invalid tlsMode")
masterKey, err := key.MasterKey(cmd)
logging.OnError(err).Panic("No master key provided")

46
cmd/admin/tls/tls.go Normal file
View File

@@ -0,0 +1,46 @@
package tls
import (
"errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
const (
flagTLSMode = "tlsMode"
)
var (
ErrValidValue = errors.New("value must either be `enabled`, `external` or `disabled`")
)
func AddTLSModeFlag(cmd *cobra.Command) {
if cmd.PersistentFlags().Lookup(flagTLSMode) != nil {
return
}
cmd.PersistentFlags().String(flagTLSMode, "", "start ZITADEL with (enabled), without (disabled) TLS or external component e.g. reverse proxy (external) terminating TLS, this flag will overwrite `externalSecure` and `tls.enabled` in configs files")
}
func ModeFromFlag(cmd *cobra.Command) error {
tlsMode, _ := cmd.Flags().GetString(flagTLSMode)
var tlsEnabled, externalSecure bool
switch tlsMode {
case "enabled":
tlsEnabled = true
externalSecure = true
case "external":
tlsEnabled = false
externalSecure = true
case "disabled":
tlsEnabled = false
externalSecure = false
case "":
return nil
default:
return ErrValidValue
}
viper.Set("tls.enabled", tlsEnabled)
viper.Set("externalSecure", externalSecure)
return nil
}