fn: SSL config adjustments (#1160)

SSL related FN_NODE_CERT (and related) settings are
not very clear today. Removing this in favor of a
simple map of tls.Config objects. Three keys are
provided for this map:

TLSGRPCServer
TLSAdminServer
TLSWebServer

which correspond to server TLS settings for the
associated services.

Operators/implementers can further add more
keys to the map and add their own TLS config.
This commit is contained in:
Tolga Ceylan
2018-08-06 20:57:03 -07:00
committed by GitHub
parent ff39d0896f
commit f57571fb3a
9 changed files with 157 additions and 175 deletions

View File

@@ -2,6 +2,7 @@ package agent
import (
"context"
"crypto/tls"
"errors"
"fmt"
"io"
@@ -27,13 +28,12 @@ type mockRunner struct {
type mockRunnerPool struct {
runners []pool.Runner
generator pool.MTLSRunnerFactory
pki *pool.PKIData
}
func newMockRunnerPool(rf pool.MTLSRunnerFactory, runnerAddrs []string) *mockRunnerPool {
var runners []pool.Runner
for _, addr := range runnerAddrs {
r, err := rf(addr, "", nil)
r, err := rf(addr, nil)
if err != nil {
continue
}
@@ -43,7 +43,6 @@ func newMockRunnerPool(rf pool.MTLSRunnerFactory, runnerAddrs []string) *mockRun
return &mockRunnerPool{
runners: runners,
generator: rf,
pki: &pool.PKIData{},
}
}
@@ -56,7 +55,7 @@ func (rp *mockRunnerPool) Shutdown(context.Context) error {
}
func NewMockRunnerFactory(sleep time.Duration, maxCalls int32) pool.MTLSRunnerFactory {
return func(addr, cn string, pki *pool.PKIData) (pool.Runner, error) {
return func(addr string, tlsConf *tls.Config) (pool.Runner, error) {
return &mockRunner{
sleep: sleep,
maxCalls: maxCalls,
@@ -66,7 +65,7 @@ func NewMockRunnerFactory(sleep time.Duration, maxCalls int32) pool.MTLSRunnerFa
}
func FaultyRunnerFactory() pool.MTLSRunnerFactory {
return func(addr, cn string, pki *pool.PKIData) (pool.Runner, error) {
return func(addr string, tlsConf *tls.Config) (pool.Runner, error) {
return &mockRunner{
addr: addr,
}, errors.New("Creation of new runner failed")

View File

@@ -4,7 +4,6 @@ import (
"bytes"
"context"
"crypto/tls"
"crypto/x509"
"encoding/hex"
"encoding/json"
"errors"
@@ -866,26 +865,22 @@ func (pr *pureRunner) Status(ctx context.Context, _ *empty.Empty) (*runner.Runne
return pr.handleStatusCall(ctx)
}
func DefaultPureRunner(cancel context.CancelFunc, addr string, da CallHandler, cert string, key string, ca string) (Agent, error) {
func DefaultPureRunner(cancel context.CancelFunc, addr string, da CallHandler, tlsCfg *tls.Config) (Agent, error) {
agent := New(da)
// WARNING: SSL creds are optional.
if cert == "" || key == "" || ca == "" {
if tlsCfg == nil {
return NewPureRunner(cancel, addr, PureRunnerWithAgent(agent))
}
return NewPureRunner(cancel, addr, PureRunnerWithAgent(agent), PureRunnerWithSSL(cert, key, ca))
return NewPureRunner(cancel, addr, PureRunnerWithAgent(agent), PureRunnerWithSSL(tlsCfg))
}
type PureRunnerOption func(*pureRunner) error
func PureRunnerWithSSL(cert string, key string, ca string) PureRunnerOption {
func PureRunnerWithSSL(tlsCfg *tls.Config) PureRunnerOption {
return func(pr *pureRunner) error {
c, err := createCreds(cert, key, ca)
if err != nil {
return fmt.Errorf("Failed to create pure runner credentials: %s", err)
}
pr.creds = c
pr.creds = credentials.NewTLS(tlsCfg)
return nil
}
}
@@ -961,34 +956,5 @@ func NewPureRunner(cancel context.CancelFunc, addr string, options ...PureRunner
return pr, nil
}
func createCreds(cert string, key string, ca string) (credentials.TransportCredentials, error) {
if cert == "" || key == "" || ca == "" {
return nil, errors.New("Failed to create credentials, cert/key/ca not provided")
}
// Load the certificates from disk
certificate, err := tls.LoadX509KeyPair(cert, key)
if err != nil {
return nil, fmt.Errorf("Could not load server key pair: %s", err)
}
// Create a certificate pool from the certificate authority
certPool := x509.NewCertPool()
authority, err := ioutil.ReadFile(ca)
if err != nil {
return nil, fmt.Errorf("Could not read ca certificate: %s", err)
}
if ok := certPool.AppendCertsFromPEM(authority); !ok {
return nil, errors.New("Failed to append client certs")
}
return credentials.NewTLS(&tls.Config{
ClientAuth: tls.RequireAndVerifyClientCert,
Certificates: []tls.Certificate{certificate},
ClientCAs: certPool,
}), nil
}
var _ runner.RunnerProtocolServer = &pureRunner{}
var _ Agent = &pureRunner{}

View File

@@ -2,6 +2,7 @@ package agent
import (
"context"
"crypto/tls"
"encoding/hex"
"encoding/json"
"errors"
@@ -39,8 +40,8 @@ type gRPCRunner struct {
client pb.RunnerProtocolClient
}
func SecureGRPCRunnerFactory(addr, runnerCertCN string, pki *pool.PKIData) (pool.Runner, error) {
conn, client, err := runnerConnection(addr, runnerCertCN, pki)
func SecureGRPCRunnerFactory(addr string, tlsConf *tls.Config) (pool.Runner, error) {
conn, client, err := runnerConnection(addr, tlsConf)
if err != nil {
return nil, err
}
@@ -59,20 +60,15 @@ func (r *gRPCRunner) Close(context.Context) error {
return r.conn.Close()
}
func runnerConnection(address, runnerCertCN string, pki *pool.PKIData) (*grpc.ClientConn, pb.RunnerProtocolClient, error) {
func runnerConnection(address string, tlsConf *tls.Config) (*grpc.ClientConn, pb.RunnerProtocolClient, error) {
ctx := context.Background()
logger := common.Logger(ctx).WithField("runner_addr", address)
ctx = common.WithLogger(ctx, logger)
var creds credentials.TransportCredentials
if pki != nil {
var err error
creds, err = grpcutil.CreateCredentials(pki.Cert, pki.Key, pki.Ca, runnerCertCN)
if err != nil {
logger.WithError(err).Error("Unable to create credentials to connect to runner node")
return nil, nil, err
}
if tlsConf != nil {
creds = credentials.NewTLS(tlsConf)
}
// we want to set a very short timeout to fail-fast if something goes wrong

View File

@@ -2,6 +2,7 @@ package agent
import (
"context"
"crypto/tls"
pool "github.com/fnproject/fn/api/runnerpool"
"github.com/sirupsen/logrus"
@@ -10,20 +11,20 @@ import (
// manages a single set of runners ignoring lb groups
type staticRunnerPool struct {
generator pool.MTLSRunnerFactory
pki *pool.PKIData // can be nil when running in insecure mode
tlsConf *tls.Config // can be nil when running in insecure mode
runnerCN string
runners []pool.Runner
}
func DefaultStaticRunnerPool(runnerAddresses []string) pool.RunnerPool {
return NewStaticRunnerPool(runnerAddresses, nil, "", SecureGRPCRunnerFactory)
return NewStaticRunnerPool(runnerAddresses, nil, SecureGRPCRunnerFactory)
}
func NewStaticRunnerPool(runnerAddresses []string, pki *pool.PKIData, runnerCN string, runnerFactory pool.MTLSRunnerFactory) pool.RunnerPool {
func NewStaticRunnerPool(runnerAddresses []string, tlsConf *tls.Config, runnerFactory pool.MTLSRunnerFactory) pool.RunnerPool {
logrus.WithField("runners", runnerAddresses).Info("Starting static runner pool")
var runners []pool.Runner
for _, addr := range runnerAddresses {
r, err := runnerFactory(addr, runnerCN, pki)
r, err := runnerFactory(addr, tlsConf)
if err != nil {
logrus.WithError(err).WithField("runner_addr", addr).Warn("Invalid runner")
continue
@@ -33,8 +34,7 @@ func NewStaticRunnerPool(runnerAddresses []string, pki *pool.PKIData, runnerCN s
}
return &staticRunnerPool{
runners: runners,
pki: pki,
runnerCN: runnerCN,
tlsConf: tlsConf,
generator: runnerFactory,
}
}

View File

@@ -2,6 +2,7 @@ package agent
import (
"context"
"crypto/tls"
"errors"
"testing"
@@ -9,7 +10,7 @@ import (
)
func setupStaticPool(runners []string) pool.RunnerPool {
return NewStaticRunnerPool(runners, nil, "", mockRunnerFactory)
return NewStaticRunnerPool(runners, nil, mockRunnerFactory)
}
var (
@@ -36,7 +37,7 @@ func (r *mockStaticRunner) Address() string {
return r.address
}
func mockRunnerFactory(addr, cn string, pki *pool.PKIData) (pool.Runner, error) {
func mockRunnerFactory(addr string, tlsConf *tls.Config) (pool.Runner, error) {
return &mockStaticRunner{address: addr}, nil
}