Skip to content

Commit

Permalink
Reload certificates in operator-ca-tls secrets (#2133)
Browse files Browse the repository at this point in the history
* Listen for secret changes in the operator namespace and trust TLS certificates stored in secrets with the prefix "operator-ca-tls."

* No longer copy the secret `operator-ca-tls` from the operator namespace to the tenants namespace: Since [PR #1847](#1847), the secret `operator-ca-tls` is no longer mounted in the tenant, so there is no need to keep a copy.
* `queue.NewNamedRateLimitingQueue` is deprecated and has been replaced with the recommended `queue.NewRateLimitingQueueWithConfig`.
* Remove the duplicated method `getTLSSecret` and invoke `getCertificateSecret` instead.
* Rename [generateTLSCert](https://github.com/minio/operator/blob/1c2fa4f402cc2c91c9903e6da6e9a693c92b65e4/pkg/controller/tls.go#L108) to `generateTLSCertificateForService` for better understanding.
* Remove duplicated constants for 'public.crt', 'tls.crt', and 'ca.crt' in the `github.com/minio/operator/pkg/common` namespace.
* Replace hardcoded strings 'public.crt', 'tls.crt', and 'ca.crt' with constants in the `github.com/minio/operator/pkg/certs` namespace.

Signed-off-by: pjuarezd <[email protected]>

---------

Signed-off-by: pjuarezd <[email protected]>
  • Loading branch information
pjuarezd authored May 28, 2024
1 parent fdb7232 commit 4df07c1
Show file tree
Hide file tree
Showing 17 changed files with 322 additions and 309 deletions.
10 changes: 6 additions & 4 deletions pkg/apis/minio.min.io/v2/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import (
"text/template"
"time"

"github.com/minio/operator/pkg/certs"

"github.com/miekg/dns"

appsv1 "k8s.io/api/apps/v1"
Expand Down Expand Up @@ -102,7 +104,7 @@ var (
// GetPodCAFromFile assumes the operator is running inside a k8s pod and extract the
// current ca certificate from /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
func GetPodCAFromFile() []byte {
cert, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/ca.crt")
cert, err := os.ReadFile(fmt.Sprintf("/var/run/secrets/kubernetes.io/serviceaccount/%s", certs.CAPublicCertFile))
if err != nil {
return nil
}
Expand All @@ -120,7 +122,7 @@ func GetOpenshiftServiceCAFromFile() []byte {

// GetOpenshiftCSRSignerCAFromFile extracts the tls.crt certificate in Openshift deployments coming from the mounted secret openshift-csr-signer-ca
func GetOpenshiftCSRSignerCAFromFile() []byte {
cert, err := os.ReadFile("/tmp/csr-signer-ca/tls.crt")
cert, err := os.ReadFile(fmt.Sprintf("/tmp/csr-signer-ca/%s", certs.TLSCertFile))
if err != nil {
return nil
}
Expand All @@ -129,13 +131,13 @@ func GetOpenshiftCSRSignerCAFromFile() []byte {

// GetPublicCertFilePath return the path to the certificate file based for the serviceName
func GetPublicCertFilePath(serviceName string) string {
publicCertPath := fmt.Sprintf("/tmp/%s/public.crt", serviceName)
publicCertPath := fmt.Sprintf("/tmp/%s/%s", serviceName, certs.PublicCertFile)
return publicCertPath
}

// GetPrivateKeyFilePath return the path to the key file based for the serviceName
func GetPrivateKeyFilePath(serviceName string) string {
privateKey := fmt.Sprintf("/tmp/%s/private.key", serviceName)
privateKey := fmt.Sprintf("/tmp/%s/%s", serviceName, certs.PrivateKeyFile)
return privateKey
}

Expand Down
3 changes: 3 additions & 0 deletions pkg/certs/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ const (
// PrivateKeyFile Private key file for HTTPS.
PrivateKeyFile = "private.key"

// CAPublicCertFile Public certificate file for Certificate authority.
CAPublicCertFile = "ca.crt"

// TLSKeyFile Private key file for HTTPS.
TLSKeyFile = "tls.key"
)
9 changes: 0 additions & 9 deletions pkg/common/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,6 @@ const (
OperatorRuntimeOpenshift Runtime = "OPENSHIFT"
// OperatorRuntimeRancher is the Rancher runtime flag
OperatorRuntimeRancher Runtime = "RANCHER"

// TLSCRT is name of the field containing tls certificate in secret
TLSCRT = "tls.crt"

// CACRT name of the field containing ca certificate in secret
CACRT = "ca.crt"

// PublicCRT name of the field containing public certificate in secret
PublicCRT = "public.crt"
)

// Runtimes is a map of the supported Kubernetes runtimes
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/console.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,12 @@ func (c *Controller) checkConsoleSvc(ctx context.Context, tenant *miniov2.Tenant

// generateConsoleTLSCert Issues the Operator Console TLS Certificate
func (c *Controller) generateConsoleTLSCert() (*string, *string) {
return c.generateTLSCert("console", OperatorConsoleTLSSecretName, getConsoleDeploymentName())
return c.generateTLSCertificateForService("console", OperatorConsoleTLSSecretName, getConsoleDeploymentName())
}

func (c *Controller) recreateOperatorConsoleCertsIfRequired(ctx context.Context) error {
namespace := miniov2.GetNSFromFile()
operatorConsoleTLSSecret, err := c.getTLSSecret(ctx, namespace, OperatorConsoleTLSSecretName)
operatorConsoleTLSSecret, err := c.getCertificateSecret(ctx, namespace, OperatorConsoleTLSSecretName)
if err != nil {
if k8serrors.IsNotFound(err) {
klog.V(2).Info("TLS certificate not found. Generating one.")
Expand Down
13 changes: 6 additions & 7 deletions pkg/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ func StartOperator(kubeconfig string) {
klog.Infof("Watching only namespaces: %s", strings.Join(namespaces.ToSlice(), ","))
}

kubeInformerFactoryInOperatorNamespace := kubeinformers.NewSharedInformerFactoryWithOptions(kubeClient, time.Hour*1, kubeinformers.WithNamespace(v2.GetNSFromFile()))
kubeInformerFactory := kubeinformers.NewSharedInformerFactory(kubeClient, time.Second*30)
minioInformerFactory := informers.NewSharedInformerFactory(controllerClient, time.Second*30)
podName := os.Getenv(HostnameEnv)
Expand All @@ -163,20 +164,18 @@ func StartOperator(kubeconfig string) {
k8sClient,
controllerClient,
promClient,
kubeInformerFactory.Apps().V1().StatefulSets(),
kubeInformerFactory.Apps().V1().Deployments(),
kubeInformerFactory.Core().V1().Pods(),
minioInformerFactory.Minio().V2().Tenants(),
minioInformerFactory.Sts().V1beta1().PolicyBindings(),
kubeInformerFactory.Core().V1().Services(),
hostsTemplate,
pkg.Version,
kubeInformerFactory,
minioInformerFactory.Minio().V2().Tenants(),
minioInformerFactory.Sts().V1beta1().PolicyBindings(),
minioInformerFactory.Job().V1alpha1().MinIOJobs(),
kubeInformerFactory.Batch().V1().Jobs(),
kubeInformerFactoryInOperatorNamespace,
)

go kubeInformerFactory.Start(stopCh)
go minioInformerFactory.Start(stopCh)
go kubeInformerFactoryInOperatorNamespace.Start(stopCh)

if err = mainController.Start(2, stopCh); err != nil {
klog.Fatalf("Error running mainController: %s", err.Error())
Expand Down
6 changes: 4 additions & 2 deletions pkg/controller/csr.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (
"syscall"
"time"

"github.com/minio/operator/pkg/certs"

"github.com/minio/operator/pkg/controller/certificates"

certificatesV1 "k8s.io/api/certificates/v1"
Expand Down Expand Up @@ -257,8 +259,8 @@ func (c *Controller) createSecret(ctx context.Context, tenant *miniov2.Tenant, l
},
},
Data: map[string][]byte{
"private.key": pkBytes,
"public.crt": certBytes,
certs.PrivateKeyFile: pkBytes,
certs.PublicCertFile: certBytes,
},
}
_, err := c.kubeClientSet.CoreV1().Secrets(tenant.Namespace).Create(ctx, secret, metav1.CreateOptions{})
Expand Down
10 changes: 6 additions & 4 deletions pkg/controller/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,17 @@ import (
"math"
"time"

"github.com/minio/operator/pkg/certs"

miniov2 "github.com/minio/operator/pkg/apis/minio.min.io/v2"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var secretTypePublicKeyNameMap = map[string]string{
"kubernetes.io/tls": "tls.crt",
"cert-manager.io/v1": "tls.crt",
"cert-manager.io/v1alpha2": "tls.crt",
"kubernetes.io/tls": certs.TLSCertFile,
"cert-manager.io/v1": certs.TLSCertFile,
"cert-manager.io/v1alpha2": certs.TLSCertFile,
// Add newer secretTypes and their corresponding values in future
}

Expand All @@ -51,7 +53,7 @@ func (c *Controller) getCustomCertificates(ctx context.Context, tenant *miniov2.

for certType, secrets := range secretsMap {
certificates = nil
publicKey := "public.crt"
publicKey := certs.PublicCertFile
// Iterate over TLS secrets and build array of CertificateInfo structure
// that will be used to display information about certs
for _, secret := range secrets {
Expand Down
6 changes: 4 additions & 2 deletions pkg/controller/kes.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import (
"errors"
"fmt"

"github.com/minio/operator/pkg/certs"

"github.com/minio/operator/pkg/controller/certificates"

corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -326,9 +328,9 @@ func (c *Controller) getCertIdentity(ns string, cert *miniov2.LocalCertificateRe
}
// Store the Identity to be used later during KES container creation
if secret.Type == "kubernetes.io/tls" || secret.Type == "cert-manager.io/v1alpha2" || secret.Type == "cert-manager.io/v1" {
certbytes = secret.Data["tls.crt"]
certbytes = secret.Data[certs.TLSCertFile]
} else {
certbytes = secret.Data["public.crt"]
certbytes = secret.Data[certs.PublicCertFile]
}

// parse the certificate here to generate the identity for this certifcate.
Expand Down
Loading

0 comments on commit 4df07c1

Please sign in to comment.