mirror of
https://github.com/zrepl/zrepl.git
synced 2025-06-19 17:27:46 +02:00
serve TLS: validate client CNs against whitelist in config file
This commit is contained in:
parent
1edf020ce7
commit
7836ea36fc
@ -3,6 +3,7 @@ package serve
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
"fmt"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/zrepl/zrepl/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/tlsconf"
|
"github.com/zrepl/zrepl/tlsconf"
|
||||||
@ -16,6 +17,7 @@ type TLSListenerFactory struct {
|
|||||||
clientCA *x509.CertPool
|
clientCA *x509.CertPool
|
||||||
serverCert tls.Certificate
|
serverCert tls.Certificate
|
||||||
handshakeTimeout time.Duration
|
handshakeTimeout time.Duration
|
||||||
|
clientCNs map[string]struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TLSListenerFactoryFromConfig(c *config.Global, in *config.TLSServe) (lf *TLSListenerFactory, err error) {
|
func TLSListenerFactoryFromConfig(c *config.Global, in *config.TLSServe) (lf *TLSListenerFactory, err error) {
|
||||||
@ -38,6 +40,15 @@ func TLSListenerFactoryFromConfig(c *config.Global, in *config.TLSServe) (lf *TL
|
|||||||
return nil, errors.Wrap(err, "cannot parse cer/key pair")
|
return nil, errors.Wrap(err, "cannot parse cer/key pair")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lf.clientCNs = make(map[string]struct{}, len(in.ClientCNs))
|
||||||
|
for i, cn := range in.ClientCNs {
|
||||||
|
if err := ValidateClientIdentity(cn); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "unsuitable client_cn #%d %q", i, cn)
|
||||||
|
}
|
||||||
|
// dupes are ok fr now
|
||||||
|
lf.clientCNs[cn] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
return lf, nil
|
return lf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,11 +58,12 @@ func (f *TLSListenerFactory) Listen() (AuthenticatedListener, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tl := tlsconf.NewClientAuthListener(l, f.clientCA, f.serverCert, f.handshakeTimeout)
|
tl := tlsconf.NewClientAuthListener(l, f.clientCA, f.serverCert, f.handshakeTimeout)
|
||||||
return tlsAuthListener{tl}, nil
|
return tlsAuthListener{tl, f.clientCNs}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type tlsAuthListener struct {
|
type tlsAuthListener struct {
|
||||||
*tlsconf.ClientAuthListener
|
*tlsconf.ClientAuthListener
|
||||||
|
clientCNs map[string]struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l tlsAuthListener) Accept(ctx context.Context) (AuthenticatedConn, error) {
|
func (l tlsAuthListener) Accept(ctx context.Context) (AuthenticatedConn, error) {
|
||||||
@ -59,6 +71,12 @@ func (l tlsAuthListener) Accept(ctx context.Context) (AuthenticatedConn, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if _, ok := l.clientCNs[cn]; !ok {
|
||||||
|
if err := c.Close(); err != nil {
|
||||||
|
getLogger(ctx).WithError(err).Error("error closing connection with unauthorized common name")
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("unauthorized client common name %q from %s", cn, c.RemoteAddr())
|
||||||
|
}
|
||||||
return authConn{c, cn}, nil
|
return authConn{c, cn}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user