|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +set -euo pipefail |
| 4 | + |
| 5 | +: "${MDB_MEMBERS:=3}" |
| 6 | + |
| 7 | +# Inline TLS DNS entry functions (avoiding external file dependency) |
| 8 | +mongodb_service_fqdn() { |
| 9 | + printf '%s-svc.%s.svc.cluster.local' "${MDB_RESOURCE_NAME}" "${MDB_NS}" |
| 10 | +} |
| 11 | + |
| 12 | +mongodb_wildcard_fqdn() { |
| 13 | + printf '*.%s-svc.%s.svc.cluster.local' "${MDB_RESOURCE_NAME}" "${MDB_NS}" |
| 14 | +} |
| 15 | + |
| 16 | +mongodb_dns_entries() { |
| 17 | + local members="${MDB_MEMBERS:-3}" |
| 18 | + local member |
| 19 | + local service |
| 20 | + local wildcard |
| 21 | + |
| 22 | + service="$(mongodb_service_fqdn)" |
| 23 | + wildcard="$(mongodb_wildcard_fqdn)" |
| 24 | + |
| 25 | + for ((member = 0; member < members; member++)); do |
| 26 | + printf '%s-%s.%s\n' "${MDB_RESOURCE_NAME}" "${member}" "${service}" |
| 27 | + done |
| 28 | + |
| 29 | + printf '%s\n%s\n' "${service}" "${wildcard}" |
| 30 | +} |
| 31 | + |
| 32 | +mongot_service_fqdn() { |
| 33 | + printf '%s-search-svc.%s.svc.cluster.local' "${MDB_RESOURCE_NAME}" "${MDB_NS}" |
| 34 | +} |
| 35 | + |
| 36 | +mongot_wildcard_fqdn() { |
| 37 | + printf '*.%s-search.%s.svc.cluster.local' "${MDB_RESOURCE_NAME}" "${MDB_NS}" |
| 38 | +} |
| 39 | + |
| 40 | +mongot_dns_entries() { |
| 41 | + mongot_service_fqdn |
| 42 | + printf '\n' |
| 43 | + mongot_wildcard_fqdn |
| 44 | + printf '\n' |
| 45 | + # Add individual search pod hostname for proper TLS validation |
| 46 | + printf '%s-search-0.%s-search-svc.%s.svc.cluster.local\n' "${MDB_RESOURCE_NAME}" "${MDB_RESOURCE_NAME}" "${MDB_NS}" |
| 47 | + # Add localhost and IP for local connections |
| 48 | + printf 'localhost\n' |
| 49 | + printf '127.0.0.1\n' |
| 50 | +} |
| 51 | + |
| 52 | +tls_ca_common_name() { |
| 53 | + mongodb_service_fqdn |
| 54 | +} |
| 55 | + |
| 56 | +# Validate OpenSSL is available |
| 57 | +if ! command -v openssl &>/dev/null; then |
| 58 | + echo "Error: OpenSSL is required but not installed" |
| 59 | + exit 1 |
| 60 | +fi |
| 61 | + |
| 62 | +# Mirror the certificate subjects and SAN entries that the optional cert-manager |
| 63 | +# helper provisions so users can either self-manage the assets or plug cert-manager |
| 64 | +# in to populate the same Kubernetes secrets automatically. |
| 65 | + |
| 66 | +tmpdir="$(mktemp -d)" |
| 67 | +trap 'rm -rf "${tmpdir}"' EXIT |
| 68 | + |
| 69 | +# Pre-calculate all DNS entries and services |
| 70 | +mongodb_service="$(mongodb_service_fqdn)" |
| 71 | +mongodb_sans=() |
| 72 | +while IFS= read -r entry; do |
| 73 | + mongodb_sans+=("${entry}") |
| 74 | +done < <(mongodb_dns_entries) |
| 75 | +mongodb_san=$(printf 'DNS:%s,' "${mongodb_sans[@]}") |
| 76 | +mongodb_san="${mongodb_san%,}" |
| 77 | + |
| 78 | +mongot_service="$(mongot_service_fqdn)" |
| 79 | +mongot_sans=() |
| 80 | +while IFS= read -r entry; do |
| 81 | + mongot_sans+=("${entry}") |
| 82 | +done < <(mongot_dns_entries) |
| 83 | +mongot_san=$(printf 'DNS:%s,' "${mongot_sans[@]}") |
| 84 | +mongot_san="${mongot_san%,}" |
| 85 | + |
| 86 | +# Function to handle OpenSSL errors |
| 87 | +openssl_exec() { |
| 88 | + if ! "$@" >/dev/null 2>&1; then |
| 89 | + echo "Error: OpenSSL command failed: $*" >&2 |
| 90 | + exit 1 |
| 91 | + fi |
| 92 | +} |
| 93 | + |
| 94 | +# Create CA certificate |
| 95 | +echo "Generating CA certificate..." |
| 96 | +openssl_exec openssl ecparam -name prime256v1 -genkey -noout -out "${tmpdir}/ca.key" |
| 97 | +openssl_exec openssl req -x509 -new -key "${tmpdir}/ca.key" \ |
| 98 | + -out "${tmpdir}/ca.crt" \ |
| 99 | + -days 365 \ |
| 100 | + -sha256 \ |
| 101 | + -subj "/CN=$(tls_ca_common_name)" \ |
| 102 | + -addext "basicConstraints = critical,CA:true" \ |
| 103 | + -addext "keyUsage = critical,keyCertSign,cRLSign" \ |
| 104 | + -addext "subjectKeyIdentifier = hash" |
| 105 | + |
| 106 | +# Optimized function to sign certificates |
| 107 | +sign_cert() { |
| 108 | + local name="$1" |
| 109 | + local common_name="$2" |
| 110 | + local san="$3" |
| 111 | + |
| 112 | + echo "Generating certificate for ${name}..." |
| 113 | + |
| 114 | + # Generate private key |
| 115 | + openssl_exec openssl ecparam -name prime256v1 -genkey -noout -out "${tmpdir}/${name}.key" |
| 116 | + |
| 117 | + # Create CSR |
| 118 | + openssl_exec openssl req -new \ |
| 119 | + -key "${tmpdir}/${name}.key" \ |
| 120 | + -out "${tmpdir}/${name}.csr" \ |
| 121 | + -subj "/CN=${common_name}" \ |
| 122 | + -addext "subjectAltName = ${san}" \ |
| 123 | + -addext "extendedKeyUsage = serverAuth,clientAuth" \ |
| 124 | + -addext "keyUsage = digitalSignature,keyEncipherment" |
| 125 | + |
| 126 | + # Sign certificate with consolidated extensions including client auth |
| 127 | + openssl_exec openssl x509 -req -in "${tmpdir}/${name}.csr" \ |
| 128 | + -CA "${tmpdir}/ca.crt" \ |
| 129 | + -CAkey "${tmpdir}/ca.key" \ |
| 130 | + -CAcreateserial \ |
| 131 | + -out "${tmpdir}/${name}.crt" \ |
| 132 | + -days 365 \ |
| 133 | + -sha256 \ |
| 134 | + -extfile <(cat <<EOF |
| 135 | +subjectAltName=${san} |
| 136 | +extendedKeyUsage=serverAuth,clientAuth |
| 137 | +keyUsage=digitalSignature,keyEncipherment |
| 138 | +basicConstraints=CA:FALSE |
| 139 | +EOF |
| 140 | +) |
| 141 | +} |
| 142 | + |
| 143 | +# Generate certificates for MongoDB and Search |
| 144 | +sign_cert mongodb "${mongodb_service}" "${mongodb_san}" |
| 145 | +sign_cert mongot "${mongot_service}" "${mongot_san}" |
| 146 | + |
| 147 | +# Function to create secrets with consistent pattern |
| 148 | +create_tls_secret() { |
| 149 | + local secret_name="$1" |
| 150 | + local cert_file="$2" |
| 151 | + local key_file="$3" |
| 152 | + local secret_type="${4:-tls}" |
| 153 | + |
| 154 | + echo "Creating secret ${secret_name}..." |
| 155 | + if [[ "${secret_type}" == "generic" ]]; then |
| 156 | + kubectl create secret generic "${secret_name}" \ |
| 157 | + --from-file=ca.crt="${cert_file}" \ |
| 158 | + --dry-run=client -o yaml \ |
| 159 | + | kubectl apply --context "${K8S_CTX}" --namespace "${MDB_NS}" -f - |
| 160 | + else |
| 161 | + kubectl create secret tls "${secret_name}" \ |
| 162 | + --cert="${cert_file}" \ |
| 163 | + --key="${key_file}" \ |
| 164 | + --dry-run=client -o yaml \ |
| 165 | + | kubectl apply --context "${K8S_CTX}" --namespace "${MDB_NS}" -f - |
| 166 | + fi |
| 167 | +} |
| 168 | + |
| 169 | +# Create all secrets |
| 170 | +echo "Creating Kubernetes secrets..." |
| 171 | +create_tls_secret "${MDB_TLS_CA_SECRET}" "${tmpdir}/ca.crt" "" "generic" |
| 172 | +create_tls_secret "${MDB_TLS_CERT_SECRET}" "${tmpdir}/mongodb.crt" "${tmpdir}/mongodb.key" |
| 173 | +create_tls_secret "${MDB_SEARCH_TLS_SECRET}" "${tmpdir}/mongot.crt" "${tmpdir}/mongot.key" |
| 174 | + |
| 175 | +echo "TLS certificates and secrets created successfully" |
0 commit comments