Skip to content

Commit

Permalink
Add ServerName TLS Config; Fix Worker SDK TLS (#396)
Browse files Browse the repository at this point in the history
  • Loading branch information
shawnhathaway authored May 20, 2020
1 parent 4475e40 commit 45d930f
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 27 deletions.
18 changes: 14 additions & 4 deletions cmd/server/temporal/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import (
"github.com/temporalio/temporal/common/primitives"
"github.com/temporalio/temporal/common/resource"
"github.com/temporalio/temporal/common/rpc"
"github.com/temporalio/temporal/common/rpc/encryption"
"github.com/temporalio/temporal/common/service/config"
"github.com/temporalio/temporal/common/service/config/ringpop"
"github.com/temporalio/temporal/common/service/dynamicconfig"
Expand Down Expand Up @@ -124,14 +125,16 @@ func (s *server) startService() common.Daemon {
log.Fatalf("Ringpop config validation error - %v", err)
}

svcCfg := s.cfg.Services[s.name]
params.MetricScope = svcCfg.Metrics.NewScope(params.Logger)
params.RPCFactory, err = rpc.NewFactory(&svcCfg.RPC, params.Name, params.Logger, &s.cfg.Global)
tlsFactory, err := encryption.NewTLSConfigProviderFromConfig(s.cfg.Global.TLS)

if err != nil {
log.Fatalf("error constructing RPC factory: %v", err)
log.Fatalf("error initializing TLS provider: %v", err)
}

svcCfg := s.cfg.Services[s.name]
params.MetricScope = svcCfg.Metrics.NewScope(params.Logger)
params.RPCFactory = rpc.NewFactory(&svcCfg.RPC, params.Name, params.Logger, tlsFactory)

// Ringpop uses a different port to register handlers, this map is needed to resolve
// services to correct addresses used by clients through ServiceResolver lookup API
servicePortMap := make(map[string]int)
Expand Down Expand Up @@ -180,11 +183,18 @@ func (s *server) startService() common.Daemon {
if err != nil {
log.Fatalf("failed to initialize zap logger: %v", err)
}

options, err := tlsFactory.GetFrontendClientConfig()
if err != nil {
log.Fatalf("unable to load frontend tls configuration: %v", err)
}

params.PublicClient, err = sdkclient.NewClient(sdkclient.Options{
HostPort: s.cfg.PublicClient.HostPort,
Namespace: common.SystemLocalNamespace,
MetricsScope: params.MetricScope,
Logger: zapLogger,
ConnectionOptions: sdkclient.ConnectionOptions{ TLS: options },
})
if err != nil {
log.Fatalf("failed to create public client: %v", err)
Expand Down
19 changes: 19 additions & 0 deletions common/rpc/encryption/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"math/big"
mathrand "math/rand"
"net"
"strings"
"time"
)

Expand Down Expand Up @@ -63,6 +64,15 @@ func GenerateSelfSignedX509CA(commonName string, extUsage []x509.ExtKeyUsage, ke

if ip := net.ParseIP(commonName).To4(); ip != nil {
template.IPAddresses = []net.IP{ip}

if ip.IsLoopback() {
template.DNSNames = []string{"localhost"}
}
}

if strings.ToLower(commonName) == "localhost" {
template.IPAddresses = []net.IP{net.IPv6loopback, net.IPv4(127,0 ,0, 1)}
template.DNSNames = []string{"localhost"}
}

privateKey, err := rsa.GenerateKey(rand.Reader, keyLengthBits)
Expand Down Expand Up @@ -103,6 +113,15 @@ func GenerateServerX509UsingCA(commonName string, ca *tls.Certificate) (*tls.Cer

if ip := net.ParseIP(commonName).To4(); ip != nil {
template.IPAddresses = []net.IP{ip}

if ip.IsLoopback() {
template.DNSNames = []string{"localhost"}
}
}

if strings.ToLower(commonName) == "localhost" {
template.IPAddresses = []net.IP{net.IPv6loopback, net.IPv4(127,0 ,0, 1)}
template.DNSNames = []string{"localhost"}
}

privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
Expand Down
10 changes: 5 additions & 5 deletions common/rpc/encryption/localStoreTlsFactory.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ func (s *localStoreTlsProvider) getOrCreateConfig(
localCertProvider CertProvider,
settingsProvider CertProvider,
) (*tls.Config, error) {
if !localCertProvider.GetSettings().IsEnabled() {
return nil, nil
}

// Check if exists under a read lock first
s.RLock()
if *cachedConfig != nil {
Expand Down Expand Up @@ -161,13 +165,9 @@ func newClientTLSConfig(localProvider CertProvider, remoteProvider CertProvider)
clientCerts = []tls.Certificate{*cert}
}

// No client settings
if clientCerts == nil && serverCa == nil {
return nil, nil
}

return &tls.Config{
Certificates: clientCerts,
RootCAs: serverCa,
ServerName: remoteProvider.GetSettings().Client.ServerName,
}, nil
}
2 changes: 1 addition & 1 deletion common/rpc/encryption/tlsFactory.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const (
)

// NewTLSConfigProviderFromConfig creates a new TLS Configuration provider from RootTLS config
func NewTLSConfigProviderFromConfig(encryptionSettings config.RootTLS, hostname string) (TLSConfigProvider, error) {
func NewTLSConfigProviderFromConfig(encryptionSettings config.RootTLS) (TLSConfigProvider, error) {
/* if || encryptionSettings.Provider == "" {
return nil, nil
}
Expand Down
15 changes: 4 additions & 11 deletions common/rpc/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,13 @@ type RPCFactory struct {

// NewFactory builds a new RPCFactory
// conforming to the underlying configuration
func NewFactory(cfg *config.RPC, sName string, logger log.Logger, serverCfg *config.Global) (*RPCFactory, error) {
tlsFactory, err := encryption.NewTLSConfigProviderFromConfig(
serverCfg.TLS,
getBroadcastAddressFromConfig(serverCfg, cfg, logger))

if err != nil {
return nil, err
}
return newFactory(cfg, sName, logger, tlsFactory)
func NewFactory(cfg *config.RPC, sName string, logger log.Logger, tlsProvider encryption.TLSConfigProvider) (*RPCFactory) {
return newFactory(cfg, sName, logger, tlsProvider)
}

func newFactory(cfg *config.RPC, sName string, logger log.Logger, tlsProvider encryption.TLSConfigProvider) (*RPCFactory, error) {
func newFactory(cfg *config.RPC, sName string, logger log.Logger, tlsProvider encryption.TLSConfigProvider) (*RPCFactory) {
factory := &RPCFactory{config: cfg, serviceName: sName, logger: logger, tlsFactory: tlsProvider}
return factory, nil
return factory
}

func (d *RPCFactory) GetFrontendGRPCServerOptions() ([]grpc.ServerOption, error) {
Expand Down
17 changes: 12 additions & 5 deletions common/rpc/rpc_localstore_tls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,9 @@ func (s *localStoreRPCSuite) SetupSuite() {
s.Assertions = require.New(s.T())
s.logger = loggerimpl.NewDevelopmentForTest(s.Suite)

insecureFactory, err := NewFactory(rpcTestCfgDefault, "tester", s.logger, serverCfgInsecure)
provider, err := encryption.NewTLSConfigProviderFromConfig(serverCfgInsecure.TLS)
s.NoError(err)
insecureFactory := NewFactory(rpcTestCfgDefault, "tester", s.logger, provider)
s.NotNil(insecureFactory)
s.insecureRPCFactory = i(insecureFactory)

Expand Down Expand Up @@ -136,11 +137,14 @@ func (s *localStoreRPCSuite) setupFrontend(internodeChain CertChain, frontendCha
},
}

frontendMutualTLSFactory, err := NewFactory(rpcTestCfgDefault, "tester", s.logger, localStoreMutualTLS)
provider, err := encryption.NewTLSConfigProviderFromConfig(localStoreMutualTLS.TLS)
s.NoError(err)
frontendMutualTLSFactory := NewFactory(rpcTestCfgDefault, "tester", s.logger, provider)
s.NotNil(frontendMutualTLSFactory)

frontendServerTLSFactory, err := NewFactory(rpcTestCfgDefault, "tester", s.logger, localStoreServerTLS)
provider, err = encryption.NewTLSConfigProviderFromConfig(localStoreServerTLS.TLS)
s.NoError(err)
frontendServerTLSFactory := NewFactory(rpcTestCfgDefault, "tester", s.logger, provider)
s.NoError(err)
s.NotNil(frontendServerTLSFactory)

Expand Down Expand Up @@ -202,11 +206,14 @@ func (s *localStoreRPCSuite) setupInternode(internodeChain CertChain, frontendCh
},
}

internodeMutualTLSFactory, err := NewFactory(rpcTestCfgDefault, "worker", s.logger, localStoreMutualTLS)
provider, err := encryption.NewTLSConfigProviderFromConfig(localStoreMutualTLS.TLS)
s.NoError(err)
internodeMutualTLSFactory := NewFactory(rpcTestCfgDefault, "tester", s.logger, provider)
s.NotNil(internodeMutualTLSFactory)

internodeServerTLSFactory, err := NewFactory(rpcTestCfgDefault, "worker", s.logger, localStoreServerTLS)
provider, err = encryption.NewTLSConfigProviderFromConfig(localStoreServerTLS.TLS)
s.NoError(err)
internodeServerTLSFactory := NewFactory(rpcTestCfgDefault, "tester", s.logger, provider)
s.NoError(err)
s.NotNil(internodeServerTLSFactory)

Expand Down
12 changes: 11 additions & 1 deletion common/service/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ type (
CertFile string `yaml:"certFile"`
// The path to the file containing the PEM-encoded private key of the certificate to use.
KeyFile string `yaml:"keyFile"`
// A list of paths to files containing the PEM-encoded public key of the Certificate Authorities you wish to trust for client authentication.
// A list of paths to files containing the PEM-encoded public key of the Certificate Authorities you wish to trust for client authentication.
// This value is ignored if `requireClientAuth` is not enabled.
ClientCAFiles []string `yaml:"clientCaFiles"`
// Requires clients to authenticate with a certificate when connecting, otherwise known as mutual TLS.
Expand All @@ -145,6 +145,12 @@ type (

// ClientTLS contains TLS configuration for clients.
ClientTLS struct {
// DNS name to validate against for server to server connections.
// Required when TLS is enabled in a multi-host cluster.
// This name should be referenced by the certificate specified in the ServerTLS section.
ServerName string `yaml:"serverName"`

// Optional - A list of paths to files containing the PEM-encoded public key of the Certificate Authorities you wish to trust.
RootCAFiles []string `yaml:"rootCaFiles"`
}

Expand Down Expand Up @@ -472,3 +478,7 @@ func (c *Config) String() string {
out, _ := json.MarshalIndent(c, "", " ")
return string(out)
}

func (r *GroupTLS) IsEnabled() bool {
return r.Server.KeyFile != ""
}

0 comments on commit 45d930f

Please sign in to comment.