Skip to content

Commit 459c2e8

Browse files
authored
CLOUDP-342363 [Search] Enterprise Server with TLS (#395)
# Summary <!-- Enter your issue summary here.--> ## Proof of Work <!-- Enter your proof that it works here.--> ## Checklist - [x] Have you linked a jira ticket and/or is the ticket in the title? - [x] Have you checked whether your jira ticket required DOCSP changes? - [x] Have you added changelog file? - use `skip-changelog` label if not needed - refer to [Changelog files and Release Notes](https://github.com/mongodb/mongodb-kubernetes/blob/master/CONTRIBUTING.md#changelog-files-and-release-notes) section in CONTRIBUTING.md for more details
1 parent 32a5c42 commit 459c2e8

File tree

13 files changed

+376
-61
lines changed

13 files changed

+376
-61
lines changed

.evergreen-tasks.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,3 +1306,8 @@ tasks:
13061306
commands:
13071307
- func: "e2e_test"
13081308

1309+
- name: e2e_search_enterprise_tls
1310+
tags: [ "patch-run" ]
1311+
commands:
1312+
- func: "e2e_test"
1313+

.evergreen.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,7 @@ task_groups:
817817
- e2e_sharded_cluster_oidc_m2m_user
818818
# MongoDBSearch test group
819819
- e2e_search_enterprise_basic
820+
- e2e_search_enterprise_tls
820821
<<: *teardown_group
821822

822823
# this task group contains just a one task, which is smoke testing whether the operator

config/crd/bases/mongodb.com_mongodbsearch.yaml

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ spec:
4949
spec:
5050
properties:
5151
persistence:
52+
description: Configure MongoDB Search's persistent volume. If not
53+
defined, the operator will request 10GB of storage.
5254
properties:
5355
multiple:
5456
properties:
@@ -95,7 +97,8 @@ spec:
9597
type: object
9698
type: object
9799
resourceRequirements:
98-
description: ResourceRequirements describes the compute resource requirements.
100+
description: Configure resource requests and limits for the MongoDB
101+
Search pods.
99102
properties:
100103
claims:
101104
description: |-
@@ -150,6 +153,8 @@ spec:
150153
type: object
151154
type: object
152155
security:
156+
description: Configure security settings of the MongoDB Search server
157+
that MongoDB database is connecting to when performing search queries.
153158
properties:
154159
tls:
155160
properties:
@@ -181,6 +186,8 @@ spec:
181186
type: object
182187
type: object
183188
source:
189+
description: MongoDB database connection details from which MongoDB
190+
Search will synchronize data to build indexes.
184191
properties:
185192
external:
186193
properties:
@@ -199,7 +206,7 @@ spec:
199206
name:
200207
type: string
201208
required:
202-
- name
209+
- name
203210
type: object
204211
tls:
205212
properties:
@@ -224,7 +231,7 @@ spec:
224231
enabled:
225232
type: boolean
226233
required:
227-
- enabled
234+
- enabled
228235
type: object
229236
type: object
230237
mongodbResourceRef:
@@ -277,6 +284,9 @@ spec:
277284
- spec
278285
type: object
279286
version:
287+
description: Optional version of MongoDB Search component (mongot).
288+
If not set, then the operator will set the most appropriate version
289+
of MongoDB Search.
280290
type: string
281291
type: object
282292
status:

controllers/operator/mongodbsearch_controller.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,21 @@ func (r *MongoDBSearchReconciler) Reconcile(ctx context.Context, request reconci
5959

6060
r.watch.AddWatchedResourceIfNotAdded(searchSource.KeyfileSecretName(), mdbSearch.Namespace, watch.Secret, mdbSearch.NamespacedName())
6161

62+
// Watch for changes in database source CA certificate secrets or configmaps
63+
tlsSourceConfig := searchSource.TLSConfig()
64+
if tlsSourceConfig != nil {
65+
for wType, resources := range tlsSourceConfig.ResourcesToWatch {
66+
for _, resource := range resources {
67+
r.watch.AddWatchedResourceIfNotAdded(resource.Name, resource.Namespace, wType, mdbSearch.NamespacedName())
68+
}
69+
}
70+
}
71+
72+
// Watch our own TLS certificate secret for changes
73+
if mdbSearch.Spec.Security.TLS.Enabled {
74+
r.watch.AddWatchedResourceIfNotAdded(mdbSearch.Spec.Security.TLS.CertificateKeySecret.Name, mdbSearch.Namespace, watch.Secret, mdbSearch.NamespacedName())
75+
}
76+
6277
reconcileHelper := search_controller.NewMongoDBSearchReconcileHelper(kubernetesClient.NewClient(r.kubeClient), mdbSearch, searchSource, r.operatorSearchConfig)
6378

6479
return reconcileHelper.Reconcile(ctx, log).ReconcileResult()

controllers/search_controller/community_search_source.go

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ import (
88
"golang.org/x/xerrors"
99
"k8s.io/apimachinery/pkg/types"
1010

11+
corev1 "k8s.io/api/core/v1"
12+
13+
"github.com/mongodb/mongodb-kubernetes/controllers/operator/watch"
1114
mdbcv1 "github.com/mongodb/mongodb-kubernetes/mongodb-community-operator/api/v1"
15+
"github.com/mongodb/mongodb-kubernetes/pkg/statefulset"
1216
"github.com/mongodb/mongodb-kubernetes/pkg/util"
1317
)
1418

@@ -32,12 +36,27 @@ func (r *CommunitySearchSource) KeyfileSecretName() string {
3236
return r.MongoDBCommunity.GetAgentKeyfileSecretNamespacedName().Name
3337
}
3438

35-
func (r *CommunitySearchSource) IsSecurityTLSConfigEnabled() bool {
36-
return r.Spec.Security.TLS.Enabled
37-
}
39+
func (r *CommunitySearchSource) TLSConfig() *TLSSourceConfig {
40+
if !r.Spec.Security.TLS.Enabled {
41+
return nil
42+
}
43+
44+
var volume corev1.Volume
45+
watchedResources := make(map[watch.Type][]types.NamespacedName)
3846

39-
func (r *CommunitySearchSource) TLSOperatorCASecretNamespacedName() types.NamespacedName {
40-
return r.MongoDBCommunity.TLSOperatorCASecretNamespacedName()
47+
if r.Spec.Security.TLS.CaCertificateSecret != nil {
48+
volume = statefulset.CreateVolumeFromSecret("ca", r.Spec.Security.TLS.CaCertificateSecret.Name)
49+
watchedResources[watch.Secret] = []types.NamespacedName{r.TLSCaCertificateSecretNamespacedName()}
50+
} else {
51+
volume = statefulset.CreateVolumeFromConfigMap("ca", r.Spec.Security.TLS.CaConfigMap.Name)
52+
watchedResources[watch.ConfigMap] = []types.NamespacedName{r.TLSConfigMapNamespacedName()}
53+
}
54+
55+
return &TLSSourceConfig{
56+
CAFileName: "ca.crt",
57+
CAVolume: volume,
58+
ResourcesToWatch: watchedResources,
59+
}
4160
}
4261

4362
func (r *CommunitySearchSource) Validate() error {

controllers/search_controller/enterprise_search_source.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"k8s.io/apimachinery/pkg/types"
1010

1111
mdbv1 "github.com/mongodb/mongodb-kubernetes/api/v1/mdb"
12+
"github.com/mongodb/mongodb-kubernetes/controllers/operator/watch"
13+
"github.com/mongodb/mongodb-kubernetes/pkg/statefulset"
1214
"github.com/mongodb/mongodb-kubernetes/pkg/util"
1315
)
1416

@@ -28,16 +30,24 @@ func (r EnterpriseResourceSearchSource) HostSeeds() []string {
2830
return seeds
2931
}
3032

31-
func (r EnterpriseResourceSearchSource) KeyfileSecretName() string {
32-
return fmt.Sprintf("%s-keyfile", r.Name)
33-
}
33+
func (r EnterpriseResourceSearchSource) TLSConfig() *TLSSourceConfig {
34+
if !r.Spec.Security.IsTLSEnabled() {
35+
return nil
36+
}
3437

35-
func (r EnterpriseResourceSearchSource) IsSecurityTLSConfigEnabled() bool {
36-
return r.Spec.Security.IsTLSEnabled()
38+
return &TLSSourceConfig{
39+
CAFileName: "ca-pem",
40+
CAVolume: statefulset.CreateVolumeFromConfigMap("ca", r.Spec.Security.TLSConfig.CA),
41+
ResourcesToWatch: map[watch.Type][]types.NamespacedName{
42+
watch.ConfigMap: {
43+
{Namespace: r.Namespace, Name: r.Spec.Security.TLSConfig.CA},
44+
},
45+
},
46+
}
3747
}
3848

39-
func (r EnterpriseResourceSearchSource) TLSOperatorCASecretNamespacedName() types.NamespacedName {
40-
return types.NamespacedName{}
49+
func (r EnterpriseResourceSearchSource) KeyfileSecretName() string {
50+
return fmt.Sprintf("%s-keyfile", r.Name)
4151
}
4252

4353
func (r EnterpriseResourceSearchSource) Validate() error {

controllers/search_controller/external_search_source.go

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"k8s.io/apimachinery/pkg/types"
55

66
searchv1 "github.com/mongodb/mongodb-kubernetes/api/v1/search"
7+
"github.com/mongodb/mongodb-kubernetes/controllers/operator/watch"
8+
"github.com/mongodb/mongodb-kubernetes/pkg/statefulset"
79
)
810

911
func NewExternalSearchSource(namespace string, spec *searchv1.ExternalMongoDBSource) SearchSourceDBResource {
@@ -20,27 +22,28 @@ func (r *externalSearchResource) Validate() error {
2022
return nil
2123
}
2224

23-
func (r *externalSearchResource) KeyfileSecretName() string {
24-
if r.spec.KeyFileSecretKeyRef != nil {
25-
return r.spec.KeyFileSecretKeyRef.Name
25+
func (r *externalSearchResource) TLSConfig() *TLSSourceConfig {
26+
if r.spec.TLS == nil || !r.spec.TLS.Enabled {
27+
return nil
2628
}
2729

28-
return ""
29-
}
30-
31-
func (r *externalSearchResource) IsSecurityTLSConfigEnabled() bool {
32-
return r.spec.TLS != nil && r.spec.TLS.Enabled
30+
return &TLSSourceConfig{
31+
CAFileName: "ca.crt",
32+
CAVolume: statefulset.CreateVolumeFromSecret("ca", r.spec.TLS.CA.Name),
33+
ResourcesToWatch: map[watch.Type][]types.NamespacedName{
34+
watch.Secret: {
35+
{Namespace: r.namespace, Name: r.spec.TLS.CA.Name},
36+
},
37+
},
38+
}
3339
}
3440

35-
func (r *externalSearchResource) TLSOperatorCASecretNamespacedName() types.NamespacedName {
36-
if r.spec.TLS != nil && r.spec.TLS.CA != nil {
37-
return types.NamespacedName{
38-
Name: r.spec.TLS.CA.Name,
39-
Namespace: r.namespace,
40-
}
41+
func (r *externalSearchResource) KeyfileSecretName() string {
42+
if r.spec.KeyFileSecretKeyRef != nil {
43+
return r.spec.KeyFileSecretKeyRef.Name
4144
}
4245

43-
return types.NamespacedName{}
46+
return ""
4447
}
4548

4649
func (r *externalSearchResource) HostSeeds() []string { return r.spec.HostAndPorts }

controllers/search_controller/mongodbsearch_reconcile_helper.go

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -261,28 +261,17 @@ func (r *MongoDBSearchReconcileHelper) ensureIngressTlsConfig(ctx context.Contex
261261
}
262262

263263
func (r *MongoDBSearchReconcileHelper) ensureEgressTlsConfig(ctx context.Context) (mongot.Modification, statefulset.Modification, error) {
264-
if !r.db.IsSecurityTLSConfigEnabled() {
264+
tlsSourceConfig := r.db.TLSConfig()
265+
if tlsSourceConfig == nil {
265266
return mongot.NOOP(), statefulset.NOOP(), nil
266267
}
267268

268-
caSecretName := r.db.TLSOperatorCASecretNamespacedName()
269-
caSecret := &corev1.Secret{}
270-
if err := r.client.Get(ctx, caSecretName, caSecret); err != nil {
271-
return nil, nil, xerrors.Errorf("error getting CA Secret %s: %w", caSecretName, err)
272-
}
273-
274-
// HACK: find a better way of getting the CA file name
275-
var caFileName string
276-
for k := range caSecret.Data {
277-
caFileName = k
278-
}
279-
280269
mongotModification := func(config *mongot.Config) {
281270
config.SyncSource.ReplicaSet.TLS = ptr.To(true)
282271
}
283272

284273
_, containerSecurityContext := podtemplatespec.WithDefaultSecurityContextsModifications()
285-
caVolume := statefulset.CreateVolumeFromSecret("ca", caSecretName.Name)
274+
caVolume := tlsSourceConfig.CAVolume
286275
trustStoreVolume := statefulset.CreateVolumeFromEmptyDir("cacerts")
287276
statefulsetModification := statefulset.WithPodSpecTemplate(podtemplatespec.Apply(
288277
podtemplatespec.WithVolume(caVolume),
@@ -300,7 +289,7 @@ func (r *MongoDBSearchReconcileHelper) ensureEgressTlsConfig(ctx context.Context
300289
fmt.Sprintf(`
301290
cp /mongot-community/bin/jdk/lib/security/cacerts /java/trust-store/cacerts
302291
/mongot-community/bin/jdk/bin/keytool -keystore /java/trust-store/cacerts -storepass changeit -noprompt -trustcacerts -importcert -alias mongodcert -file %s/%s
303-
`, tls.CAMountPath, caFileName),
292+
`, tls.CAMountPath, tlsSourceConfig.CAFileName),
304293
}),
305294
)),
306295
podtemplatespec.WithContainer(MongotContainerName, container.Apply(

controllers/search_controller/search_construction.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
searchv1 "github.com/mongodb/mongodb-kubernetes/api/v1/search"
1111
"github.com/mongodb/mongodb-kubernetes/controllers/operator/construct"
12+
"github.com/mongodb/mongodb-kubernetes/controllers/operator/watch"
1213
"github.com/mongodb/mongodb-kubernetes/mongodb-community-operator/api/v1/common"
1314
"github.com/mongodb/mongodb-kubernetes/mongodb-community-operator/pkg/kube/container"
1415
"github.com/mongodb/mongodb-kubernetes/mongodb-community-operator/pkg/kube/podtemplatespec"
@@ -31,12 +32,17 @@ const (
3132
// TODO check if we could use already existing interface (DbCommon, MongoDBStatefulSetOwner, etc.)
3233
type SearchSourceDBResource interface {
3334
KeyfileSecretName() string
34-
IsSecurityTLSConfigEnabled() bool
35-
TLSOperatorCASecretNamespacedName() types.NamespacedName
35+
TLSConfig() *TLSSourceConfig
3636
HostSeeds() []string
3737
Validate() error
3838
}
3939

40+
type TLSSourceConfig struct {
41+
CAFileName string
42+
CAVolume corev1.Volume
43+
ResourcesToWatch map[watch.Type][]types.NamespacedName
44+
}
45+
4046
// ReplicaSetOptions returns a set of options which will configure a ReplicaSet StatefulSet
4147
func CreateSearchStatefulSetFunc(mdbSearch *searchv1.MongoDBSearch, sourceDBResource SearchSourceDBResource, searchImage string) statefulset.Modification {
4248
labels := map[string]string{

docker/mongodb-kubernetes-tests/kubetester/mongodb.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,10 +278,8 @@ def configure_custom_tls(
278278
tls_cert_secret_name: str,
279279
):
280280
ensure_nested_objects(self, ["spec", "security", "tls"])
281-
self["spec"]["security"] = {
282-
"certsSecretPrefix": tls_cert_secret_name,
283-
"tls": {"enabled": True, "ca": issuer_ca_configmap_name},
284-
}
281+
self["spec"]["security"]["certsSecretPrefix"] = tls_cert_secret_name
282+
self["spec"]["security"]["tls"].update({"enabled": True, "ca": issuer_ca_configmap_name})
285283

286284
def build_list_of_hosts(self):
287285
"""Returns the list of full_fqdn:27017 for every member of the mongodb resource"""

0 commit comments

Comments
 (0)