Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/v1/tigerastatus_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type TigeraStatusStatus struct {
// +kubebuilder:printcolumn:name="Progressing",type="string",JSONPath=".status.conditions[?(@.type=='Progressing')].status",description="Whether the component is processing changes."
// +kubebuilder:printcolumn:name="Degraded",type="string",JSONPath=".status.conditions[?(@.type=='Degraded')].status",description="Whether the component is degraded."
// +kubebuilder:printcolumn:name="Since",type="date",JSONPath=".status.conditions[?(@.type=='Available')].lastTransitionTime",description="The time the component's Available status last changed."
// +kubebuilder:printcolumn:name="Message",type="string",JSONPath=".status.conditions[?(@.type=='Degraded')].message",description="Error message when the component is degraded.",priority=0
type TigeraStatus struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Expand Down
13 changes: 9 additions & 4 deletions pkg/common/components.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022-2024 Tigera, Inc. All rights reserved.
// Copyright (c) 2022-2026 Tigera, Inc. All rights reserved.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -22,17 +22,22 @@ import (

// MergeMaps merges current and desired maps. If both current and desired maps contain the same key, the
// desired map's value is used.
// MergeMaps does not copy hash.operator.tigera.io annotations from the current map, since those are managed by the operator.
// MergeMaps does not copy operator-managed annotations from the current map.
func MergeMaps(current, desired map[string]string) map[string]string {
for k, v := range current {
// Copy over key/value that should be copied.
if _, ok := desired[k]; !ok && !strings.Contains(k, "hash.operator.tigera.io") {
if _, ok := desired[k]; !ok && !isOperatorManaged(k) {
desired[k] = v
}
}
return desired
}

// isOperatorManaged returns true if the given annotation key is managed by the operator
// and should not be copied from the current map during merges.
func isOperatorManaged(key string) bool {
return strings.Contains(key, "operator.tigera.io")
}

// MapExistsOrInitialize returns the given map if non-nil or returns an empty map.
func MapExistsOrInitialize(m map[string]string) map[string]string {
if m != nil {
Expand Down
9 changes: 8 additions & 1 deletion pkg/controller/apiserver/apiserver_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ func (r *ReconcileAPIServer) Reconcile(ctx context.Context, request reconcile.Re

var components []render.Component

var webhooksTLS certificatemanagement.KeyPairInterface
certKeyPairOptions := []rcertificatemanagement.KeyPairOption{
rcertificatemanagement.NewKeyPairOption(tlsSecret, true, true),
}
Expand All @@ -481,7 +482,7 @@ func (r *ReconcileAPIServer) Reconcile(ctx context.Context, request reconcile.Re
//
// The network policy is included within the webhooks component so it is reconciled alongside
// the Deployment. The TLS keypair is provisioned by the CertificateManagement component below.
webhooksTLS, err := certificateManager.GetOrCreateKeyPair(
webhooksTLS, err = certificateManager.GetOrCreateKeyPair(
r.client,
webhooks.WebhooksTLSSecretName,
common.OperatorNamespace(),
Expand Down Expand Up @@ -538,6 +539,12 @@ func (r *ReconcileAPIServer) Reconcile(ctx context.Context, request reconcile.Re
}
}

// Check BYO certificate expiry warnings.
certificatemanagement.CheckKeyPairWarnings(map[string]certificatemanagement.KeyPairInterface{
render.CalicoAPIServerTLSSecretName: tlsSecret,
webhooks.WebhooksTLSSecretName: webhooksTLS,
}, r.status)

// Clear the degraded bit if we've reached this far.
r.status.ClearDegraded()

Expand Down
2 changes: 2 additions & 0 deletions pkg/controller/apiserver/apiserver_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ var _ = Describe("apiserver controller tests", func() {
mockStatus.On("IsAvailable").Return(true)
mockStatus.On("OnCRFound").Return()
mockStatus.On("ClearDegraded")
mockStatus.On("SetWarning", mock.Anything, mock.Anything).Return()
mockStatus.On("ClearWarning", mock.Anything).Return()
mockStatus.On("AddCertificateSigningRequests", mock.Anything)
mockStatus.On("RemoveCertificateSigningRequests", mock.Anything)
mockStatus.On("RemoveDeployments", mock.Anything)
Expand Down
5 changes: 5 additions & 0 deletions pkg/controller/authentication/authentication_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,11 @@ func (r *ReconcileAuthentication) Reconcile(ctx context.Context, request reconci
}
}

// Check BYO certificate expiry warnings.
certificatemanagement.CheckKeyPairWarnings(map[string]certificatemanagement.KeyPairInterface{
render.DexTLSSecretName: tlsKeyPair,
}, r.status)

// Clear the degraded bit if we've reached this far.
r.status.ClearDegraded()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ var _ = Describe("authentication controller tests", func() {
mockStatus.On("IsAvailable").Return(true)
mockStatus.On("OnCRFound").Return()
mockStatus.On("ClearDegraded")
mockStatus.On("SetWarning", mock.Anything, mock.Anything).Return()
mockStatus.On("ClearWarning", mock.Anything).Return()
mockStatus.On("SetDegraded", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return()
mockStatus.On("ReadyToMonitor")
mockStatus.On("OnCRNotFound").Return()
Expand Down Expand Up @@ -489,6 +491,8 @@ var _ = Describe("authentication controller tests", func() {

mockStatus = &status.MockStatus{}
mockStatus.On("OnCRFound").Return()
mockStatus.On("SetWarning", mock.Anything, mock.Anything).Return().Maybe()
mockStatus.On("ClearWarning", mock.Anything).Return().Maybe()
r = &ReconcileAuthentication{
client: cli,
scheme: scheme,
Expand Down
46 changes: 46 additions & 0 deletions pkg/controller/certificatemanager/certificatemanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,52 @@ var _ = Describe("Test CertificateManagement suite", func() {
Expect(len(keyPair.HashAnnotationValue())).NotTo(BeNil())
})

It("should add cert metadata labels and annotations to the secret", func() {
By("creating a key pair signed by certificateManager")
keyPair, err := certificateManager.GetOrCreateKeyPair(cli, appSecretName, appNs, appDNSNames)
Expect(err).NotTo(HaveOccurred())
secret := keyPair.Secret(appNs)

By("verifying the signer label is set")
Expect(secret.Labels).To(HaveKey("certificates.operator.tigera.io/signer"))
signerLabel := secret.Labels["certificates.operator.tigera.io/signer"]
Expect(signerLabel).To(ContainSubstring("tigera-operator-signer"))

By("verifying cert metadata annotations are present and correct")
Expect(secret.Annotations).To(HaveKey("certificates.operator.tigera.io/issuer"))
Expect(secret.Annotations).To(HaveKey("certificates.operator.tigera.io/signer"))
Expect(secret.Annotations).To(HaveKey("certificates.operator.tigera.io/expiry"))
Expect(secret.Annotations["certificates.operator.tigera.io/issuer"]).To(ContainSubstring("tigera-operator-signer"))
Expect(secret.Annotations["certificates.operator.tigera.io/signer"]).To(Equal(secret.Annotations["certificates.operator.tigera.io/issuer"]))
Expect(secret.Annotations["certificates.operator.tigera.io/expiry"]).To(MatchRegexp(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$`))

By("verifying DNS names annotation contains expected names")
Expect(secret.Annotations).To(HaveKey("certificates.operator.tigera.io/dns-names"))
Expect(secret.Annotations["certificates.operator.tigera.io/dns-names"]).To(ContainSubstring(appSecretName))

By("verifying the hash annotation is on the secret")
Expect(secret.Annotations).To(HaveKey(keyPair.HashAnnotationKey()))
Expect(secret.Annotations[keyPair.HashAnnotationKey()]).To(Equal(keyPair.HashAnnotationValue()))
})

It("should add cert metadata for BYO secrets", func() {
By("creating a BYO secret and fetching it via certificateManager")
Expect(cli.Create(ctx, byoSecret)).NotTo(HaveOccurred())
keyPair, err := certificateManager.GetOrCreateKeyPair(cli, appSecretName, appNs, appDNSNames)
Expect(err).NotTo(HaveOccurred())
Expect(keyPair.BYO()).To(BeTrue())
secret := keyPair.Secret(appNs)

By("verifying the signer label reflects the BYO CA")
Expect(secret.Labels).To(HaveKey("certificates.operator.tigera.io/signer"))
Expect(secret.Labels["certificates.operator.tigera.io/signer"]).To(ContainSubstring("byo-ca"))

By("verifying cert metadata annotations reflect the BYO certificate")
Expect(secret.Annotations).To(HaveKey("certificates.operator.tigera.io/issuer"))
Expect(secret.Annotations["certificates.operator.tigera.io/issuer"]).To(ContainSubstring("byo-ca"))
Expect(secret.Annotations).To(HaveKey("certificates.operator.tigera.io/expiry"))
})

It("renders the right spec for certificate management", func() {
By("creating a key pair w/ certificate management")
installation.CertificateManagement = cm
Expand Down
9 changes: 9 additions & 0 deletions pkg/controller/compliance/compliance_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,15 @@ func (r *ReconcileCompliance) Reconcile(ctx context.Context, request reconcile.R
return reconcile.Result{}, nil
}

// Check BYO certificate expiry warnings.
certificatemanagement.CheckKeyPairWarnings(map[string]certificatemanagement.KeyPairInterface{
render.ComplianceServerCertSecret: complianceServerKeyPair,
render.ComplianceSnapshotterSecret: snapshotterKeyPair.Interface,
render.ComplianceBenchmarkerSecret: benchmarkerKeyPair.Interface,
render.ComplianceReporterSecret: reporterKeyPair.Interface,
render.ComplianceControllerSecret: controllerKeyPair.Interface,
}, r.status)

// Clear the degraded bit if we've reached this far.
r.status.ClearDegraded()

Expand Down
2 changes: 2 additions & 0 deletions pkg/controller/compliance/compliance_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ var _ = Describe("Compliance controller tests", func() {
mockStatus.On("OnCRFound").Return()
mockStatus.On("AddCertificateSigningRequests", mock.Anything).Return()
mockStatus.On("ClearDegraded")
mockStatus.On("SetWarning", mock.Anything, mock.Anything).Return()
mockStatus.On("ClearWarning", mock.Anything).Return()
mockStatus.On("ReadyToMonitor")
mockStatus.On("SetMetaData", mock.Anything).Return()

Expand Down
9 changes: 9 additions & 0 deletions pkg/controller/installation/core_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1696,6 +1696,15 @@ func (r *ReconcileInstallation) Reconcile(ctx context.Context, request reconcile
// Tell the status manager that we're ready to monitor the resources we've told it about and receive statuses.
r.status.ReadyToMonitor()

// Check BYO certificate expiry warnings and propagate them to the status manager.
certificatemanagement.CheckKeyPairWarnings(map[string]certificatemanagement.KeyPairInterface{
render.TyphaTLSSecretName: typhaNodeTLS.TyphaSecret,
render.NodeTLSSecretName: typhaNodeTLS.NodeSecret,
render.TyphaTLSSecretName + render.TyphaNonClusterHostSuffix: typhaNodeTLS.TyphaSecretNonClusterHost,
render.NodePrometheusTLSServerSecret: nodePrometheusTLS,
kubecontrollers.KubeControllerPrometheusTLSSecret: kubeControllerTLS,
}, r.status)

// We can clear the degraded state now since as far as we know everything is in order.
r.status.ClearDegraded()

Expand Down
10 changes: 10 additions & 0 deletions pkg/controller/installation/core_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ var _ = Describe("Testing core-controller installation", func() {
mockStatus.On("IsAvailable").Return(true)
mockStatus.On("OnCRFound").Return()
mockStatus.On("ClearDegraded")
mockStatus.On("SetWarning", mock.Anything, mock.Anything).Return()
mockStatus.On("ClearWarning", mock.Anything).Return()
mockStatus.On("AddCertificateSigningRequests", mock.Anything)
mockStatus.On("RemoveCertificateSigningRequests", mock.Anything)
mockStatus.On("ReadyToMonitor")
Expand Down Expand Up @@ -785,6 +787,8 @@ var _ = Describe("Testing core-controller installation", func() {
mockStatus.On("IsAvailable").Return(true)
mockStatus.On("OnCRFound").Return()
mockStatus.On("ClearDegraded")
mockStatus.On("SetWarning", mock.Anything, mock.Anything).Return()
mockStatus.On("ClearWarning", mock.Anything).Return()
mockStatus.On("AddCertificateSigningRequests", mock.Anything)
mockStatus.On("RemoveCertificateSigningRequests", mock.Anything)
mockStatus.On("ReadyToMonitor")
Expand Down Expand Up @@ -1004,6 +1008,8 @@ var _ = Describe("Testing core-controller installation", func() {
mockStatus.On("IsAvailable").Return(true)
mockStatus.On("OnCRFound").Return()
mockStatus.On("ClearDegraded")
mockStatus.On("SetWarning", mock.Anything, mock.Anything).Return()
mockStatus.On("ClearWarning", mock.Anything).Return()
mockStatus.On("AddCertificateSigningRequests", mock.Anything)
mockStatus.On("ReadyToMonitor")
mockStatus.On("SetMetaData", mock.Anything).Return()
Expand Down Expand Up @@ -2139,6 +2145,8 @@ var _ = Describe("Testing core-controller installation", func() {
mockStatus.On("IsAvailable").Return(true)
mockStatus.On("OnCRFound").Return()
mockStatus.On("ClearDegraded")
mockStatus.On("SetWarning", mock.Anything, mock.Anything).Return()
mockStatus.On("ClearWarning", mock.Anything).Return()
mockStatus.On("AddCertificateSigningRequests", mock.Anything)
mockStatus.On("RemoveCertificateSigningRequests", mock.Anything)
mockStatus.On("ReadyToMonitor")
Expand Down Expand Up @@ -2273,6 +2281,8 @@ var _ = Describe("Testing core-controller installation", func() {
mockStatus.On("IsAvailable").Return(true)
mockStatus.On("OnCRFound").Return()
mockStatus.On("ClearDegraded")
mockStatus.On("SetWarning", mock.Anything, mock.Anything).Return()
mockStatus.On("ClearWarning", mock.Anything).Return()
mockStatus.On("AddCertificateSigningRequests", mock.Anything)
mockStatus.On("RemoveCertificateSigningRequests", mock.Anything)
mockStatus.On("ReadyToMonitor")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ func (r *ReconcileIntrusionDetection) Reconcile(ctx context.Context, request rec
intrusionDetectionComponent,
}

var dpiKeyPair certificatemanagement.KeyPairInterface
if !r.opts.MultiTenant {
// FIXME: core controller creates TyphaNodeTLSConfig, this controller should only get it.
// But changing the call from GetOrCreateTyphaNodeTLSConfig() to GetTyphaNodeTLSConfig()
Expand All @@ -511,7 +512,7 @@ func (r *ReconcileIntrusionDetection) Reconcile(ctx context.Context, request rec
typhaNodeTLS.TrustedBundle.AddCertificates(linseedCertificate)

// dpiKeyPair is the key pair dpi presents to identify itself
dpiKeyPair, err := certificateManager.GetOrCreateKeyPair(r.client, render.DPITLSSecretName, helper.TruthNamespace(), []string{render.IntrusionDetectionTLSSecretName})
dpiKeyPair, err = certificateManager.GetOrCreateKeyPair(r.client, render.DPITLSSecretName, helper.TruthNamespace(), []string{render.IntrusionDetectionTLSSecretName})
if err != nil {
r.status.SetDegraded(operatorv1.ResourceCreateError, "Error creating TLS certificate", err, reqLogger)
return reconcile.Result{}, err
Expand Down Expand Up @@ -581,6 +582,12 @@ func (r *ReconcileIntrusionDetection) Reconcile(ctx context.Context, request rec
return reconcile.Result{}, nil
}

// Check BYO certificate expiry warnings.
certificatemanagement.CheckKeyPairWarnings(map[string]certificatemanagement.KeyPairInterface{
render.IntrusionDetectionTLSSecretName: intrusionDetectionKeyPair,
render.DPITLSSecretName: dpiKeyPair,
}, r.status)

// Clear the degraded bit if we've reached this far.
r.status.ClearDegraded()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ var _ = Describe("IntrusionDetection controller tests", func() {
mockStatus.On("IsAvailable").Return(true)
mockStatus.On("OnCRFound").Return()
mockStatus.On("ClearDegraded")
mockStatus.On("SetWarning", mock.Anything, mock.Anything).Return()
mockStatus.On("ClearWarning", mock.Anything).Return()
mockStatus.On("SetDegraded", operatorv1.InvalidConfigurationError, mock.AnythingOfType("string"), mock.Anything, mock.Anything).Return().Maybe()
mockStatus.On("SetDegraded", operatorv1.ResourceReadError, mock.AnythingOfType("string"), mock.Anything, mock.Anything).Return().Maybe()
mockStatus.On("SetDegraded", operatorv1.ResourceUpdateError, mock.AnythingOfType("string"), mock.Anything, mock.Anything).Return().Maybe()
Expand Down
6 changes: 6 additions & 0 deletions pkg/controller/logcollector/logcollector_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,12 @@ func (r *ReconcileLogCollector) Reconcile(ctx context.Context, request reconcile
return reconcile.Result{}, nil
}

// Check BYO certificate expiry warnings.
certificatemanagement.CheckKeyPairWarnings(map[string]certificatemanagement.KeyPairInterface{
render.FluentdPrometheusTLSSecretName: fluentdKeyPair,
render.EKSLogForwarderTLSSecretName: eksLogForwarderKeyPair,
}, r.status)

// Clear the degraded bit if we've reached this far.
r.status.ClearDegraded()

Expand Down
2 changes: 2 additions & 0 deletions pkg/controller/logcollector/logcollector_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ var _ = Describe("LogCollector controller tests", func() {
mockStatus.On("IsAvailable").Return(true)
mockStatus.On("OnCRFound").Return()
mockStatus.On("ClearDegraded")
mockStatus.On("SetWarning", mock.Anything, mock.Anything).Return()
mockStatus.On("ClearWarning", mock.Anything).Return()
mockStatus.On("SetDegraded", operatorv1.ResourceNotReady, "Waiting for LicenseKeyAPI to be ready", mock.Anything, mock.Anything).Return().Maybe()
mockStatus.On("ReadyToMonitor")
mockStatus.On("SetMetaData", mock.Anything).Return()
Expand Down
7 changes: 7 additions & 0 deletions pkg/controller/manager/manager_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,13 @@ func (r *ReconcileManager) Reconcile(ctx context.Context, request reconcile.Requ
}
}

// Check BYO certificate expiry warnings.
certificatemanagement.CheckKeyPairWarnings(map[string]certificatemanagement.KeyPairInterface{
render.ManagerTLSSecretName: tlsSecret,
render.ManagerInternalTLSSecretName: internalTrafficSecret,
render.VoltronLinseedTLS: linseedVoltronServerCert,
}, r.status)

// Clear the degraded bit if we've reached this far.
r.status.ClearDegraded()
instance.Status.State = operatorv1.TigeraStatusReady
Expand Down
8 changes: 8 additions & 0 deletions pkg/controller/manager/manager_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ var _ = Describe("Manager controller tests", func() {
mockStatus.On("IsAvailable").Return(true)
mockStatus.On("OnCRFound").Return()
mockStatus.On("ClearDegraded")
mockStatus.On("SetWarning", mock.Anything, mock.Anything).Return()
mockStatus.On("ClearWarning", mock.Anything).Return()
mockStatus.On("SetDegraded", operatorv1.ResourceNotReady, "Waiting for LicenseKeyAPI to be ready", mock.Anything, mock.Anything).Return().Maybe()
mockStatus.On("SetDegraded", operatorv1.ResourceNotReady, "Waiting for secret 'tigera-packetcapture-server-tls' to become available", mock.Anything, mock.Anything).Return().Maybe()
mockStatus.On("SetDegraded", operatorv1.ResourceNotReady, "Waiting for secret 'tigera-secure-linseed-cert' to become available", mock.Anything, mock.Anything).Return().Maybe()
Expand Down Expand Up @@ -525,6 +527,8 @@ var _ = Describe("Manager controller tests", func() {
mockStatus.On("IsAvailable").Return(true)
mockStatus.On("OnCRFound").Return()
mockStatus.On("ClearDegraded")
mockStatus.On("SetWarning", mock.Anything, mock.Anything).Return()
mockStatus.On("ClearWarning", mock.Anything).Return()
mockStatus.On("SetDegraded", operatorv1.ResourceNotReady, "Waiting for LicenseKeyAPI to be ready", mock.Anything, mock.Anything).Return().Maybe()
mockStatus.On("SetDegraded", operatorv1.ResourceNotReady, "Waiting for secret 'calico-node-prometheus-tls' to become available", mock.Anything, mock.Anything).Return().Maybe()
mockStatus.On("SetDegraded", operatorv1.ResourceNotReady, "Waiting for secret 'tigera-packetcapture-server-tls' to become available", mock.Anything, mock.Anything).Return().Maybe()
Expand Down Expand Up @@ -763,6 +767,8 @@ var _ = Describe("Manager controller tests", func() {
mockStatus.On("AddDeployments", mock.Anything)
mockStatus.On("RemoveDeployments", []types.NamespacedName{{Name: render.LegacyManagerDeploymentName, Namespace: render.LegacyManagerNamespace}}).Return()
mockStatus.On("ClearDegraded")
mockStatus.On("SetWarning", mock.Anything, mock.Anything).Return().Maybe()
mockStatus.On("ClearWarning", mock.Anything).Return().Maybe()
mockStatus.On("SetDegraded", operatorv1.ResourceNotReady, "Compliance is not ready", mock.Anything, mock.Anything).Return().Maybe()
mockStatus.On("RemoveCertificateSigningRequests", mock.Anything)
mockStatus.On("ReadyToMonitor")
Expand Down Expand Up @@ -1192,6 +1198,8 @@ var _ = Describe("Manager controller tests", func() {
mockStatus.On("RemoveDeployments", []types.NamespacedName{{Name: render.LegacyManagerDeploymentName, Namespace: tenantBNamespace}}).Return()
mockStatus.On("ReadyToMonitor")
mockStatus.On("ClearDegraded")
mockStatus.On("SetWarning", mock.Anything, mock.Anything).Return()
mockStatus.On("ClearWarning", mock.Anything).Return()
mockStatus.On("IsAvailable").Return(true)

r.opts.MultiTenant = true
Expand Down
Loading
Loading