Skip to content

Commit 73d2c40

Browse files
authored
CLOUDP-353164: Community/Enterprise Search TLS and cert manager changes (#572)
# Summary Why: Making Search snippets with TLS-First Our MongoDB Search snippets guide previously deployed without TLS. This PR overhauls them to be "TLS-first," adding and automating end-to-end encryption by default. What's Changing: 1. Integrates cert-manager to automatically install, bootstrap a self-signed CA, and issue all TLS certificates for MongoDB and MongoDBSearch. 2. All resource manifests are updated to require and reference the new TLS secrets and CA. 3. Replaces all hardcoded resource names, member counts, and secret names with environment variables (e.g., $RESOURCE_NAME). 4. Adds validation scripts to check for required variables before deployment. ## Proof of Work Tests pass
1 parent c926ece commit 73d2c40

28 files changed

+457
-29
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,5 @@ logs
9494

9595
# locally packaged chart
9696
mongodb-kubernetes-*.tgz
97+
98+
scripts/code_snippets/tests/outputs/*

controllers/searchcontroller/mongodbsearch_reconcile_helper.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ func (r *MongoDBSearchReconcileHelper) ensureEgressTlsConfig(ctx context.Context
274274

275275
mongotModification := func(config *mongot.Config) {
276276
config.SyncSource.ReplicaSet.TLS = ptr.To(true)
277-
config.SyncSource.CertificateAuthorityFile = ptr.To(tls.CAMountPath + "/" + tlsSourceConfig.CAFileName)
277+
config.SyncSource.CertificateAuthorityFile = ptr.To(tls.CAMountPath + tlsSourceConfig.CAFileName)
278278

279279
// if the gRPC server is configured to accept TLS connections then toggle mTLS as well
280280
if config.Server.Grpc.TLS.Mode == mongot.ConfigTLSModeTLS {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
required=(
2+
K8S_CTX
3+
MDB_NS
4+
MDB_RESOURCE_NAME
5+
MDB_VERSION
6+
MDB_MEMBERS
7+
CERT_MANAGER_NAMESPACE
8+
MDB_TLS_CA_SECRET_NAME
9+
MDB_TLS_SERVER_CERT_SECRET_NAME
10+
MDB_SEARCH_TLS_SECRET_NAME
11+
MDB_ADMIN_USER_PASSWORD
12+
MDB_SEARCH_SYNC_USER_PASSWORD
13+
MDB_USER_PASSWORD
14+
OPERATOR_HELM_CHART
15+
)
16+
17+
missing_req=()
18+
for v in "${required[@]}"; do [[ -n "${!v:-}" ]] || missing_req+=("${v}"); done
19+
20+
if (( ${#missing_req[@]} )); then
21+
echo "ERROR: Missing required environment variables:" >&2
22+
for m in "${missing_req[@]}"; do echo " - ${m}" >&2; done
23+
else
24+
echo "All required environment variables present."
25+
fi
Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
kubectl --context "${K8S_CTX}" --namespace "${MDB_NS}" \
2-
create secret generic mdb-admin-user-password \
3-
--from-literal=password="${MDB_ADMIN_USER_PASSWORD}"
1+
# Create admin user secret
2+
kubectl create secret generic mdb-admin-user-password \
3+
--from-literal=password="${MDB_ADMIN_USER_PASSWORD}" \
4+
--dry-run=client -o yaml | kubectl apply --context "${K8S_CTX}" --namespace "${MDB_NS}" -f -
45

5-
kubectl --context "${K8S_CTX}" --namespace "${MDB_NS}" \
6-
create secret generic mdbc-rs-search-sync-source-password \
7-
--from-literal=password="${MDB_SEARCH_SYNC_USER_PASSWORD}"
6+
# Create search sync source user secret
7+
kubectl create secret generic "${MDB_RESOURCE_NAME}-search-sync-source-password" \
8+
--from-literal=password="${MDB_SEARCH_SYNC_USER_PASSWORD}" \
9+
--dry-run=client -o yaml | kubectl apply --context "${K8S_CTX}" --namespace "${MDB_NS}" -f -
810

9-
kubectl --context "${K8S_CTX}" --namespace "${MDB_NS}" \
10-
create secret generic mdb-user-password \
11-
--from-literal=password="${MDB_USER_PASSWORD}"
11+
# Create regular user secret
12+
kubectl create secret generic mdb-user-password \
13+
--from-literal=password="${MDB_USER_PASSWORD}" \
14+
--dry-run=client -o yaml | kubectl apply --context "${K8S_CTX}" --namespace "${MDB_NS}" -f -
1215

16+
echo "User secrets created."
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
helm upgrade --install \
2+
cert-manager \
3+
oci://quay.io/jetstack/charts/cert-manager \
4+
--kube-context "${K8S_CTX}" \
5+
--namespace "${CERT_MANAGER_NAMESPACE}" \
6+
--create-namespace \
7+
--set crds.enabled=true
8+
9+
for deployment in cert-manager cert-manager-cainjector cert-manager-webhook; do
10+
kubectl --context "${K8S_CTX}" \
11+
-n "${CERT_MANAGER_NAMESPACE}" \
12+
wait --for=condition=Available "deployment/${deployment}" --timeout=300s
13+
done
14+
15+
echo "cert-manager is ready in namespace ${CERT_MANAGER_NAMESPACE}."
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Bootstrap a self-signed ClusterIssuer that will mint the CA material consumed by
2+
# the MongoDBCommunity deployment.
3+
kubectl apply --context "${K8S_CTX}" -f - <<EOF_MANIFEST
4+
apiVersion: cert-manager.io/v1
5+
kind: ClusterIssuer
6+
metadata:
7+
name: ${MDB_TLS_SELF_SIGNED_ISSUER}
8+
spec:
9+
selfSigned: {}
10+
EOF_MANIFEST
11+
12+
kubectl --context "${K8S_CTX}" wait --for=condition=Ready clusterissuer "${MDB_TLS_SELF_SIGNED_ISSUER}"
13+
14+
# Create the CA certificate and secret in the cert-manager namespace.
15+
kubectl apply --context "${K8S_CTX}" -f - <<EOF_MANIFEST
16+
apiVersion: cert-manager.io/v1
17+
kind: Certificate
18+
metadata:
19+
name: ${MDB_TLS_CA_CERT_NAME}
20+
namespace: ${CERT_MANAGER_NAMESPACE}
21+
spec:
22+
isCA: true
23+
commonName: ${MDB_TLS_CA_CERT_NAME}
24+
secretName: ${MDB_TLS_CA_SECRET_NAME}
25+
privateKey:
26+
algorithm: ECDSA
27+
size: 256
28+
issuerRef:
29+
name: ${MDB_TLS_SELF_SIGNED_ISSUER}
30+
kind: ClusterIssuer
31+
EOF_MANIFEST
32+
33+
kubectl --context "${K8S_CTX}" wait --for=condition=Ready -n "${CERT_MANAGER_NAMESPACE}" certificate "${MDB_TLS_CA_CERT_NAME}"
34+
35+
# Publish a cluster-scoped issuer that fronts the generated CA secret so all namespaces can reuse it.
36+
kubectl apply --context "${K8S_CTX}" -f - <<EOF_MANIFEST
37+
apiVersion: cert-manager.io/v1
38+
kind: ClusterIssuer
39+
metadata:
40+
name: ${MDB_TLS_CA_ISSUER}
41+
spec:
42+
ca:
43+
secretName: ${MDB_TLS_CA_SECRET_NAME}
44+
EOF_MANIFEST
45+
46+
kubectl --context "${K8S_CTX}" wait --for=condition=Ready clusterissuer "${MDB_TLS_CA_ISSUER}"
47+
48+
TMP_CA_CERT="$(mktemp)"
49+
50+
kubectl --context "${K8S_CTX}" \
51+
get secret "${MDB_TLS_CA_SECRET_NAME}" -n "${CERT_MANAGER_NAMESPACE}" \
52+
-o jsonpath="{.data['ca\\.crt']}" | base64 --decode > "${TMP_CA_CERT}"
53+
54+
# Expose the CA bundle through a ConfigMap for workloads and the MongoDBCommunity resource.
55+
kubectl --context "${K8S_CTX}" create configmap "${MDB_TLS_CA_CONFIGMAP}" -n "${MDB_NS}" \
56+
--from-file=ca-pem="${TMP_CA_CERT}" --from-file=mms-ca.crt="${TMP_CA_CERT}" \
57+
--from-file=ca.crt="${TMP_CA_CERT}" \
58+
--dry-run=client -o yaml | kubectl --context "${K8S_CTX}" apply -f -
59+
60+
echo "Cluster-wide CA issuer ${MDB_TLS_CA_ISSUER} is ready."
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
server_certificate="${MDB_RESOURCE_NAME}-server-tls"
2+
search_certificate="${MDB_RESOURCE_NAME}-search-tls"
3+
4+
mongo_dns_names=()
5+
for ((member = 0; member < MDB_MEMBERS; member++)); do
6+
mongo_dns_names+=("${MDB_RESOURCE_NAME}-${member}")
7+
mongo_dns_names+=("${MDB_RESOURCE_NAME}-${member}.${MDB_RESOURCE_NAME}-svc.${MDB_NS}.svc.cluster.local")
8+
done
9+
mongo_dns_names+=(
10+
"${MDB_RESOURCE_NAME}-svc.${MDB_NS}.svc.cluster.local"
11+
"*.${MDB_RESOURCE_NAME}-svc.${MDB_NS}.svc.cluster.local"
12+
)
13+
14+
search_dns_names=(
15+
"${MDB_RESOURCE_NAME}-search-svc.${MDB_NS}.svc.cluster.local"
16+
)
17+
18+
render_dns_list() {
19+
local dns_list=("$@")
20+
for dns in "${dns_list[@]}"; do
21+
printf " - \"%s\"\n" "${dns}"
22+
done
23+
}
24+
25+
kubectl apply --context "${K8S_CTX}" -n "${MDB_NS}" -f - <<EOF_MANIFEST
26+
apiVersion: cert-manager.io/v1
27+
kind: Certificate
28+
metadata:
29+
name: ${server_certificate}
30+
namespace: ${MDB_NS}
31+
spec:
32+
secretName: ${MDB_TLS_SERVER_CERT_SECRET_NAME}
33+
issuerRef:
34+
name: ${MDB_TLS_CA_ISSUER}
35+
kind: ClusterIssuer
36+
duration: 240h0m0s
37+
renewBefore: 120h0m0s
38+
usages:
39+
- digital signature
40+
- key encipherment
41+
- server auth
42+
- client auth
43+
dnsNames:
44+
$(render_dns_list "${mongo_dns_names[@]}")
45+
---
46+
apiVersion: cert-manager.io/v1
47+
kind: Certificate
48+
metadata:
49+
name: ${search_certificate}
50+
namespace: ${MDB_NS}
51+
spec:
52+
secretName: ${MDB_SEARCH_TLS_SECRET_NAME}
53+
issuerRef:
54+
name: ${MDB_TLS_CA_ISSUER}
55+
kind: ClusterIssuer
56+
duration: 240h0m0s
57+
renewBefore: 120h0m0s
58+
usages:
59+
- digital signature
60+
- key encipherment
61+
- server auth
62+
- client auth
63+
dnsNames:
64+
$(render_dns_list "${search_dns_names[@]}")
65+
EOF_MANIFEST
66+
67+
kubectl --context "${K8S_CTX}" -n "${MDB_NS}" wait --for=condition=Ready certificate "${server_certificate}" --timeout=300s
68+
kubectl --context "${K8S_CTX}" -n "${MDB_NS}" wait --for=condition=Ready certificate "${search_certificate}" --timeout=300s
69+
70+
echo "MongoDB TLS certificates have been issued."

docs/search/01-search-community-deploy/code_snippets/01_0310_create_mongodb_community_resource.sh

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@ kubectl apply --context "${K8S_CTX}" -n "${MDB_NS}" -f - <<EOF
22
apiVersion: mongodbcommunity.mongodb.com/v1
33
kind: MongoDBCommunity
44
metadata:
5-
name: mdbc-rs
5+
name: ${MDB_RESOURCE_NAME}
66
spec:
77
version: ${MDB_VERSION}
88
type: ReplicaSet
9-
members: 3
9+
members: ${MDB_MEMBERS}
1010
security:
11+
tls:
12+
enabled: true
13+
certificateKeySecretRef:
14+
name: ${MDB_TLS_SERVER_CERT_SECRET_NAME}
15+
caConfigMapRef:
16+
name: ${MDB_TLS_CA_CONFIGMAP}
1117
authentication:
1218
ignoreUnknownUsers: true
1319
modes:
@@ -68,8 +74,8 @@ spec:
6874
db: admin
6975
# a reference to the secret that will be used to generate the user's password
7076
passwordSecretRef:
71-
name: mdbc-rs-search-sync-source-password
72-
scramCredentialsSecretName: mdbc-rs-search-sync-source
77+
name: ${MDB_RESOURCE_NAME}-search-sync-source-password
78+
scramCredentialsSecretName: ${MDB_RESOURCE_NAME}-search-sync-source
7379
roles:
7480
- name: searchCoordinator
7581
db: admin

docs/search/01-search-community-deploy/code_snippets/01_0320_create_mongodb_search_resource.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@ kubectl apply --context "${K8S_CTX}" -n "${MDB_NS}" -f - <<EOF
22
apiVersion: mongodb.com/v1
33
kind: MongoDBSearch
44
metadata:
5-
name: mdbc-rs
5+
name: ${MDB_RESOURCE_NAME}
66
spec:
7+
security:
8+
tls:
9+
certificateKeySecretRef:
10+
name: ${MDB_SEARCH_TLS_SECRET_NAME}
711
resourceRequirements:
812
limits:
913
cpu: "3"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
echo "Waiting for MongoDBSearch resource to reach Running phase..."
22
kubectl --context "${K8S_CTX}" -n "${MDB_NS}" wait \
3-
--for=jsonpath='{.status.phase}'=Running mdbs/mdbc-rs --timeout=300s
3+
--for=jsonpath='{.status.phase}'=Running mdbs/"${MDB_RESOURCE_NAME}" --timeout=300s

0 commit comments

Comments
 (0)