From 746e9a1c21e365300764af52808fba3b8b34f63e Mon Sep 17 00:00:00 2001 From: rmweir Date: Tue, 10 Mar 2020 18:18:17 -0700 Subject: [PATCH] Skip restore if no valid certs --- cmd/etcd.go | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/cmd/etcd.go b/cmd/etcd.go index 5e403498..35171de7 100644 --- a/cmd/etcd.go +++ b/cmd/etcd.go @@ -2,10 +2,12 @@ package cmd import ( "context" + "crypto/x509" "fmt" "strings" "time" + "github.com/pkg/errors" "github.com/rancher/rke/cluster" "github.com/rancher/rke/hosts" "github.com/rancher/rke/log" @@ -129,6 +131,11 @@ func RestoreEtcdSnapshot( if err != nil { return APIURL, caCrt, clientCert, clientKey, nil, err } + + if err := validateCerts(rkeFullState.DesiredState); err != nil { + return APIURL, caCrt, clientCert, clientKey, nil, err + } + if err := checkLegacyCluster(ctx, kubeCluster, rkeFullState, flags); err != nil { return APIURL, caCrt, clientCert, clientKey, nil, err } @@ -180,6 +187,42 @@ func RestoreEtcdSnapshot( return APIURL, caCrt, clientCert, clientKey, certs, err } +func validateCerts(state cluster.State) error { + var failedErrs error + + if state.RancherKubernetesEngineConfig == nil { + // possibly already started a restore + return nil + } + for name, certPKI := range state.CertificatesBundle { + if name == pki.ServiceAccountTokenKeyName || name == pki.RequestHeaderCACertName || name == pki.KubeAdminCertName { + continue + } + + cert := certPKI.Certificate + if cert == nil { + if failedErrs == nil { + failedErrs = fmt.Errorf("Certificate [%s] is nil", certPKI.Name) + } else { + failedErrs = errors.Wrap(failedErrs, fmt.Sprintf("Certificate [%s] is nil", certPKI.Name)) + } + } + + certPool := x509.NewCertPool() + certPool.AddCert(cert) + if _, err := cert.Verify(x509.VerifyOptions{Roots: certPool, KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}}); err != nil { + if failedErrs == nil { + failedErrs = fmt.Errorf("Certificate [%s] failed verification: %v", certPKI.Name, err) + } + failedErrs = errors.Wrap(failedErrs, fmt.Sprintf("Certificate [%s] failed verification: %v", certPKI.Name, err)) + } + } + if failedErrs != nil { + return errors.Wrap(failedErrs, "[etcd] Failed to restore etcd snapshot: invalid certs") + } + return nil +} + func SnapshotSaveEtcdHostsFromCli(ctx *cli.Context) error { logrus.Infof("Running RKE version: %v", ctx.App.Version) clusterFile, filePath, err := resolveClusterFile(ctx)