Skip to content
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
2 changes: 1 addition & 1 deletion Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ keywords:
- odf
- pattern
- regionaldr
version: 0.0.1
version: 0.0.2
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# odf-dr-chart

![Version: 0.0.1](https://img.shields.io/badge/Version-0.0.1-informational?style=flat-square)
![Version: 0.0.2](https://img.shields.io/badge/Version-0.0.2-informational?style=flat-square)

Standalone Helm chart for ODF storage infrastructure supporting Regional DR. Deploys ODF SSL certificate extraction, Submariner network overlay, MirrorPeer storage mirroring, ODF DR prerequisites.

Expand All @@ -27,9 +27,10 @@ v0.1.0 - Initial release
| odf.postInstallFixesEnabled | bool | `true` | Enable ODF post-install automation (MirrorPeer, prerequisites checker, Ramen trusted-CA jobs/RBAC). |
| odfRamenTrustedCa.pollInterval | int | `15` | Polling interval in seconds for readiness checks inside the trusted-CA job. |
| odfRamenTrustedCa.ramenS3WaitSeconds | int | `3600` | Maximum seconds to wait for Ramen s3StoreProfiles to be populated before the trusted-CA job gives up. |
| odfRamenTrustedCa.trustedCaWaitSeconds | int | `3600` | Maximum seconds to wait for the hub cluster-proxy-ca-bundle trusted CA before the job gives up. |
| odfRamenTrustedCa.trustedCaWaitSeconds | int | `3600` | Maximum seconds to wait for the hub vp-pattern-proxy-ca-bundle trusted CA before the job gives up. |
| odfSslCertificateExtractor.clusterReadinessMaxAttempts | int | `150` | Maximum number of attempts to check DR ManagedCluster readiness before the extractor job fails. |
| odfSslCertificateExtractor.clusterReadinessSleepSeconds | int | `30` | Seconds to sleep between each ManagedCluster readiness poll attempt. |
| odfSslCertificateExtractor.enabled | bool | `false` | When false, skip legacy SSL certificate extraction jobs (disable when using vp-manage-proxy-cluster-ca). |
| regionalDR[0].globalnetEnabled | bool | `false` | Enable Submariner Globalnet. Required when primary and secondary cluster CIDRs overlap. |
| regionalDR[0].name | string | `"resilient"` | Name of this DR pair set. Must be unique within the regionalDR list and match the ACM policy placement label. |
| submariner.NATTEnable | bool | `true` | Enable NAT traversal (NAT-T) for Submariner IPsec tunnels. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,24 +251,24 @@ check_ca_configuration() {

echo "Checking CA configuration on $cluster..."

# Check if cluster-proxy-ca-bundle ConfigMap exists
if ! oc --kubeconfig="$kubeconfig" get configmap cluster-proxy-ca-bundle -n openshift-config &>/dev/null; then
report_check_failure "CA config ($cluster): ConfigMap cluster-proxy-ca-bundle not found in openshift-config"
# Check if vp-pattern-proxy-ca-bundle ConfigMap exists
if ! oc --kubeconfig="$kubeconfig" get configmap vp-pattern-proxy-ca-bundle -n openshift-config &>/dev/null; then
report_check_failure "CA config ($cluster): ConfigMap vp-pattern-proxy-ca-bundle not found in openshift-config"
return 1
fi

# Check if ConfigMap has certificate data
local ca_bundle_size=$(oc --kubeconfig="$kubeconfig" get configmap cluster-proxy-ca-bundle -n openshift-config -o jsonpath='{.data.ca-bundle\.crt}' 2>/dev/null | wc -c || echo "0")
local ca_bundle_size=$(oc --kubeconfig="$kubeconfig" get configmap vp-pattern-proxy-ca-bundle -n openshift-config -o jsonpath='{.data.ca-bundle\.crt}' 2>/dev/null | wc -c || echo "0")
ca_bundle_size=$(echo "$ca_bundle_size" | tr -d ' \n')
if [[ $ca_bundle_size -lt 100 ]]; then
report_check_failure "CA config ($cluster): cluster-proxy-ca-bundle data ca-bundle.crt too small or empty (bytes: $ca_bundle_size)"
report_check_failure "CA config ($cluster): vp-pattern-proxy-ca-bundle data ca-bundle.crt too small or empty (bytes: $ca_bundle_size)"
return 1
fi

# Check if Proxy object is configured
local proxy_trusted_ca=$(oc --kubeconfig="$kubeconfig" get proxy cluster -o jsonpath='{.spec.trustedCA.name}' 2>/dev/null || echo "")
if [[ "$proxy_trusted_ca" != "cluster-proxy-ca-bundle" ]]; then
report_check_failure "CA config ($cluster): Proxy cluster spec.trustedCA.name is '$proxy_trusted_ca' (expected cluster-proxy-ca-bundle)"
if [[ "$proxy_trusted_ca" != "vp-pattern-proxy-ca-bundle" ]]; then
report_check_failure "CA config ($cluster): Proxy cluster spec.trustedCA.name is '$proxy_trusted_ca' (expected vp-pattern-proxy-ca-bundle)"
return 1
fi

Expand All @@ -285,9 +285,9 @@ check_ca_material_completeness() {
echo "Checking CA material completeness across all clusters..."

# Extract CA bundle from each cluster
local hub_ca_bundle=$(oc --kubeconfig="$hub_kubeconfig" get configmap cluster-proxy-ca-bundle -n openshift-config -o jsonpath='{.data.ca-bundle\.crt}' 2>/dev/null || echo "")
local primary_ca_bundle=$(oc --kubeconfig="$primary_kubeconfig" get configmap cluster-proxy-ca-bundle -n openshift-config -o jsonpath='{.data.ca-bundle\.crt}' 2>/dev/null || echo "")
local secondary_ca_bundle=$(oc --kubeconfig="$secondary_kubeconfig" get configmap cluster-proxy-ca-bundle -n openshift-config -o jsonpath='{.data.ca-bundle\.crt}' 2>/dev/null || echo "")
local hub_ca_bundle=$(oc --kubeconfig="$hub_kubeconfig" get configmap vp-pattern-proxy-ca-bundle -n openshift-config -o jsonpath='{.data.ca-bundle\.crt}' 2>/dev/null || echo "")
local primary_ca_bundle=$(oc --kubeconfig="$primary_kubeconfig" get configmap vp-pattern-proxy-ca-bundle -n openshift-config -o jsonpath='{.data.ca-bundle\.crt}' 2>/dev/null || echo "")
local secondary_ca_bundle=$(oc --kubeconfig="$secondary_kubeconfig" get configmap vp-pattern-proxy-ca-bundle -n openshift-config -o jsonpath='{.data.ca-bundle\.crt}' 2>/dev/null || echo "")

# Check if all CA bundles exist and have reasonable size
if [[ -z "$hub_ca_bundle" || ${#hub_ca_bundle} -lt 100 ]]; then
Expand All @@ -305,77 +305,41 @@ check_ca_material_completeness() {
return 1
fi

# Check if all CA bundles contain certificates from all three clusters
echo "🔍 Debug: Checking CA bundle contents..."
echo "Hub CA bundle size: ${#hub_ca_bundle} characters"
echo "Primary CA bundle size: ${#primary_ca_bundle} characters"
echo "Secondary CA bundle size: ${#secondary_ca_bundle} characters"
echo "Hub CA bundle first 500 chars:"
echo "${hub_ca_bundle:0:500}"
echo ""

# Look for hub cluster certificates
if [[ "$hub_ca_bundle" != *"# CA from hub-ca"* ]]; then
echo "Available markers in hub CA bundle:"
echo "$hub_ca_bundle" | grep "^# CA from" || echo "No CA markers found"
report_check_failure "CA material: hub bundle missing marker '# CA from hub-ca'"
return 1
fi

if [[ "$primary_ca_bundle" != *"# CA from hub-ca"* ]]; then
echo "Available markers in primary CA bundle:"
echo "$primary_ca_bundle" | grep "^# CA from" || echo "No CA markers found"
report_check_failure "CA material: primary bundle missing marker '# CA from hub-ca'"
return 1
fi

if [[ "$secondary_ca_bundle" != *"# CA from hub-ca"* ]]; then
echo "Available markers in secondary CA bundle:"
echo "$secondary_ca_bundle" | grep "^# CA from" || echo "No CA markers found"
report_check_failure "CA material: secondary bundle missing marker '# CA from hub-ca'"
return 1
fi
# Check that each bundle contains PEM certificate data.
# Note: vp-manage-proxy-cluster-ca writes standard PEM without custom markers.
local MIN_CERTS=3
local hub_cert_count primary_cert_count secondary_cert_count
hub_cert_count=$(echo "$hub_ca_bundle" | grep -c "BEGIN CERTIFICATE" || echo "0")
primary_cert_count=$(echo "$primary_ca_bundle" | grep -c "BEGIN CERTIFICATE" || echo "0")
secondary_cert_count=$(echo "$secondary_ca_bundle" | grep -c "BEGIN CERTIFICATE" || echo "0")

# Look for primary cluster certificates (marker from odf-ssl-certificate-extraction.sh)
if [[ "$hub_ca_bundle" != *"# CA from ${PRIMARY_CLUSTER}-ca"* ]]; then
report_check_failure "CA material: hub bundle missing marker '# CA from ${PRIMARY_CLUSTER}-ca'"
return 1
fi

if [[ "$primary_ca_bundle" != *"# CA from ${PRIMARY_CLUSTER}-ca"* ]]; then
report_check_failure "CA material: primary bundle missing marker '# CA from ${PRIMARY_CLUSTER}-ca'"
return 1
fi

if [[ "$secondary_ca_bundle" != *"# CA from ${PRIMARY_CLUSTER}-ca"* ]]; then
report_check_failure "CA material: secondary bundle missing marker '# CA from ${PRIMARY_CLUSTER}-ca'"
return 1
fi
echo "Hub CA bundle: ${#hub_ca_bundle} chars, ${hub_cert_count} certificates"
echo "Primary CA bundle: ${#primary_ca_bundle} chars, ${primary_cert_count} certificates"
echo "Secondary CA bundle: ${#secondary_ca_bundle} chars, ${secondary_cert_count} certificates"

# Look for secondary cluster certificates
if [[ "$hub_ca_bundle" != *"# CA from ${SECONDARY_CLUSTER}-ca"* ]]; then
report_check_failure "CA material: hub bundle missing marker '# CA from ${SECONDARY_CLUSTER}-ca'"
if [[ "$hub_cert_count" -lt "$MIN_CERTS" ]]; then
report_check_failure "CA material: hub bundle has only ${hub_cert_count} certificates (expected at least ${MIN_CERTS})"
return 1
fi

if [[ "$primary_ca_bundle" != *"# CA from ${SECONDARY_CLUSTER}-ca"* ]]; then
report_check_failure "CA material: primary bundle missing marker '# CA from ${SECONDARY_CLUSTER}-ca'"
if [[ "$primary_cert_count" -lt "$MIN_CERTS" ]]; then
report_check_failure "CA material: primary ($PRIMARY_CLUSTER) bundle has only ${primary_cert_count} certificates (expected at least ${MIN_CERTS})"
return 1
fi

if [[ "$secondary_ca_bundle" != *"# CA from ${SECONDARY_CLUSTER}-ca"* ]]; then
report_check_failure "CA material: secondary bundle missing marker '# CA from ${SECONDARY_CLUSTER}-ca'"
if [[ "$secondary_cert_count" -lt "$MIN_CERTS" ]]; then
report_check_failure "CA material: secondary ($SECONDARY_CLUSTER) bundle has only ${secondary_cert_count} certificates (expected at least ${MIN_CERTS})"
return 1
fi

# Check that all CA bundles are identical (they should contain the same combined certificate data)
if [[ "$hub_ca_bundle" != "$primary_ca_bundle" ]]; then
report_check_failure "CA material: hub and primary cluster-proxy-ca-bundle contents differ (must be identical after trust sync)"
report_check_failure "CA material: hub and primary vp-pattern-proxy-ca-bundle contents differ (must be identical after trust sync)"
return 1
fi

if [[ "$hub_ca_bundle" != "$secondary_ca_bundle" ]]; then
report_check_failure "CA material: hub and secondary cluster-proxy-ca-bundle contents differ (must be identical after trust sync)"
report_check_failure "CA material: hub and secondary vp-pattern-proxy-ca-bundle contents differ (must be identical after trust sync)"
return 1
fi

Expand Down
38 changes: 24 additions & 14 deletions ansible/roles/odf_ramen_trusted_ca/files/odf-ramen-trusted-ca.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# After MirrorPeer (and policies that populate cluster-proxy-ca-bundle), copy CA from the hub
# cluster-proxy-ca-bundle ConfigMap — do not re-extract from router/spoke API servers.
# After MirrorPeer (and vp-manage-proxy-cluster-ca populates vp-pattern-proxy-ca-bundle), copy CA from
# the hub vp-pattern-proxy-ca-bundle ConfigMap — do not re-extract from router/spoke API servers.
# Wait until Ramen hub config has s3StoreProfiles (from ODF/MirrorPeer), then patch caCertificates only.
set -euo pipefail

Expand All @@ -14,6 +14,12 @@ POLL_INTERVAL="${POLL_INTERVAL:-15}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
RAMEN_SCRIPT="${SCRIPT_DIR}/odf-ssl-ramen-hub-configmap.sh"

LOG_FILE="${WORK_DIR:-/tmp/odf-ssl-certs}/ramen-trusted-ca.log"
mkdir -p "${WORK_DIR:-/tmp/odf-ssl-certs}"
# Tee all output to a log file readable via oc exec while Ansible buffers stdout.
exec > >(tee -a "$LOG_FILE") 2>&1
echo "[$(date -u +%T)] odf-ramen-trusted-ca.sh started"

die() {
echo "❌ odf-ramen-trusted-ca.sh: $*" >&2
exit 1
Expand All @@ -27,20 +33,23 @@ mkdir -p "$WORK_DIR"

wait_for_trusted_ca() {
local deadline=$((SECONDS + TRUSTED_CA_WAIT_SECONDS))
echo "Waiting for cluster-proxy-ca-bundle (openshift-config) with non-trivial ca-bundle.crt (max ${TRUSTED_CA_WAIT_SECONDS}s)..."
# Use the differential bundle: cluster-specific CAs only (API + ingress, no system trust store).
# This is the correct material for Ramen s3StoreProfiles caCertificates — concise and focused
# on the CAs needed to verify NooBaa S3 external route TLS certificates.
echo "Waiting for vp-pattern-proxy-ca-bundle-differential (openshift-config) with non-trivial cabundle (max ${TRUSTED_CA_WAIT_SECONDS}s)..."
while ((SECONDS < deadline)); do
local data bytes
data=$(oc get configmap cluster-proxy-ca-bundle -n openshift-config -o jsonpath='{.data.ca-bundle\.crt}' 2>/dev/null || true)
data=$(oc get configmap vp-pattern-proxy-ca-bundle-differential -n openshift-config -o jsonpath='{.data.cabundle}' 2>/dev/null || true)
bytes=$(printf '%s' "$data" | wc -c | tr -d ' ')
if [[ "${bytes:-0}" -ge 64 ]]; then
printf '%s' "$data" >"$WORK_DIR/combined-ca-bundle.crt"
echo " ✅ trusted CA bundle captured (${bytes} bytes)"
echo " ✅ differential CA bundle captured (${bytes} bytes)"
return 0
fi
echo " ... ca-bundle.crt bytes=${bytes:-0}, retry in ${POLL_INTERVAL}s"
echo " ... cabundle bytes=${bytes:-0}, retry in ${POLL_INTERVAL}s"
sleep "$POLL_INTERVAL"
done
die "cluster-proxy-ca-bundle not ready in time — ensure ACM/ODF policy populated it (see opp-policy-chart policy-odf-managed-cluster-ssl)"
die "vp-pattern-proxy-ca-bundle-differential not ready in time — ensure vp-manage-proxy-cluster-ca chart differentialBundle is enabled and synced"
}

count_s3_profiles() {
Expand All @@ -66,14 +75,15 @@ wait_for_ramen_s3_profiles() {
echo "Waiting for ramen-hub-operator-config s3StoreProfiles (openshift-operators, max ${RAMEN_CM_WAIT_SECONDS}s)..."
while ((SECONDS < deadline)); do
yaml=$(oc get configmap ramen-hub-operator-config -n openshift-operators -o jsonpath='{.data.ramen_manager_config\.yaml}' 2>/dev/null || true)
if [[ -n "$yaml" ]] && echo "$yaml" | grep -q 's3StoreProfiles'; then
c=$(count_s3_profiles "$yaml")
if [[ "${c:-0}" -ge 2 ]]; then
echo " ✅ ramen_manager_config has s3StoreProfiles (count≈$c)"
return 0
fi
# Strip carriage returns — configmap YAML may have CRLF line endings.
yaml=$(printf '%s' "$yaml" | tr -d '\r')
c=$(count_s3_profiles "$yaml")
echo " [$(date -u +%T)] yaml_empty=$([ -z "$yaml" ] && echo YES || echo NO) count=${c}"
if [[ -n "$yaml" && "${c:-0}" -ge 2 ]]; then
echo " ✅ ramen_manager_config has s3StoreProfiles (count≈$c)"
return 0
fi
echo " ... profiles not ready yet (need >=2), retry in ${POLL_INTERVAL}s"
echo " ... profiles not ready yet (need >=2, got ${c:-0}), retry in ${POLL_INTERVAL}s"
sleep "$POLL_INTERVAL"
done
die "ramen-hub-operator-config never gained s3StoreProfiles — confirm MirrorPeer and hub Ramen operator reconciled"
Expand Down
Loading
Loading