From c8f3800f1cacb2a812fe467116c224b83709093b Mon Sep 17 00:00:00 2001 From: Simon Thulbourn Date: Fri, 20 Mar 2015 15:19:07 +0000 Subject: [PATCH] Add client certificate CA option to authenticate with client certs Add the ability to authenticate against multiple client CA certificates. Signed-off-by: Simon Thulbourn --- cmd/registry/main.go | 37 ++++++++++++++++++++++++++++- configuration/configuration.go | 4 ++++ configuration/configuration_test.go | 24 +++++++++++++++++++ doc/configuration.md | 7 ++++++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/cmd/registry/main.go b/cmd/registry/main.go index 6c442895..ab14990b 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" @@ -67,8 +70,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 6c03b27f..4bfbf9df 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -57,6 +57,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 5a6abf90..c5041487 100644 --- a/configuration/configuration_test.go +++ b/configuration/configuration_test.go @@ -52,6 +52,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 @@ -82,6 +103,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 f9cbf197..b431869d 100644 --- a/doc/configuration.md +++ b/doc/configuration.md @@ -62,6 +62,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: @@ -260,6 +263,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 ``` @@ -276,6 +282,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