Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable client-side CQL encryption in Stargate if it is configured on the cluster (fixes #722) #733

Merged
merged 3 commits into from
Oct 21, 2022
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
3 changes: 2 additions & 1 deletion CHANGELOG/CHANGELOG-1.4.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ When cutting a new release, update the `unreleased` heading to the tag being gen
* [FEATURE] [#599](https://github.com/k8ssandra/k8ssandra-operator/issues/599) Introduce a secrets provider setting in the CRD
* [FEATURE] [#728](https://github.com/k8ssandra/k8ssandra-operator/issues/728) Add token generation utility
* [FEATURE] [#724](https://github.com/k8ssandra/k8ssandra-operator/issues/724) Ability to provide per-node configuration
[FEATURE] [#718](https://github.com/k8ssandra/k8ssandra-operator/issues/718) Make keystore-password, keystore, truststore keys in secret configurable
[FEATURE] [#718](https://github.com/k8ssandra/k8ssandra-operator/issues/718) Make keystore-password, keystore, truststore keys in secret configurable
* [BUGFIX] [#722](https://github.com/k8ssandra/k8ssandra-operator/issues/722) Enable client-side CQL encryption in Stargate if it is configured on the cluster
2 changes: 1 addition & 1 deletion apis/stargate/v1alpha1/stargate_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type StargateTemplate struct {
// ContainerImage is the image characteristics to use for Stargate containers. Leave nil
// to use a default image.
// +optional
// +kubebuilder:default={repository:"stargateio", tag:"v1.0.45"}
// +kubebuilder:default={repository:"stargateio", tag:"v1.0.66"}
Copy link
Contributor Author

@olim7t olim7t Oct 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-Dstargate.cql.config_path was introduced in 1.0.64. I went with the latest.

ContainerImage *images.Image `json:"containerImage,omitempty"`

// ServiceAccount is the service account name to use for Stargate pods.
Expand Down
6 changes: 3 additions & 3 deletions config/crd/bases/k8ssandra.io_k8ssandraclusters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8473,7 +8473,7 @@ spec:
containerImage:
default:
repository: stargateio
tag: v1.0.45
tag: v1.0.66
description: ContainerImage is the image characteristics
to use for Stargate containers. Leave nil to use a
default image.
Expand Down Expand Up @@ -9898,7 +9898,7 @@ spec:
containerImage:
default:
repository: stargateio
tag: v1.0.45
tag: v1.0.66
description: ContainerImage is the image characteristics
to use for Stargate containers. Leave nil to
use a default image.
Expand Down Expand Up @@ -18525,7 +18525,7 @@ spec:
containerImage:
default:
repository: stargateio
tag: v1.0.45
tag: v1.0.66
description: ContainerImage is the image characteristics to use
for Stargate containers. Leave nil to use a default image.
properties:
Expand Down
4 changes: 2 additions & 2 deletions config/crd/bases/stargate.k8ssandra.io_stargates.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@ spec:
containerImage:
default:
repository: stargateio
tag: v1.0.45
tag: v1.0.66
description: ContainerImage is the image characteristics to use for
Stargate containers. Leave nil to use a default image.
properties:
Expand Down Expand Up @@ -2265,7 +2265,7 @@ spec:
containerImage:
default:
repository: stargateio
tag: v1.0.45
tag: v1.0.66
description: ContainerImage is the image characteristics to
use for Stargate containers. Leave nil to use a default image.
properties:
Expand Down
65 changes: 43 additions & 22 deletions controllers/stargate/stargate_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,17 @@ func (r *StargateReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
}

// if a configmap is specified, we need to read its content to merge it with the generated one
userConfigMapContent := ""
userStargateCassandraYaml := ""
userStargateCqlYaml := ""
if stargate.Spec.CassandraConfigMapRef != nil {
userConfigMap := &corev1.ConfigMap{}
configMapKey := types.NamespacedName{Namespace: req.Namespace, Name: stargate.Spec.CassandraConfigMapRef.Name}
err := r.Get(ctx, configMapKey, userConfigMap)
if err != nil {
return ctrl.Result{}, err
}
userConfigMapContent = userConfigMap.Data["cassandra.yaml"]
userStargateCassandraYaml = userConfigMap.Data["cassandra.yaml"]
userStargateCqlYaml = userConfigMap.Data[stargateutil.CqlConfigName]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to think of a case where we'd get a user input that should go into that Stargate cql config file.
Which settings other than client_encryption_options have to be passed through this file?

}

logger.Info("Reconciling Stargate configmap")
Expand All @@ -154,7 +156,7 @@ func (r *StargateReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
}
}

if stargateConfigResult, err := r.reconcileStargateConfigMap(ctx, stargate, dcConfig, userConfigMapContent, req.Namespace, *actualDc, logger); err != nil {
if stargateConfigResult, err := r.reconcileStargateConfigMap(ctx, stargate, dcConfig, userStargateCassandraYaml, userStargateCqlYaml, req.Namespace, *actualDc, logger); err != nil {
return ctrl.Result{}, err
} else {
if stargateConfigResult.Requeue {
Expand Down Expand Up @@ -398,42 +400,39 @@ func (r *StargateReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
func (r *StargateReconciler) reconcileStargateConfigMap(
ctx context.Context,
stargateObject *api.Stargate,
desiredConfig map[string]interface{},
userConfigMapContent string,
dcConfig map[string]interface{},
userCassandraYaml, userCqlYaml string,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit of naming/refactoring in this function, because it was getting really confusing with two files.

namespace string,
dc cassdcapi.CassandraDatacenter,
logger logr.Logger,
) (ctrl.Result, error) {
logger.Info(fmt.Sprintf("Reconciling Stargate Cassandra yaml configMap on namespace %s for cluster %s and dc %s", namespace, dc.Spec.ClusterName, dc.Name))
var filteredCassandraConfig map[string]interface{}
desiredCassandraYaml, exists := desiredConfig["cassandra-yaml"]
if exists {
filteredCassandraConfig = stargate.FilterYamlConfig(desiredCassandraYaml.(map[string]interface{}))
}

configYamlString := ""
if len(filteredCassandraConfig) > 0 {
if configYaml, err := yaml.Marshal(filteredCassandraConfig); err != nil {
return ctrl.Result{}, err
} else {
configYamlString = string(configYaml)
}
var cassandraYaml, cqlYaml string
var err error
if cassandraYaml, err = reconcileStargateConfigFile(userCassandraYaml, dcConfig, stargate.CassandraYamlRetainedSettings); err != nil {
return ctrl.Result{}, err
}
if cqlYaml, err = reconcileStargateConfigFile(userCqlYaml, dcConfig, stargate.CqlYamlRetainedSettings); err != nil {
return ctrl.Result{}, err
}
if len(cqlYaml) == 0 {
// The Stargate code fails on an empty file. Replace with this which is valid YAML:
cqlYaml = "{}"
}

mergedConfigMap := stargate.MergeConfigMaps(userConfigMapContent, configYamlString)

configMapKey := client.ObjectKey{
Namespace: namespace,
Name: stargate.GeneratedConfigMapName(dc.Spec.ClusterName, dc.Name),
}

logger = logger.WithValues("StargateConfigMap", configMapKey)
desiredConfigMap := stargate.CreateStargateConfigMap(namespace, mergedConfigMap, dc)
desiredConfigMap := stargate.CreateStargateConfigMap(namespace, cassandraYaml, cqlYaml, dc)
// Compute a hash which will allow to compare desired and actual configMaps
annotations.AddHashAnnotation(desiredConfigMap)
actualConfigMap := &corev1.ConfigMap{}

if err := r.Get(ctx, configMapKey, actualConfigMap); err != nil {
if err = r.Get(ctx, configMapKey, actualConfigMap); err != nil {
if errors.IsNotFound(err) {
if err = controllerutil.SetControllerReference(stargateObject, desiredConfigMap, r.Scheme); err != nil {
return ctrl.Result{}, err
Expand All @@ -454,7 +453,7 @@ func (r *StargateReconciler) reconcileStargateConfigMap(
resourceVersion := actualConfigMap.GetResourceVersion()
desiredConfigMap.DeepCopyInto(actualConfigMap)
actualConfigMap.SetResourceVersion(resourceVersion)
if err := r.Update(ctx, actualConfigMap); err != nil {
if err = r.Update(ctx, actualConfigMap); err != nil {
logger.Error(err, "Failed to update Stargate ConfigMap resource")
return ctrl.Result{}, err
}
Expand All @@ -464,6 +463,28 @@ func (r *StargateReconciler) reconcileStargateConfigMap(
return ctrl.Result{}, nil
}

// reconcileStargateConfigFile builds a Stargate config file from two different sources: userConfig is the user-provided
// config passed via cassandraConfigMapRef in the Stargate spec; dcConfig is the DC-level config from the
// CassandraDatacenter spec, of which we'll only keep retainedOptions.
func reconcileStargateConfigFile(
userConfig string, dcConfig map[string]interface{}, retainedOptions []string,
) (string, error) {
var dcYaml map[string]interface{}
dcFullYaml, exists := dcConfig["cassandra-yaml"]
if exists {
dcYaml = stargate.FilterConfig(dcFullYaml.(map[string]interface{}), retainedOptions)
}
dcYamlString := ""
if len(dcYaml) > 0 {
if out, err := yaml.Marshal(dcYaml); err != nil {
return "", err
} else {
dcYamlString = string(out)
}
}
return stargate.MergeYamlString(userConfig, dcYamlString), nil
}

// SetupWithManager sets up the controller with the Manager.
func (r *StargateReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
Expand Down
9 changes: 6 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/Masterminds/semver/v3 v3.1.1
github.com/apache/tinkerpop/gremlin-go v0.0.0-20220530191148-29272fa563ec
github.com/bombsimon/logrusr/v2 v2.0.1
github.com/datastax/go-cassandra-native-protocol v0.0.0-20210829124742-a80a54434112
github.com/datastax/go-cassandra-native-protocol v0.0.0-20220706104457-5e8aad05cf90
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull in TLS support.

github.com/davecgh/go-spew v1.1.1
github.com/go-logr/logr v1.2.3
github.com/go-logr/zapr v1.2.3
Expand All @@ -20,8 +20,9 @@ require (
github.com/robfig/cron/v3 v3.0.1
github.com/rs/zerolog v1.20.0
github.com/sirupsen/logrus v1.8.1
github.com/square/certigo v1.16.0
github.com/stargate/stargate-grpc-go-client v0.0.0-20220822130422-9a1c6261d4fa
github.com/stretchr/testify v1.7.0
github.com/stretchr/testify v1.7.5
go.uber.org/zap v1.19.1
google.golang.org/grpc v1.40.0
google.golang.org/protobuf v1.28.0
Expand Down Expand Up @@ -57,6 +58,7 @@ require (
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.3 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/google/go-querystring v1.1.0 // indirect
Expand All @@ -72,13 +74,14 @@ require (
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nicksnyder/go-i18n/v2 v2.2.0 // indirect
github.com/pavel-v-chernykh/keystore-go v2.1.0+incompatible // indirect
github.com/pierrec/lz4/v4 v4.0.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.12.1 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.32.1 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.2.0 // indirect
github.com/stretchr/objx v0.4.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
Expand Down
Loading