Add auth over ALPN (#5)

This commit is contained in:
Jeff Mitchell authored and GitHub committed 2020-03-22 20:17:23 -04:00
1 parent 5acda6a0b1
commit cad3c24f54
11 files changed
+278 -234

No files matched your search

+14 -3
View File
@@ -93,15 +93,26 @@ func (c *Controller) startListeners() error {
}
configureForCluster := func(ln *base.ServerListener) error {
l, err := ln.Mux.RegisterProto("watchtower-worker-v1", &tls.Config{
l, err := ln.Mux.RegisterProto(alpnmux.DefaultProto, &tls.Config{
GetConfigForClient: c.validateWorkerTLS,
})
if err != nil {
return fmt.Errorf("error getting sub-listener for worker proto: %w", err)
}
ln.ALPNListener = l
// TODO: Pass this to a handler, e.g. a grpc server
_ = l
// TODO: Pass this to a handler, e.g. a grpc server, in the mean time
// just accepting what comes
go func() {
for {
conn, err := ln.ALPNListener.Accept()
if err != nil {
c.conf.Logger.Info("default alpn listener errored, exiting")
return
}
conn.Close()
}
}()
return nil
}
@@ -1,7 +1,77 @@
package controller
import "crypto/tls"
import (
"context"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"encoding/json"
"errors"
"strings"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/watchtower/internal/cmd/base"
"google.golang.org/protobuf/proto"
)
func (c Controller) validateWorkerTLS(hello *tls.ClientHelloInfo) (*tls.Config, error) {
for _, p := range hello.SupportedProtos {
switch {
case strings.HasPrefix(p, "v1workerauth-"):
return c.v1WorkerAuthConfig(hello.SupportedProtos)
}
}
return nil, nil
}
func (c Controller) v1WorkerAuthConfig(protos []string) (*tls.Config, error) {
var firstMatchProto string
var encString string
for _, p := range protos {
if strings.HasPrefix(p, "v1workerauth-") {
// Strip that and the number
encString += strings.TrimPrefix(p, "v1workerauth-")[3:]
if firstMatchProto == "" {
firstMatchProto = p
}
}
}
if firstMatchProto == "" {
return nil, errors.New("no matching proto found")
}
marshaledEncInfo, err := base64.RawStdEncoding.DecodeString(encString)
if err != nil {
return nil, err
}
encInfo := new(wrapping.EncryptedBlobInfo)
if err := proto.Unmarshal(marshaledEncInfo, encInfo); err != nil {
return nil, err
}
marshaledInfo, err := c.conf.WorkerAuthKMS.Decrypt(context.Background(), encInfo, nil)
if err != nil {
return nil, err
}
info := new(base.WorkerAuthCertInfo)
if err := json.Unmarshal(marshaledInfo, info); err != nil {
return nil, err
}
rootCAs := x509.NewCertPool()
if ok := rootCAs.AppendCertsFromPEM(info.CACertPEM); !ok {
return nil, errors.New("unable to add ca cert to cert pool")
}
tlsCert, err := tls.X509KeyPair(info.CertPEM, info.KeyPEM)
if err != nil {
return nil, err
}
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{tlsCert},
ClientCAs: rootCAs,
ClientAuth: tls.RequireAndVerifyClientCert,
NextProtos: []string{firstMatchProto},
MinVersion: tls.VersionTLS13,
}
tlsConfig.BuildNameToCertificate()
return tlsConfig, nil
}