Skip to content

Commit

Permalink
security: Implemented certificate revocation list
Browse files Browse the repository at this point in the history
  • Loading branch information
kayrus committed Jul 18, 2016
1 parent dcd1a8e commit 0d47908
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 3 deletions.
35 changes: 33 additions & 2 deletions embed/etcd.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,18 @@ package embed

import (
"crypto/tls"
"errors"
"fmt"
"net"
"net/http"
"path"

"github.com/cloudflare/cfssl/revoke"
"github.com/coreos/etcd/etcdserver"
"github.com/coreos/etcd/etcdserver/api/v2http"
"github.com/coreos/etcd/pkg/cors"
runtimeutil "github.com/coreos/etcd/pkg/runtime"
"github.com/coreos/etcd/pkg/tlsutil"
"github.com/coreos/etcd/pkg/transport"
"github.com/coreos/etcd/pkg/types"
"github.com/coreos/etcd/rafthttp"
Expand Down Expand Up @@ -272,6 +275,27 @@ func startClientListeners(cfg *Config) (sctxs map[string]*serveCtx, err error) {
return sctxs, nil
}

func revokeCheckHandler(req *http.Request, CRLpath string) error {
if req.TLS == nil {
return nil
}
for _, cert := range req.TLS.PeerCertificates {
var revoked, ok bool
if CRLpath != "" {
revoked, ok = revoke.VerifyCertificateByCRLPath(cert, CRLpath)
} else {
revoked, ok = revoke.VerifyCertificate(cert)
}
if !ok {
return errors.New("Cert check failed")
}
if revoked {
return errors.New("Cert if revoked")
}
}
return nil
}

func (e *Etcd) serve() (err error) {
var ctlscfg *tls.Config
if !e.cfg.ClientTLSInfo.Empty() {
Expand All @@ -286,16 +310,23 @@ func (e *Etcd) serve() (err error) {
}

// Start the peer server in a goroutine
ph := v2http.NewPeerHandler(e.Server)
ph := tlsutil.RevocationCheck(
v2http.NewPeerHandler(e.Server),
revokeCheckHandler,
e.cfg.PeerTLSInfo.CRLFile)
for _, l := range e.Peers {
go func(l net.Listener) {
e.errc <- servePeerHTTP(l, ph)
}(l)
}

clientHandler := tlsutil.RevocationCheck(
v2http.NewClientHandler(e.Server, e.Server.Cfg.ReqTimeout()),
revokeCheckHandler,
e.cfg.ClientTLSInfo.CRLFile)
// Start a client server goroutine for each listen address
ch := http.Handler(&cors.CORSHandler{
Handler: v2http.NewClientHandler(e.Server, e.Server.Cfg.ReqTimeout()),
Handler: clientHandler,
Info: e.cfg.CorsInfo,
})
for _, sctx := range e.sctxs {
Expand Down
2 changes: 2 additions & 0 deletions etcdmain/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,14 @@ func newConfig() *config {
fs.StringVar(&cfg.ClientTLSInfo.KeyFile, "key-file", "", "Path to the client server TLS key file.")
fs.BoolVar(&cfg.ClientTLSInfo.ClientCertAuth, "client-cert-auth", false, "Enable client cert authentication.")
fs.StringVar(&cfg.ClientTLSInfo.TrustedCAFile, "trusted-ca-file", "", "Path to the client server TLS trusted CA key file.")
fs.StringVar(&cfg.ClientTLSInfo.CRLFile, "crl-file", "", "Path to the client server certificate revocation list file.")
fs.BoolVar(&cfg.ClientAutoTLS, "auto-tls", false, "Client TLS using generated certificates")
fs.StringVar(&cfg.PeerTLSInfo.CAFile, "peer-ca-file", "", "DEPRECATED: Path to the peer server TLS CA file.")
fs.StringVar(&cfg.PeerTLSInfo.CertFile, "peer-cert-file", "", "Path to the peer server TLS cert file.")
fs.StringVar(&cfg.PeerTLSInfo.KeyFile, "peer-key-file", "", "Path to the peer server TLS key file.")
fs.BoolVar(&cfg.PeerTLSInfo.ClientCertAuth, "peer-client-cert-auth", false, "Enable peer client cert authentication.")
fs.StringVar(&cfg.PeerTLSInfo.TrustedCAFile, "peer-trusted-ca-file", "", "Path to the peer server TLS trusted CA file.")
fs.StringVar(&cfg.PeerTLSInfo.CRLFile, "peer-crl-file", "", "Path to the peer server certificate revocation list file.")
fs.BoolVar(&cfg.PeerAutoTLS, "peer-auto-tls", false, "Peer TLS using generated certificates")

// logging
Expand Down
4 changes: 4 additions & 0 deletions etcdmain/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ security flags:
enable client cert authentication.
--trusted-ca-file ''
path to the client server TLS trusted CA key file.
--crl-file ''
path to the client server certificate revocation list file.
--auto-tls 'false'
client TLS using generated certificates.
--peer-ca-file '' [DEPRECATED]
Expand All @@ -130,6 +132,8 @@ security flags:
enable peer client cert authentication.
--peer-trusted-ca-file ''
path to the peer server TLS trusted CA file.
--peer-crl-file ''
path to the peer server certificate revocation list file.
--peer-auto-tls 'false'
peer TLS using self-generated certificates if --peer-key-file and --peer-cert-file are not provided.
Expand Down
17 changes: 17 additions & 0 deletions pkg/tlsutil/tlsutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ import (
"crypto/tls"
"crypto/x509"
"encoding/pem"
"fmt"
"io/ioutil"
"net/http"

etcdErr "github.com/coreos/etcd/error"
)

// NewCertPool creates x509 certPool with provided CA files.
Expand Down Expand Up @@ -70,3 +74,16 @@ func NewCert(certfile, keyfile string, parseFunc func([]byte, []byte) (tls.Certi
}
return &tlsCert, nil
}

func RevocationCheck(handler http.Handler, checker func(*http.Request, string) error, CRLpath string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
err := checker(req, CRLpath)
if err == nil {
handler.ServeHTTP(w, req)
return
}
w.WriteHeader(http.StatusForbidden)
e := etcdErr.NewError(etcdErr.EcodeUnauthorized, fmt.Sprint(err), 0)
e.WriteTo(w)
})
}
3 changes: 2 additions & 1 deletion pkg/transport/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ type TLSInfo struct {
KeyFile string
CAFile string
TrustedCAFile string
CRLFile string
ClientCertAuth bool

selfCert bool
Expand All @@ -72,7 +73,7 @@ type TLSInfo struct {
}

func (info TLSInfo) String() string {
return fmt.Sprintf("cert = %s, key = %s, ca = %s, trusted-ca = %s, client-cert-auth = %v", info.CertFile, info.KeyFile, info.CAFile, info.TrustedCAFile, info.ClientCertAuth)
return fmt.Sprintf("cert = %s, key = %s, ca = %s, trusted-ca = %s, cert-auth = %v, crl-file = %s", info.CertFile, info.KeyFile, info.CAFile, info.TrustedCAFile, info.ClientCertAuth, info.CRLFile)
}

func (info TLSInfo) Empty() bool {
Expand Down

0 comments on commit 0d47908

Please sign in to comment.