diff --git a/cmd/registry/main.go b/cmd/registry/main.go index 5708a285e..3c7fb4dad 100644 --- a/cmd/registry/main.go +++ b/cmd/registry/main.go @@ -1,9 +1,12 @@ package main import ( + "crypto/tls" + "crypto/x509" _ "expvar" "flag" "fmt" + "io/ioutil" "net/http" _ "net/http/pprof" "os" @@ -69,8 +72,40 @@ func main() { ctxu.GetLogger(app).Fatalln(err) } } else { + tlsConf := &tls.Config{ + ClientAuth: tls.NoClientCert, + } + + if len(config.HTTP.TLS.ClientCAs) != 0 { + pool := x509.NewCertPool() + + for _, ca := range config.HTTP.TLS.ClientCAs { + caPem, err := ioutil.ReadFile(ca) + if err != nil { + ctxu.GetLogger(app).Fatalln(err) + } + + if ok := pool.AppendCertsFromPEM(caPem); !ok { + ctxu.GetLogger(app).Fatalln(fmt.Errorf("Could not add CA to pool")) + } + } + + for _, subj := range pool.Subjects() { + ctxu.GetLogger(app).Debugf("CA Subject: %s", string(subj)) + } + + tlsConf.ClientAuth = tls.RequireAndVerifyClientCert + tlsConf.ClientCAs = pool + } + ctxu.GetLogger(app).Infof("listening on %v, tls", config.HTTP.Addr) - if err := http.ListenAndServeTLS(config.HTTP.Addr, config.HTTP.TLS.Certificate, config.HTTP.TLS.Key, handler); err != nil { + server := &http.Server{ + Addr: config.HTTP.Addr, + Handler: handler, + TLSConfig: tlsConf, + } + + if err := server.ListenAndServeTLS(config.HTTP.TLS.Certificate, config.HTTP.TLS.Key); err != nil { ctxu.GetLogger(app).Fatalln(err) } } diff --git a/configuration/configuration.go b/configuration/configuration.go index add62f50c..5b76d0291 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -73,6 +73,10 @@ type Configuration struct { // contain the private portion for the file specified in // Certificate. Key string `yaml:"key,omitempty"` + + // Specifies the CA certs for client authentication + // A file may contain multiple CA certificates encoded as PEM + ClientCAs []string `yaml:"clientcas,omitempty"` } `yaml:"tls,omitempty"` // Debug configures the http debug interface, if specified. This can diff --git a/configuration/configuration_test.go b/configuration/configuration_test.go index 479245010..ad61519bf 100644 --- a/configuration/configuration_test.go +++ b/configuration/configuration_test.go @@ -59,6 +59,27 @@ var configStruct = Configuration{ }, }, }, + HTTP: struct { + Addr string `yaml:"addr,omitempty"` + Prefix string `yaml:"prefix,omitempty"` + Secret string `yaml:"secret,omitempty"` + TLS struct { + Certificate string `yaml:"certificate,omitempty"` + Key string `yaml:"key,omitempty"` + ClientCAs []string `yaml:"clientcas,omitempty"` + } `yaml:"tls,omitempty"` + Debug struct { + Addr string `yaml:"addr,omitempty"` + } `yaml:"debug,omitempty"` + }{ + TLS: struct { + Certificate string `yaml:"certificate,omitempty"` + Key string `yaml:"key,omitempty"` + ClientCAs []string `yaml:"clientcas,omitempty"` + }{ + ClientCAs: []string{"/path/to/ca.pem"}, + }, + }, } // configYamlV0_1 is a Version 0.1 yaml document representing configStruct @@ -92,6 +113,9 @@ notifications: reporting: bugsnag: apikey: BugsnagApiKey +http: + clientcas: + - /path/to/ca.pem ` // inmemoryConfigYamlV0_1 is a Version 0.1 yaml document specifying an inmemory diff --git a/doc/configuration.md b/doc/configuration.md index a94429b5a..5ac117118 100644 --- a/doc/configuration.md +++ b/doc/configuration.md @@ -68,6 +68,9 @@ http: tls: certificate: /path/to/x509/public key: /path/to/x509/private + clientcas: + - /path/to/ca.pem + - /path/to/another/ca.pem debug: addr: localhost:5001 notifications: @@ -288,6 +291,9 @@ http: tls: certificate: /path/to/x509/public key: /path/to/x509/private + clientcas: + - /path/to/ca.pem + - /path/to/another/ca.pem debug: addr: localhost:5001 ``` @@ -304,6 +310,7 @@ The tls option within http is **optional** and allows you to configure SSL for t - certificate: **Required** - Absolute path to x509 cert file - key: **Required** - Absolute path to x509 private key file +- clientcas: **Optional** - An array of absolute paths to a x509 CA file ### debug