diff --git a/core/setup/etcd.go b/core/setup/etcd.go index 76aed5249..63e5bf8b2 100644 --- a/core/setup/etcd.go +++ b/core/setup/etcd.go @@ -1,36 +1,42 @@ package setup import ( - "log" - "os" + "crypto/tls" + "crypto/x509" + "io/ioutil" + "net" + "net/http" + "time" + etcdc "github.com/coreos/etcd/client" "github.com/miekg/coredns/middleware" "github.com/miekg/coredns/middleware/file" - "github.com/miekg/dns" ) -// File sets up the file middleware. -func File(c *Controller) (middleware.Middleware, error) { - zones, err := fileParse(c) +const defaultAddress = "http://127.0.0.1:2379" + +// Etcd sets up the etcd middleware. +func Etcd(c *Controller) (middleware.Middleware, error) { + keysapi, err := etcdParse(c) if err != nil { return nil, err } + return func(next middleware.Handler) middleware.Handler { return file.File{Next: next, Zones: zones} }, nil } -func fileParse(c *Controller) (file.Zones, error) { - // Maybe multiple, each for each zone. - z := make(map[string]file.Zone) - names := []string{} +func etcdParse(c *Controller) (etcdc.KeysAPI, error) { for c.Next() { - if c.Val() == "file" { - // file db.file [origin] + if c.Val() == "etcd" { + // etcd [address...] if !c.NextArg() { + return file.Zones{}, c.ArgErr() } + args1 := c.RemainingArgs() fileName := c.Val() origin := c.ServerBlockHosts[c.ServerBlockHostIndex] @@ -51,23 +57,48 @@ func fileParse(c *Controller) (file.Zones, error) { return file.Zones{Z: z, Names: names}, nil } -// -// parsrZone parses the zone in filename and returns a []RR or an error. -func parseZone(origin, fileName string) (file.Zone, error) { - f, err := os.Open(fileName) +func newEtcdClient(machines []string, tlsCert, tlsKey, tlsCACert string) (etcd.KeysAPI, error) { + etcdCfg := etcd.Config{ + Endpoints: machines, + Transport: newHTTPSTransport(tlsCert, tlsKey, tlsCACert), + } + cli, err := etcd.New(etcdCfg) if err != nil { return nil, err } - tokens := dns.ParseZone(f, origin, fileName) - zone := make([]dns.RR, 0, defaultZoneSize) - for x := range tokens { - if x.Error != nil { - log.Printf("[ERROR] failed to parse %s: %v", origin, x.Error) - return nil, x.Error - } - zone = append(zone, x.RR) - } - return file.Zone(zone), nil + return etcd.NewKeysAPI(cli), nil } -const defaultZoneSize = 20 // A made up number. +func newHTTPSTransport(tlsCertFile, tlsKeyFile, tlsCACertFile string) etcd.CancelableTransport { + var cc *tls.Config = nil + + if tlsCertFile != "" && tlsKeyFile != "" { + 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{ + Proxy: http.ProxyFromEnvironment, + Dial: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).Dial, + TLSHandshakeTimeout: 10 * time.Second, + TLSClientConfig: cc, + } + + return tr +} diff --git a/middleware/etcd/etcd.go b/middleware/etcd/etcd.go index 9f179228e..f7aa60a71 100644 --- a/middleware/etcd/etcd.go +++ b/middleware/etcd/etcd.go @@ -3,9 +3,10 @@ package etcd import ( "github.com/miekg/coredns/middleware" + "github.com/miekg/dns" "github.com/skynetservices/skydns/singleflight" - etcd "github.com/coreos/etcd/client" + etcdc "github.com/coreos/etcd/client" "golang.org/x/net/context" ) @@ -19,10 +20,15 @@ type ( } ) -func NewEtcd(client etcd.KeysAPI, ctx context.Context) Etcd { +func NewEtcd(client etcdc.KeysAPI, next middleware.Handler) Etcd { return Etcd{ + Next: next, client: client, - ctx: ctx, + ctx: context.Background(), inflight: &singleflight.Group{}, } } + +func (e Etcd) ServerDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { + return 0, nil +} diff --git a/middleware/etcd/etcd.md b/middleware/etcd/etcd.md index 60f53e9be..e5489298c 100644 --- a/middleware/etcd/etcd.md +++ b/middleware/etcd/etcd.md @@ -7,10 +7,10 @@ like SkyDNS. ## Syntax ~~~ -etcd [address...] +etcd [endpoint...] ~~~ -* `address` is the endpoint of etcd. +* `endpoint` is the endpoint of etcd. The will default to `/skydns` as the path and the local etcd proxy (http://127.0.0.1:2379). @@ -18,9 +18,14 @@ The will default to `/skydns` as the path and the local etcd proxy (http://127.0 etcd { round_robin path /skydns - address address... + endpoint address... stubzones } ~~~ +* `round_robin` +* `path` /skydns +* `endpoint` address... +* `stubzones` + ## Examples