diff --git a/pkg/cmd/init.go b/pkg/cmd/init.go index f5a937ac33..6b39152519 100644 --- a/pkg/cmd/init.go +++ b/pkg/cmd/init.go @@ -611,7 +611,7 @@ func cleanupStaleKubeconfigs(cfg *config.Config, path string) error { } } for _, deletePath := range deleteDirs { - if err := os.RemoveAll(deletePath); err != nil { + if err := os.RemoveAll(filepath.Clean(deletePath)); err != nil { klog.Warningf("Unable to remove %s: %v", deletePath, err) } klog.Infof("Removed stale kubeconfig %s", deletePath) diff --git a/pkg/controllers/kube-controller-manager.go b/pkg/controllers/kube-controller-manager.go index 02f031bd8f..6fb7c5b6e5 100644 --- a/pkg/controllers/kube-controller-manager.go +++ b/pkg/controllers/kube-controller-manager.go @@ -98,6 +98,10 @@ func configure(ctx context.Context, cfg *config.Config) (args []string, applyFn "v": {strconv.Itoa(cfg.GetVerbosity())}, "tls-cipher-suites": {strings.Join(cfg.ApiServer.TLS.CipherSuites, ",")}, "tls-min-version": {cfg.ApiServer.TLS.MinVersion}, + // Use the same certificates as the apiserver for localhost communication + // to avoid creating new certificates just for this component having the same CN/SAN. + "tls-cert-file": {cryptomaterial.ServingCertPath(cryptomaterial.KubeAPIServerLocalhostServingCertDir(cryptomaterial.CertsDirectory(config.DataDir)))}, + "tls-private-key-file": {cryptomaterial.ServingKeyPath(cryptomaterial.KubeAPIServerLocalhostServingCertDir(cryptomaterial.CertsDirectory(config.DataDir)))}, }, } @@ -122,7 +126,7 @@ func (s *KubeControllerManager) Run(ctx context.Context, ready chan<- struct{}, // run readiness check go func() { // This endpoint uses a self-signed certificate on purpose, we need to skip verification. - healthcheckStatus := util.RetryInsecureGet(ctx, "https://localhost:10257/healthz") + healthcheckStatus := util.RetryGet(ctx, "https://localhost:10257/healthz", cryptomaterial.CACertPath(cryptomaterial.KubeAPIServerLocalhostSigner(cryptomaterial.CertsDirectory(config.DataDir)))) if healthcheckStatus != 200 { klog.Errorf("kube-controller-manager failed to start") errorChannel <- errors.New("kube-controller-manager failed to start") diff --git a/pkg/controllers/kube-controller-manager_test.go b/pkg/controllers/kube-controller-manager_test.go index 971a5e017c..43804198d4 100644 --- a/pkg/controllers/kube-controller-manager_test.go +++ b/pkg/controllers/kube-controller-manager_test.go @@ -28,6 +28,7 @@ import ( "github.com/google/go-cmp/cmp" embedded "github.com/openshift/microshift/assets" "github.com/openshift/microshift/pkg/config" + "github.com/openshift/microshift/pkg/util/cryptomaterial" ) func TestKCMDefaultConfigAsset(t *testing.T) { @@ -72,8 +73,10 @@ func TestConfigure(t *testing.T) { "--secure-port=10257", fmt.Sprintf("--service-account-private-key-file=%s", kcmServiceAccountPrivateKeyFile()), fmt.Sprintf("--service-cluster-ip-range=%s", cfg.Network.ServiceNetwork[0]), + fmt.Sprintf("--tls-cert-file=%s", cryptomaterial.ServingCertPath(cryptomaterial.KubeAPIServerLocalhostServingCertDir(cryptomaterial.CertsDirectory(config.DataDir)))), fmt.Sprintf("--tls-cipher-suites=%s", strings.Join(crypto.OpenSSLToIANACipherSuites(fixedTLSProfile.Ciphers), ",")), fmt.Sprintf("--tls-min-version=%s", string(fixedTLSProfile.MinTLSVersion)), + fmt.Sprintf("--tls-private-key-file=%s", cryptomaterial.ServingKeyPath(cryptomaterial.KubeAPIServerLocalhostServingCertDir(cryptomaterial.CertsDirectory(config.DataDir)))), "--use-service-account-credentials=true", "-v=2", } diff --git a/pkg/controllers/kube-scheduler.go b/pkg/controllers/kube-scheduler.go index e870795146..9d62171f4a 100644 --- a/pkg/controllers/kube-scheduler.go +++ b/pkg/controllers/kube-scheduler.go @@ -24,6 +24,7 @@ import ( "github.com/openshift/microshift/pkg/config" "github.com/openshift/microshift/pkg/util" + "github.com/openshift/microshift/pkg/util/cryptomaterial" klog "k8s.io/klog/v2" kubescheduler "k8s.io/kubernetes/cmd/kube-scheduler/app" @@ -55,6 +56,10 @@ func (s *KubeScheduler) configure(cfg *config.Config) { s.options.Authorization.RemoteKubeConfigFile = cfg.KubeConfigPath(config.KubeScheduler) s.options.SecureServing.MinTLSVersion = cfg.ApiServer.TLS.MinVersion s.options.SecureServing.CipherSuites = cfg.ApiServer.TLS.CipherSuites + // Use the same certificates as the apiserver for localhost communication + // to avoid creating new certificates just for this component having the same CN/SAN. + s.options.SecureServing.ServerCert.CertKey.CertFile = cryptomaterial.ServingCertPath(cryptomaterial.KubeAPIServerLocalhostServingCertDir(cryptomaterial.CertsDirectory(config.DataDir))) + s.options.SecureServing.ServerCert.CertKey.KeyFile = cryptomaterial.ServingKeyPath(cryptomaterial.KubeAPIServerLocalhostServingCertDir(cryptomaterial.CertsDirectory(config.DataDir))) s.kubeconfig = cfg.KubeConfigPath(config.KubeScheduler) } @@ -80,7 +85,7 @@ func (s *KubeScheduler) Run(ctx context.Context, ready chan<- struct{}, stopped // run readiness check go func() { // This endpoint uses a self-signed certificate on purpose, we need to skip verification. - healthcheckStatus := util.RetryInsecureGet(ctx, "https://localhost:10259/healthz") + healthcheckStatus := util.RetryGet(ctx, "https://localhost:10259/healthz", cryptomaterial.CACertPath(cryptomaterial.KubeAPIServerLocalhostSigner(cryptomaterial.CertsDirectory(config.DataDir)))) if healthcheckStatus != 200 { klog.Errorf("%s healthcheck failed due to kube-scheduler failure to start", s.Name()) errorChannel <- errors.New("kube-scheduler healthcheck failed") diff --git a/pkg/util/net.go b/pkg/util/net.go index 2cd9a8e8cc..188b01cb39 100644 --- a/pkg/util/net.go +++ b/pkg/util/net.go @@ -18,6 +18,7 @@ package util import ( "context" "crypto/tls" + "crypto/x509" "fmt" tcpnet "net" "net/http" @@ -83,12 +84,34 @@ found: } func RetryInsecureGet(ctx context.Context, url string) int { + return RetryGet(ctx, url, "") +} + +func RetryGet(ctx context.Context, url, additionalCAPath string) int { + rootCAs, err := x509.SystemCertPool() + if err != nil { + klog.Infof("Warning: Failed to load system CA certificates: %v. Creating an empty pool.", err) + rootCAs = x509.NewCertPool() + } + if additionalCAPath != "" { + caCert, err := os.ReadFile(additionalCAPath) + if err != nil { + klog.Errorf("failed to read CA certificate %s: %v", additionalCAPath, err) + return 0 + } + + if !rootCAs.AppendCertsFromPEM(caCert) { + klog.Errorf("failed to append CA certificate %s to pool", additionalCAPath) + return 0 + } + } status := 0 - err := wait.PollUntilContextTimeout(ctx, 5*time.Second, 120*time.Second, false, func(ctx context.Context) (bool, error) { + err = wait.PollUntilContextTimeout(ctx, 5*time.Second, 120*time.Second, false, func(ctx context.Context) (bool, error) { c := http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ - InsecureSkipVerify: true, //nolint:gosec + RootCAs: rootCAs, + MinVersion: tls.VersionTLS12, }, }, }