Use common TLS parsing routine for etcd (#476)

* Use common TLS parsing routine for etcd

Change to use the new common routine, and update the docs to reflect
the different options for passing TLS configuration.

* Move middleware/tls to middleware/pkg/tls

This was put in the wrong place originally.
This commit is contained in:
John Belamaric 2017-01-12 03:14:24 -05:00 committed by Miek Gieben
parent 94c59da577
commit 2e366459c5
5 changed files with 26 additions and 37 deletions

View file

@ -39,7 +39,11 @@ etcd [ZONES...] {
pointing to external names. If you want CoreDNS to act as a proxy for clients, you'll need to add pointing to external names. If you want CoreDNS to act as a proxy for clients, you'll need to add
the proxy middleware. **ADDRESS** can be an IP address, and IP:port or a string pointing to a file the proxy middleware. **ADDRESS** can be an IP address, and IP:port or a string pointing to a file
that is structured as /etc/resolv.conf. that is structured as /etc/resolv.conf.
* `tls` followed the cert, key and the CA's cert filenames. * `tls` followed by:
* no arguments, if the server certificate is signed by a system-installed CA and no client cert is needed
* a single argument that is the CA PEM file, if the server cert is not signed by a system CA and no client cert is needed
* two arguments - path to cert PEM file, the path to private key PEM file - if the server certificate is signed by a system-installed CA and a client certificate is needed
* three arguments - path to cert PEM file, path to client private key PEM file, path to CA PEM file - if the server certificate is not signed by a system-installed CA and client certificate is needed
* `debug` allows for debug queries. Prefix the name with `o-o.debug.` to retrieve extra information in the * `debug` allows for debug queries. Prefix the name with `o-o.debug.` to retrieve extra information in the
additional section of the reply in the form of TXT records. additional section of the reply in the form of TXT records.

View file

@ -2,8 +2,6 @@ package etcd
import ( import (
"crypto/tls" "crypto/tls"
"crypto/x509"
"io/ioutil"
"net" "net"
"net/http" "net/http"
"time" "time"
@ -12,6 +10,7 @@ import (
"github.com/miekg/coredns/middleware" "github.com/miekg/coredns/middleware"
"github.com/miekg/coredns/middleware/pkg/dnsutil" "github.com/miekg/coredns/middleware/pkg/dnsutil"
"github.com/miekg/coredns/middleware/pkg/singleflight" "github.com/miekg/coredns/middleware/pkg/singleflight"
mwtls "github.com/miekg/coredns/middleware/pkg/tls"
"github.com/miekg/coredns/middleware/proxy" "github.com/miekg/coredns/middleware/proxy"
etcdc "github.com/coreos/etcd/client" etcdc "github.com/coreos/etcd/client"
@ -57,9 +56,8 @@ func etcdParse(c *caddy.Controller) (*Etcd, bool, error) {
Stubmap: &stub, Stubmap: &stub,
} }
var ( var (
tlsCertFile = "" tlsConfig *tls.Config
tlsKeyFile = "" err error
tlsCAcertFile = ""
endpoints = []string{defaultEndpoint} endpoints = []string{defaultEndpoint}
stubzones = false stubzones = false
) )
@ -101,10 +99,10 @@ func etcdParse(c *caddy.Controller) (*Etcd, bool, error) {
etc.Proxy = proxy.New(ups) etc.Proxy = proxy.New(ups)
case "tls": // cert key cacertfile case "tls": // cert key cacertfile
args := c.RemainingArgs() args := c.RemainingArgs()
if len(args) != 3 { tlsConfig, err = mwtls.NewTLSConfigFromArgs(args...)
return &Etcd{}, false, c.ArgErr() if err != nil {
return &Etcd{}, false, err
} }
tlsCertFile, tlsKeyFile, tlsCAcertFile = args[0], args[1], args[2]
default: default:
if c.Val() != "}" { if c.Val() != "}" {
return &Etcd{}, false, c.Errf("unknown property '%s'", c.Val()) return &Etcd{}, false, c.Errf("unknown property '%s'", c.Val())
@ -139,10 +137,10 @@ func etcdParse(c *caddy.Controller) (*Etcd, bool, error) {
etc.Proxy = proxy.New(ups) etc.Proxy = proxy.New(ups)
case "tls": // cert key cacertfile case "tls": // cert key cacertfile
args := c.RemainingArgs() args := c.RemainingArgs()
if len(args) != 3 { tlsConfig, err = mwtls.NewTLSConfigFromArgs(args...)
return &Etcd{}, false, c.ArgErr() if err != nil {
return &Etcd{}, false, err
} }
tlsCertFile, tlsKeyFile, tlsCAcertFile = args[0], args[1], args[2]
default: default:
if c.Val() != "}" { // TODO(miek): this feels like I'm doing it completely wrong. if c.Val() != "}" { // TODO(miek): this feels like I'm doing it completely wrong.
return &Etcd{}, false, c.Errf("unknown property '%s'", c.Val()) return &Etcd{}, false, c.Errf("unknown property '%s'", c.Val())
@ -151,7 +149,7 @@ func etcdParse(c *caddy.Controller) (*Etcd, bool, error) {
} }
} }
client, err := newEtcdClient(endpoints, tlsCertFile, tlsKeyFile, tlsCAcertFile) client, err := newEtcdClient(endpoints, tlsConfig)
if err != nil { if err != nil {
return &Etcd{}, false, err return &Etcd{}, false, err
} }
@ -164,10 +162,10 @@ func etcdParse(c *caddy.Controller) (*Etcd, bool, error) {
return &Etcd{}, false, nil return &Etcd{}, false, nil
} }
func newEtcdClient(endpoints []string, tlsCert, tlsKey, tlsCACert string) (etcdc.KeysAPI, error) { func newEtcdClient(endpoints []string, cc *tls.Config) (etcdc.KeysAPI, error) {
etcdCfg := etcdc.Config{ etcdCfg := etcdc.Config{
Endpoints: endpoints, Endpoints: endpoints,
Transport: newHTTPSTransport(tlsCert, tlsKey, tlsCACert), Transport: newHTTPSTransport(cc),
} }
cli, err := etcdc.New(etcdCfg) cli, err := etcdc.New(etcdCfg)
if err != nil { if err != nil {
@ -176,25 +174,10 @@ func newEtcdClient(endpoints []string, tlsCert, tlsKey, tlsCACert string) (etcdc
return etcdc.NewKeysAPI(cli), nil return etcdc.NewKeysAPI(cli), nil
} }
func newHTTPSTransport(tlsCertFile, tlsKeyFile, tlsCACertFile string) etcdc.CancelableTransport { func newHTTPSTransport(cc *tls.Config) etcdc.CancelableTransport {
var cc *tls.Config // this seems like a bad idea but was here in the previous version
if cc != nil {
if tlsCertFile != "" && tlsKeyFile != "" { cc.InsecureSkipVerify = true
var rpool *x509.CertPool
if tlsCACertFile != "" {
if pemBytes, err := ioutil.ReadFile(tlsCACertFile); err == nil {
rpool = x509.NewCertPool()
rpool.AppendCertsFromPEM(pemBytes)
}
}
if tlsCert, err := tls.LoadX509KeyPair(tlsCertFile, tlsKeyFile); err == nil {
cc = &tls.Config{
RootCAs: rpool,
Certificates: []tls.Certificate{tlsCert},
InsecureSkipVerify: true,
}
}
} }
tr := &http.Transport{ tr := &http.Transport{

View file

@ -14,6 +14,7 @@ import (
"github.com/miekg/coredns/middleware/pkg/singleflight" "github.com/miekg/coredns/middleware/pkg/singleflight"
"github.com/miekg/coredns/middleware/proxy" "github.com/miekg/coredns/middleware/proxy"
"github.com/miekg/coredns/middleware/test" "github.com/miekg/coredns/middleware/test"
"github.com/miekg/coredns/middleware/pkg/tls"
etcdc "github.com/coreos/etcd/client" etcdc "github.com/coreos/etcd/client"
"github.com/mholt/caddy" "github.com/mholt/caddy"
@ -28,7 +29,8 @@ func newEtcdMiddleware() *Etcd {
ctxt, _ = context.WithTimeout(context.Background(), etcdTimeout) ctxt, _ = context.WithTimeout(context.Background(), etcdTimeout)
endpoints := []string{"http://localhost:2379"} endpoints := []string{"http://localhost:2379"}
client, _ := newEtcdClient(endpoints, "", "", "") tlsc, _ := tls.NewTLSConfigFromArgs()
client, _ := newEtcdClient(endpoints, tlsc)
return &Etcd{ return &Etcd{
Proxy: proxy.New([]string{"8.8.8.8:53"}), Proxy: proxy.New([]string{"8.8.8.8:53"}),