From 34353a27e2681cc6aaf99a6160f9afabc1975fe7 Mon Sep 17 00:00:00 2001 From: Pravin Pushkar Date: Fri, 25 Feb 2022 13:43:08 +0530 Subject: [PATCH] Include certificate expiry check in all kubernetes commands (#899) * Include certificate expiry check in all kubernetes commands Signed-off-by: Pravin Pushkar * Using PostRun from Cobra and fixing review comments Signed-off-by: Pravin Pushkar * Modifying logging for error on certificate check Signed-off-by: Pravin Pushkar * Fixing review comments Signed-off-by: Pravin Pushkar * Fixing string messages Signed-off-by: Pravin Pushkar --- cmd/components.go | 3 +++ cmd/configurations.go | 3 +++ cmd/dashboard.go | 5 +++++ cmd/list.go | 5 +++++ cmd/logs.go | 3 +++ cmd/mtls.go | 8 +++++++- cmd/status.go | 3 +++ cmd/upgrade.go | 3 +++ pkg/kubernetes/mtls.go | 32 ++++++++++++++++++++++++++++++-- tests/e2e/common/common.go | 2 +- 10 files changed, 63 insertions(+), 4 deletions(-) diff --git a/cmd/components.go b/cmd/components.go index 9be06eac..234f472e 100644 --- a/cmd/components.go +++ b/cmd/components.go @@ -39,6 +39,9 @@ var ComponentsCmd = &cobra.Command{ } } }, + PostRun: func(cmd *cobra.Command, args []string) { + kubernetes.CheckForCertExpiry() + }, Example: ` # List Kubernetes components dapr components -k diff --git a/cmd/configurations.go b/cmd/configurations.go index 8e78af71..cc2eaafd 100644 --- a/cmd/configurations.go +++ b/cmd/configurations.go @@ -39,6 +39,9 @@ var ConfigurationsCmd = &cobra.Command{ } } }, + PostRun: func(cmd *cobra.Command, args []string) { + kubernetes.CheckForCertExpiry() + }, Example: ` # List Kubernetes Dapr configurations dapr configurations -k diff --git a/cmd/dashboard.go b/cmd/dashboard.go index 70647bf8..efb22d48 100644 --- a/cmd/dashboard.go +++ b/cmd/dashboard.go @@ -181,6 +181,11 @@ dapr dashboard -k -p 9999 } } }, + PostRun: func(cmd *cobra.Command, args []string) { + if kubernetesMode { + kubernetes.CheckForCertExpiry() + } + }, } func init() { diff --git a/cmd/list.go b/cmd/list.go index 7062b609..e0c11996 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -87,6 +87,11 @@ dapr list -k outputList(list, len(list)) } }, + PostRun: func(cmd *cobra.Command, args []string) { + if kubernetesMode { + kubernetes.CheckForCertExpiry() + } + }, } func init() { diff --git a/cmd/logs.go b/cmd/logs.go index a618aa58..f6f5393f 100644 --- a/cmd/logs.go +++ b/cmd/logs.go @@ -44,6 +44,9 @@ dapr logs -k --app-id sample --pod-name target --namespace custom } print.SuccessStatusEvent(os.Stdout, "Fetched logs") }, + PostRun: func(cmd *cobra.Command, args []string) { + kubernetes.CheckForCertExpiry() + }, } func init() { diff --git a/cmd/mtls.go b/cmd/mtls.go index f8515b06..9de23fba 100644 --- a/cmd/mtls.go +++ b/cmd/mtls.go @@ -47,6 +47,9 @@ dapr mtls -k } fmt.Printf("Mutual TLS is %s in your Kubernetes cluster \n", status) }, + PostRun: func(cmd *cobra.Command, args []string) { + kubernetes.CheckForCertExpiry() + }, } var ExportCMD = &cobra.Command{ @@ -60,12 +63,15 @@ dapr mtls export -o ./certs err := kubernetes.ExportTrustChain(exportPath) if err != nil { print.FailureStatusEvent(os.Stderr, fmt.Sprintf("error exporting trust chain certs: %s", err)) - return + os.Exit(1) } dir, _ := filepath.Abs(exportPath) print.SuccessStatusEvent(os.Stdout, fmt.Sprintf("Trust certs successfully exported to %s", dir)) }, + PostRun: func(cmd *cobra.Command, args []string) { + kubernetes.CheckForCertExpiry() + }, } var ExpiryCMD = &cobra.Command{ diff --git a/cmd/status.go b/cmd/status.go index 114059c6..ad917ed3 100644 --- a/cmd/status.go +++ b/cmd/status.go @@ -54,6 +54,9 @@ dapr status -k utils.PrintTable(table) }, + PostRun: func(cmd *cobra.Command, args []string) { + kubernetes.CheckForCertExpiry() + }, } func init() { diff --git a/cmd/upgrade.go b/cmd/upgrade.go index 77898576..63e4db54 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -45,6 +45,9 @@ dapr upgrade -k } print.SuccessStatusEvent(os.Stdout, "Dapr control plane successfully upgraded to version %s. Make sure your deployments are restarted to pick up the latest sidecar version.", upgradeRuntimeVersion) }, + PostRun: func(cmd *cobra.Command, args []string) { + kubernetes.CheckForCertExpiry() + }, } func init() { diff --git a/pkg/kubernetes/mtls.go b/pkg/kubernetes/mtls.go index eaf376c5..57549a6a 100644 --- a/pkg/kubernetes/mtls.go +++ b/pkg/kubernetes/mtls.go @@ -28,12 +28,14 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/dapr/cli/pkg/print" "github.com/dapr/dapr/pkg/apis/configuration/v1alpha1" ) const ( - systemConfigName = "daprsystem" - trustBundleSecretName = "dapr-trust-bundle" // nolint:gosec + systemConfigName = "daprsystem" + trustBundleSecretName = "dapr-trust-bundle" // nolint:gosec + warningDaysForCertExpiry = 30 // in days ) func IsMTLSEnabled() (bool, error) { @@ -107,6 +109,32 @@ func ExportTrustChain(outputDir string) error { return nil } +// Check and warn if cert expiry is less than `warningDaysForCertExpiry` days. +func CheckForCertExpiry() { + expiry, err := Expiry() + // The intent is to warn for certificate expiry, only when it can be fetched. + // Do not show any kind of errors with normal command flow. + if err != nil { + return + } + daysRemaining := int(expiry.Sub(time.Now().UTC()).Hours() / 24) + + if daysRemaining < warningDaysForCertExpiry { + warningMessage := "" + switch { + case daysRemaining == 0: + warningMessage = "Dapr root certificate of your Kubernetes cluster expires today." + case daysRemaining < 0: + warningMessage = "Dapr root certificate of your Kubernetes cluster has expired." + default: + warningMessage = fmt.Sprintf("Dapr root certificate of your Kubernetes cluster expires in %v days.", daysRemaining) + } + helpMessage := "Please see docs.dapr.io for certificate renewal instructions to avoid service interruptions." + print.WarningStatusEvent(os.Stdout, + fmt.Sprintf("%s Expiry date: %s. \n %s", warningMessage, expiry.Format(time.RFC1123), helpMessage)) + } +} + func getTrustChainSecret() (*corev1.Secret, error) { _, client, err := GetKubeConfigClient() if err != nil { diff --git a/tests/e2e/common/common.go b/tests/e2e/common/common.go index 023c6a54..27861806 100644 --- a/tests/e2e/common/common.go +++ b/tests/e2e/common/common.go @@ -490,7 +490,7 @@ func uninstallTest(all bool) func(t *testing.T) { go waitPodDeletion(t, done, podsDeleted) select { case <-podsDeleted: - t.Log("pods were delted as expected on uninstall") + t.Log("pods were deleted as expected on uninstall") return case <-time.After(2 * time.Minute): done <- struct{}{}