Skip to content

Commit

Permalink
Refactor GRPC TLS connection default
Browse files Browse the repository at this point in the history
  • Loading branch information
aledbf authored and roboquat committed Oct 12, 2021
1 parent b5b8bde commit 1eb8f86
Show file tree
Hide file tree
Showing 11 changed files with 201 additions and 277 deletions.
113 changes: 113 additions & 0 deletions components/common-go/grpc/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
package grpc

import (
"crypto/tls"
"crypto/x509"
"os"
"path/filepath"
"time"

"github.com/gitpod-io/gitpod/common-go/log"
Expand All @@ -14,6 +18,7 @@ import (
"github.com/opentracing/opentracing-go"
"github.com/prometheus/client_golang/prometheus"
"github.com/sirupsen/logrus"
"golang.org/x/xerrors"
"google.golang.org/grpc"
"google.golang.org/grpc/backoff"
"google.golang.org/grpc/grpclog"
Expand Down Expand Up @@ -106,3 +111,111 @@ func SetupLogging() {
log.WithField("component", "grpc").WriterLevel(logrus.ErrorLevel),
))
}

// TLSConfigOption configures a TLSConfig
type TLSConfigOption func(*tlsConfigOptions) error

type tlsConfigOptions struct {
ClientAuth tls.ClientAuthType
ServerName string

RootCAs bool
ClientCAs bool
}

// WithClientAuth configures a policy for TLS Client Authentication
func WithClientAuth(authType tls.ClientAuthType) TLSConfigOption {
return func(ico *tlsConfigOptions) error {
ico.ClientAuth = authType
return nil
}
}

// WithServerName configures thge ServerName used to verify the hostname
func WithServerName(serverName string) TLSConfigOption {
return func(ico *tlsConfigOptions) error {
ico.ServerName = serverName
return nil
}
}

func WithSetRootCAs(rootCAs bool) TLSConfigOption {
return func(ico *tlsConfigOptions) error {
ico.RootCAs = rootCAs
return nil
}
}

func WithSetClientCAs(clientCAs bool) TLSConfigOption {
return func(ico *tlsConfigOptions) error {
ico.ClientCAs = clientCAs
return nil
}
}

func ClientAuthTLSConfig(authority, certificate, privateKey string, opts ...TLSConfigOption) (*tls.Config, error) {
// Telepresence (used for debugging only) requires special paths to load files from
if root := os.Getenv("TELEPRESENCE_ROOT"); root != "" {
authority = filepath.Join(root, authority)
certificate = filepath.Join(root, certificate)
privateKey = filepath.Join(root, privateKey)
}

// Load certs
tlsCertificate, err := tls.LoadX509KeyPair(certificate, privateKey)
if err != nil {
return nil, xerrors.Errorf("cannot load TLS certificate: %w", err)
}

// Create a certificate pool from the certificate authority
certPool := x509.NewCertPool()
ca, err := os.ReadFile(authority)
if err != nil {
return nil, xerrors.Errorf("cannot not read ca certificate: %w", err)
}

if ok := certPool.AppendCertsFromPEM(ca); !ok {
return nil, xerrors.Errorf("failed to append ca certs")
}

options := tlsConfigOptions{}
for _, o := range opts {
err := o(&options)
if err != nil {
return nil, err
}
}

tlsConfig := &tls.Config{
Certificates: []tls.Certificate{tlsCertificate},
CipherSuites: []uint16{
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
},
CurvePreferences: []tls.CurveID{tls.X25519, tls.CurveP256},
MinVersion: tls.VersionTLS12,
MaxVersion: tls.VersionTLS12,
NextProtos: []string{"h2"},
}

tlsConfig.ServerName = options.ServerName

if options.ClientAuth != tls.NoClientCert {
log.WithField("clientAuth", options.ClientAuth).Info("enabling client authentication")
tlsConfig.ClientAuth = options.ClientAuth
}

if options.ClientCAs {
tlsConfig.ClientCAs = certPool
}

if options.RootCAs {
tlsConfig.RootCAs = certPool
}

return tlsConfig, nil
}
35 changes: 12 additions & 23 deletions components/content-service-api/go/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ package config

import (
"crypto/tls"
"crypto/x509"
"os"

"golang.org/x/xerrors"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"os"

common_grpc "github.com/gitpod-io/gitpod/common-go/grpc"
)

// StorageConfig configures the remote storage we use
Expand Down Expand Up @@ -143,28 +145,15 @@ func (c *TLSConfig) ServerOption() (grpc.ServerOption, error) {
return nil, nil
}

// Load certs
certificate, err := tls.LoadX509KeyPair(c.Certificate, c.PrivateKey)
tlsConfig, err := common_grpc.ClientAuthTLSConfig(
c.Authority, c.Certificate, c.PrivateKey,
common_grpc.WithSetClientCAs(true),
common_grpc.WithClientAuth(tls.RequireAndVerifyClientCert),
common_grpc.WithServerName("ws-manager"),
)
if err != nil {
return nil, xerrors.Errorf("cannot load TLS certificate: %w", err)
return nil, xerrors.Errorf("cannot load ws-manager certs: %w", err)
}

// Create a certificate pool from the certificate authority
certPool := x509.NewCertPool()
ca, err := os.ReadFile(c.Authority)
if err != nil {
return nil, xerrors.Errorf("cannot not read ca certificate: %w", err)
}
if ok := certPool.AppendCertsFromPEM(ca); !ok {
return nil, xerrors.Errorf("failed to append ca certs")
}

creds := credentials.NewTLS(&tls.Config{
ClientAuth: tls.RequireAndVerifyClientCert,
Certificates: []tls.Certificate{certificate},
ClientCAs: certPool,
MinVersion: tls.VersionTLS12,
})

return grpc.Creds(creds), nil
return grpc.Creds(credentials.NewTLS(tlsConfig)), nil
}
41 changes: 5 additions & 36 deletions components/ee/ws-scheduler/pkg/scaler/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ package scaler

import (
"context"
"crypto/tls"
"crypto/x509"
"os"
"path/filepath"
"sort"
"sync"
"time"
Expand Down Expand Up @@ -81,43 +77,16 @@ func NewWorkspaceManagerPrescaleDriver(config WorkspaceManagerPrescaleDriverConf

grpcOpts := common_grpc.DefaultClientOptions()
if config.WsManager.TLS != nil {
ca := config.WsManager.TLS.CA
crt := config.WsManager.TLS.Certificate
key := config.WsManager.TLS.PrivateKey

// Telepresence (used for debugging only) requires special paths to load files from
if root := os.Getenv("TELEPRESENCE_ROOT"); root != "" {
ca = filepath.Join(root, ca)
crt = filepath.Join(root, crt)
key = filepath.Join(root, key)
}

rootCA, err := os.ReadFile(ca)
if err != nil {
return nil, xerrors.Errorf("could not read ca certificate: %s", err)
}
certPool := x509.NewCertPool()
if ok := certPool.AppendCertsFromPEM(rootCA); !ok {
return nil, xerrors.Errorf("failed to append ca certs")
}

certificate, err := tls.LoadX509KeyPair(crt, key)
tlsConfig, err := common_grpc.ClientAuthTLSConfig(
config.WsManager.TLS.CA, config.WsManager.TLS.Certificate, config.WsManager.TLS.PrivateKey,
common_grpc.WithSetRootCAs(true),
)
if err != nil {
log.WithField("config", config.WsManager.TLS).Error("Cannot load ws-manager certs - this is a configuration issue.")
return nil, xerrors.Errorf("cannot load ws-manager certs: %w", err)
}

creds := credentials.NewTLS(&tls.Config{
Certificates: []tls.Certificate{certificate},
RootCAs: certPool,
MinVersion: tls.VersionTLS12,
})
grpcOpts = append(grpcOpts, grpc.WithTransportCredentials(creds))
log.
WithField("ca", ca).
WithField("cert", crt).
WithField("key", key).
Debug("using TLS config to connect ws-manager")
grpcOpts = append(grpcOpts, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)))
} else {
grpcOpts = append(grpcOpts, grpc.WithInsecure())
}
Expand Down
34 changes: 11 additions & 23 deletions components/image-builder-api/go/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ package config

import (
"crypto/tls"
"crypto/x509"
//wsmanapi "github.com/gitpod-io/gitpod/ws-manager/api"

"golang.org/x/xerrors"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"io/ioutil"

common_grpc "github.com/gitpod-io/gitpod/common-go/grpc"
)

type PProf struct {
Expand Down Expand Up @@ -48,29 +48,17 @@ func (c *TLSConfig) ServerOption() (grpc.ServerOption, error) {
return nil, nil
}

// Load certs
certificate, err := tls.LoadX509KeyPair(c.Certificate, c.PrivateKey)
tlsConfig, err := common_grpc.ClientAuthTLSConfig(
c.Authority, c.Certificate, c.PrivateKey,
common_grpc.WithSetClientCAs(true),
common_grpc.WithClientAuth(tls.RequireAndVerifyClientCert),
common_grpc.WithServerName("ws-manager"),
)
if err != nil {
return nil, xerrors.Errorf("cannot load TLS certificate: %w", err)
return nil, xerrors.Errorf("cannot load certs: %w", err)
}

// Create a certificate pool from the certificate authority
certPool := x509.NewCertPool()
ca, err := ioutil.ReadFile(c.Authority)
if err != nil {
return nil, xerrors.Errorf("cannot not read ca certificate: %w", err)
}
if ok := certPool.AppendCertsFromPEM(ca); !ok {
return nil, xerrors.Errorf("failed to append ca certs")
}

creds := credentials.NewTLS(&tls.Config{
ClientAuth: tls.RequireAndVerifyClientCert,
Certificates: []tls.Certificate{certificate},
ClientCAs: certPool,
})

return grpc.Creds(creds), nil
return grpc.Creds(credentials.NewTLS(tlsConfig)), nil
}

// Configuration configures the orchestrator
Expand Down
39 changes: 8 additions & 31 deletions components/image-builder-mk3/pkg/orchestrator/orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,10 @@ import (
"crypto/cipher"
"crypto/rand"
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"github.com/gitpod-io/gitpod/image-builder/api/config"
"io"
"io/ioutil"
"os"
Expand All @@ -26,6 +23,8 @@ import (
"sync"
"time"

"github.com/gitpod-io/gitpod/image-builder/api/config"

"github.com/opentracing/opentracing-go"
"golang.org/x/xerrors"
"google.golang.org/grpc"
Expand Down Expand Up @@ -96,39 +95,17 @@ func NewOrchestratingBuilder(cfg config.Configuration) (res *Orchestrator, err e
} else {
grpcOpts := common_grpc.DefaultClientOptions()
if cfg.WorkspaceManager.TLS.Authority != "" || cfg.WorkspaceManager.TLS.Certificate != "" && cfg.WorkspaceManager.TLS.PrivateKey != "" {
ca := cfg.WorkspaceManager.TLS.Authority
crt := cfg.WorkspaceManager.TLS.Certificate
key := cfg.WorkspaceManager.TLS.PrivateKey

// Telepresence (used for debugging only) requires special paths to load files from
if root := os.Getenv("TELEPRESENCE_ROOT"); root != "" {
ca = filepath.Join(root, ca)
crt = filepath.Join(root, crt)
key = filepath.Join(root, key)
}

rootCA, err := os.ReadFile(ca)
if err != nil {
return nil, xerrors.Errorf("could not read ca certificate: %s", err)
}
certPool := x509.NewCertPool()
if ok := certPool.AppendCertsFromPEM(rootCA); !ok {
return nil, xerrors.Errorf("failed to append ca certs")
}

certificate, err := tls.LoadX509KeyPair(crt, key)
tlsConfig, err := common_grpc.ClientAuthTLSConfig(
cfg.WorkspaceManager.TLS.Authority, cfg.WorkspaceManager.TLS.Certificate, cfg.WorkspaceManager.TLS.PrivateKey,
common_grpc.WithSetRootCAs(true),
common_grpc.WithServerName("ws-manager"),
)
if err != nil {
log.WithField("config", cfg.WorkspaceManager.TLS).Error("Cannot load ws-manager certs - this is a configuration issue.")
return nil, xerrors.Errorf("cannot load ws-manager certs: %w", err)
}

creds := credentials.NewTLS(&tls.Config{
ServerName: "ws-manager",
Certificates: []tls.Certificate{certificate},
RootCAs: certPool,
MinVersion: tls.VersionTLS12,
})
grpcOpts = append(grpcOpts, grpc.WithTransportCredentials(creds))
grpcOpts = append(grpcOpts, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)))
} else {
grpcOpts = append(grpcOpts, grpc.WithInsecure())
}
Expand Down
Loading

0 comments on commit 1eb8f86

Please sign in to comment.