Move TLS config into its own struct

This commit is contained in:
Kristoffer Dalby 2022-06-03 10:14:14 +02:00
parent 5514a862dc
commit aee8aa1c61
2 changed files with 50 additions and 35 deletions

18
app.go
View file

@ -689,7 +689,7 @@ func (h *Headscale) Serve() error {
func (h *Headscale) getTLSSettings() (*tls.Config, error) { func (h *Headscale) getTLSSettings() (*tls.Config, error) {
var err error var err error
if h.cfg.TLSLetsEncryptHostname != "" { if h.cfg.TLS.LetsEncrypt.Hostname != "" {
if !strings.HasPrefix(h.cfg.ServerURL, "https://") { if !strings.HasPrefix(h.cfg.ServerURL, "https://") {
log.Warn(). log.Warn().
Msg("Listening with TLS but ServerURL does not start with https://") Msg("Listening with TLS but ServerURL does not start with https://")
@ -697,15 +697,15 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) {
certManager := autocert.Manager{ certManager := autocert.Manager{
Prompt: autocert.AcceptTOS, Prompt: autocert.AcceptTOS,
HostPolicy: autocert.HostWhitelist(h.cfg.TLSLetsEncryptHostname), HostPolicy: autocert.HostWhitelist(h.cfg.TLS.LetsEncrypt.Hostname),
Cache: autocert.DirCache(h.cfg.TLSLetsEncryptCacheDir), Cache: autocert.DirCache(h.cfg.TLS.LetsEncrypt.CacheDir),
Client: &acme.Client{ Client: &acme.Client{
DirectoryURL: h.cfg.ACMEURL, DirectoryURL: h.cfg.ACMEURL,
}, },
Email: h.cfg.ACMEEmail, Email: h.cfg.ACMEEmail,
} }
switch h.cfg.TLSLetsEncryptChallengeType { switch h.cfg.TLS.LetsEncrypt.ChallengeType {
case "TLS-ALPN-01": case "TLS-ALPN-01":
// Configuration via autocert with TLS-ALPN-01 (https://tools.ietf.org/html/rfc8737) // Configuration via autocert with TLS-ALPN-01 (https://tools.ietf.org/html/rfc8737)
// The RFC requires that the validation is done on port 443; in other words, headscale // The RFC requires that the validation is done on port 443; in other words, headscale
@ -719,7 +719,7 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) {
go func() { go func() {
log.Fatal(). log.Fatal().
Caller(). Caller().
Err(http.ListenAndServe(h.cfg.TLSLetsEncryptListen, certManager.HTTPHandler(http.HandlerFunc(h.redirect)))). Err(http.ListenAndServe(h.cfg.TLS.LetsEncrypt.Listen, certManager.HTTPHandler(http.HandlerFunc(h.redirect)))).
Msg("failed to set up a HTTP server") Msg("failed to set up a HTTP server")
}() }()
@ -728,7 +728,7 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) {
default: default:
return nil, errUnsupportedLetsEncryptChallengeType return nil, errUnsupportedLetsEncryptChallengeType
} }
} else if h.cfg.TLSCertPath == "" { } else if h.cfg.TLS.CertPath == "" {
if !strings.HasPrefix(h.cfg.ServerURL, "http://") { if !strings.HasPrefix(h.cfg.ServerURL, "http://") {
log.Warn().Msg("Listening without TLS but ServerURL does not start with http://") log.Warn().Msg("Listening without TLS but ServerURL does not start with http://")
} }
@ -741,16 +741,16 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) {
log.Info().Msg(fmt.Sprintf( log.Info().Msg(fmt.Sprintf(
"Client authentication (mTLS) is \"%s\". See the docs to learn about configuring this setting.", "Client authentication (mTLS) is \"%s\". See the docs to learn about configuring this setting.",
h.cfg.TLSClientAuthMode)) h.cfg.TLS.ClientAuthMode))
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
ClientAuth: h.cfg.TLSClientAuthMode, ClientAuth: h.cfg.TLS.ClientAuthMode,
NextProtos: []string{"http/1.1"}, NextProtos: []string{"http/1.1"},
Certificates: make([]tls.Certificate, 1), Certificates: make([]tls.Certificate, 1),
MinVersion: tls.VersionTLS12, MinVersion: tls.VersionTLS12,
} }
tlsConfig.Certificates[0], err = tls.LoadX509KeyPair(h.cfg.TLSCertPath, h.cfg.TLSKeyPath) tlsConfig.Certificates[0], err = tls.LoadX509KeyPair(h.cfg.TLS.CertPath, h.cfg.TLS.KeyPath)
return tlsConfig, err return tlsConfig, err
} }

View file

@ -39,14 +39,7 @@ type Config struct {
DBuser string DBuser string
DBpass string DBpass string
TLSLetsEncryptListen string TLS TLSConfig
TLSLetsEncryptHostname string
TLSLetsEncryptCacheDir string
TLSLetsEncryptChallengeType string
TLSCertPath string
TLSKeyPath string
TLSClientAuthMode tls.ClientAuthType
ACMEURL string ACMEURL string
ACMEEmail string ACMEEmail string
@ -65,6 +58,21 @@ type Config struct {
ACL ACLConfig ACL ACLConfig
} }
type TLSConfig struct {
CertPath string
KeyPath string
ClientAuthMode tls.ClientAuthType
LetsEncrypt LetsEncryptConfig
}
type LetsEncryptConfig struct {
Listen string
Hostname string
CacheDir string
ChallengeType string
}
type OIDCConfig struct { type OIDCConfig struct {
Issuer string Issuer string
ClientID string ClientID string
@ -193,6 +201,30 @@ func LoadConfig(path string) error {
} }
} }
func GetTLSConfig() TLSConfig {
tlsClientAuthMode, _ := LookupTLSClientAuthMode(
viper.GetString("tls_client_auth_mode"),
)
return TLSConfig{
LetsEncrypt: LetsEncryptConfig{
Hostname: viper.GetString("tls_letsencrypt_hostname"),
Listen: viper.GetString("tls_letsencrypt_listen"),
CacheDir: AbsolutePathFromConfigPath(
viper.GetString("tls_letsencrypt_cache_dir"),
),
ChallengeType: viper.GetString("tls_letsencrypt_challenge_type"),
},
CertPath: AbsolutePathFromConfigPath(
viper.GetString("tls_cert_path"),
),
KeyPath: AbsolutePathFromConfigPath(
viper.GetString("tls_key_path"),
),
ClientAuthMode: tlsClientAuthMode,
}
}
func GetDERPConfig() DERPConfig { func GetDERPConfig() DERPConfig {
serverEnabled := viper.GetBool("derp.server.enabled") serverEnabled := viper.GetBool("derp.server.enabled")
serverRegionID := viper.GetInt("derp.server.region_id") serverRegionID := viper.GetInt("derp.server.region_id")
@ -394,10 +426,6 @@ func GetHeadscaleConfig() Config {
Msgf("'ip_prefixes' not configured, falling back to default: %v", prefixes) Msgf("'ip_prefixes' not configured, falling back to default: %v", prefixes)
} }
tlsClientAuthMode, _ := LookupTLSClientAuthMode(
viper.GetString("tls_client_auth_mode"),
)
return Config{ return Config{
ServerURL: viper.GetString("server_url"), ServerURL: viper.GetString("server_url"),
Addr: viper.GetString("listen_addr"), Addr: viper.GetString("listen_addr"),
@ -425,20 +453,7 @@ func GetHeadscaleConfig() Config {
DBuser: viper.GetString("db_user"), DBuser: viper.GetString("db_user"),
DBpass: viper.GetString("db_pass"), DBpass: viper.GetString("db_pass"),
TLSLetsEncryptHostname: viper.GetString("tls_letsencrypt_hostname"), TLS: GetTLSConfig(),
TLSLetsEncryptListen: viper.GetString("tls_letsencrypt_listen"),
TLSLetsEncryptCacheDir: AbsolutePathFromConfigPath(
viper.GetString("tls_letsencrypt_cache_dir"),
),
TLSLetsEncryptChallengeType: viper.GetString("tls_letsencrypt_challenge_type"),
TLSCertPath: AbsolutePathFromConfigPath(
viper.GetString("tls_cert_path"),
),
TLSKeyPath: AbsolutePathFromConfigPath(
viper.GetString("tls_key_path"),
),
TLSClientAuthMode: tlsClientAuthMode,
DNSConfig: dnsConfig, DNSConfig: dnsConfig,