From 62acd6251637250dbea7d408d8cd4d5eb1f18713 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 27 Sep 2021 17:36:06 +0300 Subject: [PATCH] fix: check trustd API CA on worker nodes This distributes API CA (just the certificate, not the key) to the worker nodes on config generation, and if the CA cert is present on the worker node, it verifies TLS connection to the trustd with the CA certificate. Signed-off-by: Andrey Smirnov --- .../machined/pkg/controllers/secrets/api.go | 2 +- pkg/grpc/gen/remote.go | 4 +-- pkg/grpc/middleware/auth/basic/basic.go | 25 +++++++++++-------- .../config/types/v1alpha1/generate/worker.go | 1 + 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/internal/app/machined/pkg/controllers/secrets/api.go b/internal/app/machined/pkg/controllers/secrets/api.go index df829a9225..2c01769882 100644 --- a/internal/app/machined/pkg/controllers/secrets/api.go +++ b/internal/app/machined/pkg/controllers/secrets/api.go @@ -337,7 +337,7 @@ func (ctrl *APIController) generateControlPlane(ctx context.Context, r controlle func (ctrl *APIController) generateJoin(ctx context.Context, r controller.Runtime, logger *zap.Logger, rootSpec *secrets.RootOSSpec, endpointsStr []string, certSANs *secrets.CertSANSpec) error { - remoteGen, err := gen.NewRemoteGenerator(rootSpec.Token, endpointsStr) + remoteGen, err := gen.NewRemoteGenerator(rootSpec.Token, endpointsStr, rootSpec.CA) if err != nil { return fmt.Errorf("failed creating trustd client: %w", err) } diff --git a/pkg/grpc/gen/remote.go b/pkg/grpc/gen/remote.go index 4c405cc296..8ea3c4b811 100644 --- a/pkg/grpc/gen/remote.go +++ b/pkg/grpc/gen/remote.go @@ -33,14 +33,14 @@ type RemoteGenerator struct { } // NewRemoteGenerator initializes a RemoteGenerator with a preconfigured grpc.ClientConn. -func NewRemoteGenerator(token string, endpoints []string) (g *RemoteGenerator, err error) { +func NewRemoteGenerator(token string, endpoints []string, ca *x509.PEMEncodedCertificateAndKey) (g *RemoteGenerator, err error) { if len(endpoints) == 0 { return nil, fmt.Errorf("at least one root of trust endpoint is required") } g = &RemoteGenerator{} - conn, err := basic.NewConnection(fmt.Sprintf("%s:///%s", trustdResolverScheme, strings.Join(endpoints, ",")), basic.NewTokenCredentials(token)) + conn, err := basic.NewConnection(fmt.Sprintf("%s:///%s", trustdResolverScheme, strings.Join(endpoints, ",")), basic.NewTokenCredentials(token), ca) if err != nil { return nil, err } diff --git a/pkg/grpc/middleware/auth/basic/basic.go b/pkg/grpc/middleware/auth/basic/basic.go index 1a64c03c3f..eaadd60695 100644 --- a/pkg/grpc/middleware/auth/basic/basic.go +++ b/pkg/grpc/middleware/auth/basic/basic.go @@ -6,7 +6,9 @@ package basic import ( "crypto/tls" + stdx509 "crypto/x509" + "github.com/talos-systems/crypto/x509" "google.golang.org/grpc" "google.golang.org/grpc/credentials" ) @@ -20,17 +22,20 @@ type Credentials interface { // NewConnection initializes a grpc.ClientConn configured for basic // authentication. -func NewConnection(address string, creds credentials.PerRPCCredentials) (conn *grpc.ClientConn, err error) { - grpcOpts := []grpc.DialOption{} - - grpcOpts = append( - grpcOpts, - grpc.WithTransportCredentials( - credentials.NewTLS(&tls.Config{ - InsecureSkipVerify: true, - })), +func NewConnection(address string, creds credentials.PerRPCCredentials, ca *x509.PEMEncodedCertificateAndKey) (conn *grpc.ClientConn, err error) { + tlsConfig := &tls.Config{} + + if ca == nil { + tlsConfig.InsecureSkipVerify = true + } else { + tlsConfig.RootCAs = stdx509.NewCertPool() + tlsConfig.RootCAs.AppendCertsFromPEM(ca.Crt) + } + + grpcOpts := []grpc.DialOption{ + grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)), grpc.WithPerRPCCredentials(creds), - ) + } conn, err = grpc.Dial(address, grpcOpts...) if err != nil { diff --git a/pkg/machinery/config/types/v1alpha1/generate/worker.go b/pkg/machinery/config/types/v1alpha1/generate/worker.go index c82009c847..7465db9cc4 100644 --- a/pkg/machinery/config/types/v1alpha1/generate/worker.go +++ b/pkg/machinery/config/types/v1alpha1/generate/worker.go @@ -39,6 +39,7 @@ func workerUd(in *Input) (*v1alpha1.Config, error) { KubeletImage: emptyIf(fmt.Sprintf("%s:v%s", constants.KubeletImage, in.KubernetesVersion), in.KubernetesVersion), }, MachineNetwork: networkConfig, + MachineCA: &x509.PEMEncodedCertificateAndKey{Crt: in.Certs.OS.Crt}, MachineInstall: &v1alpha1.InstallConfig{ InstallDisk: in.InstallDisk, InstallImage: in.InstallImage,