Skip to content

Commit

Permalink
fix(database): emit an Event when database secret is mismatched
Browse files Browse the repository at this point in the history
Signed-off-by: Thuan Vo <[email protected]>
  • Loading branch information
tthvo committed May 31, 2024
1 parent 374c576 commit 47739b1
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 19 deletions.
2 changes: 1 addition & 1 deletion api/v1beta2/cryostat_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ type TargetDiscoveryOptions struct {
type DatabaseOptions struct {
// Name of the secret containing database keys. This secret must contain a CONNECTION_KEY secret which is the
// database connection password, and an ENCRYPTION_KEY secret which is the key used to encrypt sensitive data
// stored within the database, such as the target credentials keyring.
// stored within the database, such as the target credentials keyring. Cannot be updated.
// +optional
// +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:io.kubernetes:Secret"}
SecretName *string `json:"secretName,omitempty"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ metadata:
capabilities: Seamless Upgrades
categories: Monitoring, Developer Tools
containerImage: quay.io/cryostat/cryostat-operator:3.0.0-dev
createdAt: "2024-05-28T20:14:14Z"
createdAt: "2024-05-31T05:18:57Z"
description: JVM monitoring and profiling tool
operatorframework.io/initialization-resource: |-
{
Expand Down Expand Up @@ -580,6 +580,7 @@ spec:
contain a CONNECTION_KEY secret which is the database connection password,
and an ENCRYPTION_KEY secret which is the key used to encrypt sensitive
data stored within the database, such as the target credentials keyring.
Cannot be updated.
displayName: Secret Name
path: databaseOptions.secretName
x-descriptors:
Expand Down
2 changes: 1 addition & 1 deletion bundle/manifests/operator.cryostat.io_cryostats.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5212,7 +5212,7 @@ spec:
secret must contain a CONNECTION_KEY secret which is the database
connection password, and an ENCRYPTION_KEY secret which is the
key used to encrypt sensitive data stored within the database,
such as the target credentials keyring.
such as the target credentials keyring. Cannot be updated.
type: string
type: object
enableCertManager:
Expand Down
2 changes: 1 addition & 1 deletion config/crd/bases/operator.cryostat.io_cryostats.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5202,7 +5202,7 @@ spec:
secret must contain a CONNECTION_KEY secret which is the database
connection password, and an ENCRYPTION_KEY secret which is the
key used to encrypt sensitive data stored within the database,
such as the target credentials keyring.
such as the target credentials keyring. Cannot be updated.
type: string
type: object
enableCertManager:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ spec:
contain a CONNECTION_KEY secret which is the database connection password,
and an ENCRYPTION_KEY secret which is the key used to encrypt sensitive
data stored within the database, such as the target credentials keyring.
Cannot be updated.
displayName: Secret Name
path: databaseOptions.secretName
x-descriptors:
Expand Down
43 changes: 28 additions & 15 deletions internal/controllers/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ package controllers

import (
"context"
"errors"
"fmt"

"github.com/cryostatio/cryostat-operator/internal/controllers/constants"
"github.com/cryostatio/cryostat-operator/internal/controllers/model"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)
Expand Down Expand Up @@ -57,23 +58,35 @@ func (r *Reconciler) reconcileAuthProxyCookieSecret(ctx context.Context, cr *mod
})
}

// databaseSecretNameSuffix is the suffix to be appended to the name of a
// Cryostat CR to name its database secret
const databaseSecretNameSuffix = "-db"
const (
// The suffix to be appended to the name of a Cryostat CR to name its database secret
databaseSecretNameSuffix = "-db"
eventDatabaseSecretMismatchedType = "DatabaseSecretMismatched"
eventDatabaseMismatchMsg = "\"databaseOptions.secretName\" field cannot be updated, please revert its value or re-create this Cryostat custom resource"
)

var errDatabaseSecretUpdated = errors.New("database secret cannot be updated, but another secret is specified")

func (r *Reconciler) reconcileDatabaseConnectionSecret(ctx context.Context, cr *model.CryostatInstance) error {
var secretName string
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: cr.Name + databaseSecretNameSuffix,
Namespace: cr.InstallNamespace,
},
}
secretName := secret.Name
secretProvided := cr.Spec.DatabaseOptions != nil && cr.Spec.DatabaseOptions.SecretName != nil
if secretProvided {
// Do not delete default secret to allow reverting to use default if needed
secretName = *cr.Spec.DatabaseOptions.SecretName
} else {
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: cr.Name + databaseSecretNameSuffix,
Namespace: cr.InstallNamespace,
},
}
}

// If the CR status contains the secret name, emit an Event in case the configured secret's name does not match.
if len(cr.Status.DatabaseSecret) > 0 && cr.Status.DatabaseSecret != secretName {
r.EventRecorder.Event(cr.Object, corev1.EventTypeWarning, eventDatabaseSecretMismatchedType, eventDatabaseMismatchMsg)
return errDatabaseSecretUpdated
}

if !secretProvided {
err := r.createOrUpdateSecret(ctx, secret, cr.Object, func() error {
if secret.StringData == nil {
secret.StringData = map[string]string{}
Expand All @@ -90,8 +103,8 @@ func (r *Reconciler) reconcileDatabaseConnectionSecret(ctx context.Context, cr *
if err != nil {
return err
}
secretName = secret.Name
}

cr.Status.DatabaseSecret = secretName
return r.Client.Status().Update(ctx, cr.Object)
}
Expand Down Expand Up @@ -150,7 +163,7 @@ func (r *Reconciler) createOrUpdateSecret(ctx context.Context, secret *corev1.Se

func (r *Reconciler) deleteSecret(ctx context.Context, secret *corev1.Secret) error {
err := r.Client.Delete(ctx, secret)
if err != nil && !errors.IsNotFound(err) {
if err != nil && !kerrors.IsNotFound(err) {
r.Log.Error(err, "Could not delete secret", "name", secret.Name, "namespace", secret.Namespace)
return err
}
Expand Down

0 comments on commit 47739b1

Please sign in to comment.