@@ -20,12 +20,20 @@ import (
2020 "io/ioutil"
2121 "net/http"
2222
23+ "github.com/go-kit/kit/log"
24+ "github.com/go-kit/kit/log/level"
2325 "github.com/pkg/errors"
26+ config_util "github.com/prometheus/common/config"
2427 "gopkg.in/yaml.v2"
2528)
2629
30+ var (
31+ errNoTLSConfig = errors .New ("TLS config is not present" )
32+ )
33+
2734type Config struct {
28- TLSConfig TLSStruct `yaml:"tls_config"`
35+ TLSConfig TLSStruct `yaml:"tls_config"`
36+ Users map [string ]config_util.Secret `yaml:"basic_auth_users"`
2937}
3038
3139type TLSStruct struct {
@@ -35,13 +43,18 @@ type TLSStruct struct {
3543 ClientCAs string `yaml:"client_ca_file"`
3644}
3745
38- func getTLSConfig (configPath string ) (* tls. Config , error ) {
46+ func getConfig (configPath string ) (* Config , error ) {
3947 content , err := ioutil .ReadFile (configPath )
4048 if err != nil {
4149 return nil , err
4250 }
4351 c := & Config {}
44- err = yaml .Unmarshal (content , c )
52+ err = yaml .UnmarshalStrict (content , c )
53+ return c , err
54+ }
55+
56+ func getTLSConfig (configPath string ) (* tls.Config , error ) {
57+ c , err := getConfig (configPath )
4558 if err != nil {
4659 return nil , err
4760 }
@@ -50,14 +63,18 @@ func getTLSConfig(configPath string) (*tls.Config, error) {
5063
5164// ConfigToTLSConfig generates the golang tls.Config from the TLSStruct config.
5265func ConfigToTLSConfig (c * TLSStruct ) (* tls.Config , error ) {
53- cfg := & tls. Config {
54- MinVersion : tls . VersionTLS12 ,
66+ if c . TLSCertPath == "" && c . TLSKeyPath == "" && c . ClientAuth == "" && c . ClientCAs == "" {
67+ return nil , errNoTLSConfig
5568 }
56- if len (c .TLSCertPath ) == 0 {
57- return nil , errors .New ("missing TLSCertPath" )
69+
70+ if c .TLSCertPath == "" {
71+ return nil , errors .New ("missing cert_file" )
5872 }
59- if len (c .TLSKeyPath ) == 0 {
60- return nil , errors .New ("missing TLSKeyPath" )
73+ if c .TLSKeyPath == "" {
74+ return nil , errors .New ("missing key_file" )
75+ }
76+ cfg := & tls.Config {
77+ MinVersion : tls .VersionTLS12 ,
6178 }
6279 loadCert := func () (* tls.Certificate , error ) {
6380 cert , err := tls .LoadX509KeyPair (c .TLSCertPath , c .TLSKeyPath )
@@ -74,7 +91,7 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) {
7491 return loadCert ()
7592 }
7693
77- if len ( c .ClientCAs ) > 0 {
94+ if c .ClientCAs != "" {
7895 clientCAPool := x509 .NewCertPool ()
7996 clientCAFile , err := ioutil .ReadFile (c .ClientCAs )
8097 if err != nil {
@@ -83,40 +100,67 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) {
83100 clientCAPool .AppendCertsFromPEM (clientCAFile )
84101 cfg .ClientCAs = clientCAPool
85102 }
86- if len (c .ClientAuth ) > 0 {
87- switch s := (c .ClientAuth ); s {
88- case "NoClientCert" :
89- cfg .ClientAuth = tls .NoClientCert
90- case "RequestClientCert" :
91- cfg .ClientAuth = tls .RequestClientCert
92- case "RequireClientCert" :
93- cfg .ClientAuth = tls .RequireAnyClientCert
94- case "VerifyClientCertIfGiven" :
95- cfg .ClientAuth = tls .VerifyClientCertIfGiven
96- case "RequireAndVerifyClientCert" :
97- cfg .ClientAuth = tls .RequireAndVerifyClientCert
98- case "" :
99- cfg .ClientAuth = tls .NoClientCert
100- default :
101- return nil , errors .New ("Invalid ClientAuth: " + s )
102- }
103+
104+ switch c .ClientAuth {
105+ case "RequestClientCert" :
106+ cfg .ClientAuth = tls .RequestClientCert
107+ case "RequireClientCert" :
108+ cfg .ClientAuth = tls .RequireAnyClientCert
109+ case "VerifyClientCertIfGiven" :
110+ cfg .ClientAuth = tls .VerifyClientCertIfGiven
111+ case "RequireAndVerifyClientCert" :
112+ cfg .ClientAuth = tls .RequireAndVerifyClientCert
113+ case "" , "NoClientCert" :
114+ cfg .ClientAuth = tls .NoClientCert
115+ default :
116+ return nil , errors .New ("Invalid ClientAuth: " + c .ClientAuth )
103117 }
104- if len (c .ClientCAs ) > 0 && cfg .ClientAuth == tls .NoClientCert {
118+
119+ if c .ClientCAs != "" && cfg .ClientAuth == tls .NoClientCert {
105120 return nil , errors .New ("Client CA's have been configured without a Client Auth Policy" )
106121 }
122+
107123 return cfg , nil
108124}
109125
110126// Listen starts the server on the given address. If tlsConfigPath isn't empty the server connection will be started using TLS.
111- func Listen (server * http.Server , tlsConfigPath string ) error {
112- if (tlsConfigPath ) == "" {
127+ func Listen (server * http.Server , tlsConfigPath string , logger log.Logger ) error {
128+ if tlsConfigPath == "" {
129+ level .Info (logger ).Log ("msg" , "TLS is disabled and it cannot be enabled on the fly." )
113130 return server .ListenAndServe ()
114131 }
115- var err error
116- server .TLSConfig , err = getTLSConfig (tlsConfigPath )
117- if err != nil {
132+
133+ if err := validateUsers (tlsConfigPath ); err != nil {
118134 return err
119135 }
136+
137+ // Setup basic authentication.
138+ var handler http.Handler = http .DefaultServeMux
139+ if server .Handler != nil {
140+ handler = server .Handler
141+ }
142+ server .Handler = & userAuthRoundtrip {
143+ tlsConfigPath : tlsConfigPath ,
144+ logger : logger ,
145+ handler : handler ,
146+ }
147+
148+ config , err := getTLSConfig (tlsConfigPath )
149+ switch err {
150+ case nil :
151+ // Valid TLS config.
152+ level .Info (logger ).Log ("msg" , "TLS is enabled and it cannot be disabled on the fly." )
153+ case errNoTLSConfig :
154+ // No TLS config, back to plain HTTP.
155+ level .Info (logger ).Log ("msg" , "TLS is disabled and it cannot be enabled on the fly." )
156+ return server .ListenAndServe ()
157+ default :
158+ // Invalid TLS config.
159+ return err
160+ }
161+
162+ server .TLSConfig = config
163+
120164 // Set the GetConfigForClient method of the HTTPS server so that the config
121165 // and certs are reloaded on new connections.
122166 server .TLSConfig .GetConfigForClient = func (* tls.ClientHelloInfo ) (* tls.Config , error ) {
0 commit comments