refactoring

This commit is contained in:
Justin Angel 2022-02-20 09:06:14 -05:00
parent 1b2fff4337
commit 385dd9cc34
5 changed files with 38 additions and 32 deletions

49
app.go
View file

@ -94,7 +94,7 @@ type Config struct {
TLSCertPath string TLSCertPath string
TLSKeyPath string TLSKeyPath string
TLSClientAuthMode string TLSClientAuthMode tls.ClientAuthType
ACMEURL string ACMEURL string
ACMEEmail string ACMEEmail string
@ -153,6 +153,27 @@ type Headscale struct {
requestedExpiryCache *cache.Cache requestedExpiryCache *cache.Cache
} }
// Look up the TLS constant relative to user-supplied TLS client
// authentication mode. If an unknown mode is supplied, the default
// value, tls.RequireAnyClientCert, is returned. The returned boolean
// indicates if the supplied mode was valid.
func LookupTLSClientAuthMode(mode string) (tls.ClientAuthType, bool) {
switch mode {
case DisabledClientAuth:
// Client cert is _not_ required.
return tls.NoClientCert, true
case RelaxedClientAuth:
// Client cert required, but _not verified_.
return tls.RequireAnyClientCert, true
case EnforcedClientAuth:
// Client cert is _required and verified_.
return tls.RequireAndVerifyClientCert, true
default:
// Return the default when an unknown value is supplied.
return tls.RequireAnyClientCert, false
}
}
// NewHeadscale returns the Headscale app. // NewHeadscale returns the Headscale app.
func NewHeadscale(cfg Config) (*Headscale, error) { func NewHeadscale(cfg Config) (*Headscale, error) {
privKey, err := readOrCreatePrivateKey(cfg.PrivateKeyPath) privKey, err := readOrCreatePrivateKey(cfg.PrivateKeyPath)
@ -655,17 +676,12 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) {
log.Warn().Msg("Listening with TLS but ServerURL does not start with https://") log.Warn().Msg("Listening with TLS but ServerURL does not start with https://")
} }
clientAuthMode, err := h.GetClientAuthMode()
if err != nil {
return nil, err
}
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.TLSClientAuthMode))
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
ClientAuth: clientAuthMode, ClientAuth: h.cfg.TLSClientAuthMode,
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,
@ -677,25 +693,6 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) {
} }
} }
// Look up the TLS constant relative to user-supplied TLS client
// authentication mode.
func (h *Headscale) GetClientAuthMode() (tls.ClientAuthType, error) {
switch h.cfg.TLSClientAuthMode {
case DisabledClientAuth:
// Client cert is _not_ required.
return tls.NoClientCert, nil
case RelaxedClientAuth:
// Client cert required, but _not verified_.
return tls.RequireAnyClientCert, nil
case EnforcedClientAuth:
// Client cert is _required and verified_.
return tls.RequireAndVerifyClientCert, nil
default:
return tls.NoClientCert, Error("Invalid tls_client_auth_mode provided: " +
h.cfg.TLSClientAuthMode)
}
}
func (h *Headscale) setLastStateChangeToNow(namespace string) { func (h *Headscale) setLastStateChangeToNow(namespace string) {
now := time.Now().UTC() now := time.Now().UTC()
lastStateUpdate.WithLabelValues("", "headscale").Set(float64(now.Unix())) lastStateUpdate.WithLabelValues("", "headscale").Set(float64(now.Unix()))

Binary file not shown.

View file

@ -30,6 +30,7 @@ const (
) )
func LoadConfig(path string) error { func LoadConfig(path string) error {
viper.SetConfigName("config") viper.SetConfigName("config")
if path == "" { if path == "" {
viper.AddConfigPath("/etc/headscale/") viper.AddConfigPath("/etc/headscale/")
@ -87,9 +88,15 @@ func LoadConfig(path string) error {
errorText += "Fatal config error: server_url must start with https:// or http://\n" errorText += "Fatal config error: server_url must start with https:// or http://\n"
} }
clientAuthMode := viper.GetString("tls_client_auth_mode") _, authModeValid := headscale.LookupTLSClientAuthMode(viper.GetString("tls_client_auth_mode"))
if clientAuthMode != "disabled" && clientAuthMode != "relaxed" && clientAuthMode != "enforced" {
errorText += "Invalid tls_client_auth_mode supplied. Accepted values: disabled, relaxed, enforced." if !authModeValid {
errorText += fmt.Sprintf(
"Invalid tls_client_auth_mode supplied: %s. Accepted values: %s, %s, %s.",
viper.GetString("tls_client_auth_mode"),
headscale.DisabledClientAuth,
headscale.RelaxedClientAuth,
headscale.EnforcedClientAuth)
} }
if errorText != "" { if errorText != "" {
@ -280,6 +287,8 @@ func getHeadscaleConfig() headscale.Config {
log.Warn().Msgf("'ip_prefixes' not configured, falling back to default: %v", prefixes) log.Warn().Msgf("'ip_prefixes' not configured, falling back to default: %v", prefixes)
} }
tlsClientAuthMode, _ := headscale.LookupTLSClientAuthMode(viper.GetString("tls_client_auth_mode"))
return headscale.Config{ return headscale.Config{
ServerURL: viper.GetString("server_url"), ServerURL: viper.GetString("server_url"),
Addr: viper.GetString("listen_addr"), Addr: viper.GetString("listen_addr"),
@ -310,7 +319,7 @@ func getHeadscaleConfig() headscale.Config {
TLSCertPath: absPath(viper.GetString("tls_cert_path")), TLSCertPath: absPath(viper.GetString("tls_cert_path")),
TLSKeyPath: absPath(viper.GetString("tls_key_path")), TLSKeyPath: absPath(viper.GetString("tls_key_path")),
TLSClientAuthMode: viper.GetString("tls_client_auth_mode"), TLSClientAuthMode: tlsClientAuthMode,
DNSConfig: dnsConfig, DNSConfig: dnsConfig,

View file

@ -97,7 +97,7 @@ tls_letsencrypt_hostname: ""
# - disabled: client authentication disabled # - disabled: client authentication disabled
# - relaxed: client certificate is required but not verified # - relaxed: client certificate is required but not verified
# - enforced: client certificate is required and verified # - enforced: client certificate is required and verified
tls_client_auth_mode: disabled tls_client_auth_mode: relaxed
# Path to store certificates and metadata needed by # Path to store certificates and metadata needed by
# letsencrypt # letsencrypt

View file

@ -33,7 +33,7 @@ tls_key_path: ""
### Configuring Mutual TLS Authentication (mTLS) ### Configuring Mutual TLS Authentication (mTLS)
mTLS is a method by which an HTTPS server authenticates clients, e.g. Tailscale, mTLS is a method by which an HTTPS server authenticates clients, e.g. Tailscale,
using TLS certificates. The capability can be configured by by applying one of using TLS certificates. The capability can be configured by applying one of
the following values to the `tls_client_auth_mode` setting in the configuration the following values to the `tls_client_auth_mode` setting in the configuration
file. file.