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
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@ updates:
directory: "/"
schedule:
interval: "weekly"
groups:
github-actions:
patterns:
- "*"
cooldown:
default-days: 7
2 changes: 1 addition & 1 deletion .github/workflows/helm-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

steps:
- name: Checkout Code
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/helm-unittest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

steps:
- name: Checkout Code
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false

Expand Down
18 changes: 17 additions & 1 deletion .github/workflows/superlinter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,23 @@ permissions:

jobs:
lint:
uses: validatedpatterns/github-actions-library/.github/workflows/superlinter.yml@v1
uses: validatedpatterns/github-actions-library/.github/workflows/superlinter.yml@v1 # zizmor: ignore[unpinned-uses]
with:
sl_env: |
VALIDATE_BIOME_FORMAT=false
VALIDATE_BIOME_LINT=false
VALIDATE_CHECKOV=false
VALIDATE_JSON_PRETTIER=false
VALIDATE_KUBERNETES_KUBECONFORM=false
VALIDATE_MARKDOWN=false
VALIDATE_MARKDOWN_PRETTIER=false
VALIDATE_NATURAL_LANGUAGE=false
VALIDATE_PYTHON_BLACK=false
VALIDATE_PYTHON_PYINK=false
VALIDATE_PYTHON_PYLINT=false
VALIDATE_PYTHON_RUFF_FORMAT=false
VALIDATE_SHELL_SHFMT=false
VALIDATE_SPELL_CODESPELL=false
VALIDATE_TRIVY=false
VALIDATE_YAML=false
VALIDATE_YAML_PRETTIER=false
18 changes: 17 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,24 @@ test: helm-lint helm-unittest ## Runs helm lint and unit tests
.PHONY: super-linter
super-linter: ## Runs super linter locally
rm -rf .mypy_cache
podman run -e RUN_LOCAL=true -e USE_FIND_ALGORITHM=true \
podman run -e RUN_LOCAL=true -e USE_FIND_ALGORITHM=true \
-e VALIDATE_BIOME_FORMAT=false \
-e VALIDATE_BIOME_LINT=false \
-e VALIDATE_CHECKOV=false \
-e VALIDATE_JSON_PRETTIER=false \
-e VALIDATE_KUBERNETES_KUBECONFORM=false \
-e VALIDATE_MARKDOWN=false \
-e VALIDATE_MARKDOWN_PRETTIER=false \
-e VALIDATE_NATURAL_LANGUAGE=false \
-e VALIDATE_PYTHON_BLACK=false \
-e VALIDATE_PYTHON_PYINK=false \
-e VALIDATE_PYTHON_PYLINT=false \
-e VALIDATE_PYTHON_RUFF_FORMAT=false \
-e VALIDATE_SHELL_SHFMT=false \
-e VALIDATE_SPELL_CODESPELL=false \
-e VALIDATE_TRIVY=false \
-e VALIDATE_YAML=false \
-e VALIDATE_YAML_PRETTIER=false \
-v $(PWD):/tmp/lint:rw,z \
-w /tmp/lint \
ghcr.io/super-linter/super-linter:slim-v8
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ v0.1.0 - Initial release

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| clusterCaMgt.createNamespace | bool | `false` | Create clusterCaMgt.namespace when installing the chart. |
| clusterCaMgt.namespace | string | `"cluster-ca-mgt"` | Namespace for ODF SSL certificate extraction and precheck workloads. |
| odfSslCertificateExtractor.clusterReadinessMaxAttempts | int | `150` | |
| odfSslCertificateExtractor.clusterReadinessSleepSeconds | int | `30` | |
| regionalDR[0].clusters.primary.name | string | `"ocp-primary"` | |
Expand Down
5 changes: 3 additions & 2 deletions scripts/ansible/odf-ssl-precheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# Precheck is Argo sync wave 2; odf-ssl-certificate-extractor is wave 1 and may still be running.
bundle_wait_retries: "{{ lookup('env', 'BUNDLE_WAIT_RETRIES') | default(60, true) | int }}"
bundle_wait_delay: "{{ lookup('env', 'BUNDLE_WAIT_DELAY_SECONDS') | default(30, true) | int }}"
cluster_ca_mgt_namespace: "{{ lookup('env', 'CLUSTER_CA_MGT_NAMESPACE') | default('cluster-ca-mgt', true) }}"
kubeconfig: "{{ lookup('env', 'KUBECONFIG') | default('', true) | trim }}"
tasks:
# Waits cluster_readiness_sleep seconds BETWEEN k8s_info attempts, same Pod (Ansible until/retries/delay).
Expand Down Expand Up @@ -170,11 +171,11 @@
or "This will be populated" in (item.resources[0].data.get('ca-bundle.crt', '') or '')
)
failed_when: false
- name: Trigger certificate extraction (create Job in openshift-config - handled by ArgoCD/Helm)
- name: Trigger certificate extraction (create Job in workload namespace - handled by ArgoCD/Helm)
ansible.builtin.debug:
msg: >-
Certificate distribution incomplete. Trigger or re-sync the
odf-ssl-certificate-extractor Job in openshift-config namespace,
odf-ssl-certificate-extractor Job in {{ cluster_ca_mgt_namespace }} namespace,
then re-run this precheck.
when: not (certificate_distribution_ok | default(false) | bool)

Expand Down
20 changes: 14 additions & 6 deletions scripts/odf-ssl-certificate-extraction.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ BASE_DELAY=30
MAX_DELAY=300
RETRY_COUNT=0

array_contains() {
local needle="$1"
shift
local item
for item in "$@"; do
[[ "$item" == "$needle" ]] && return 0
done
return 1
}

# Function to implement exponential backoff
exponential_backoff() {
local delay=$((BASE_DELAY * (2 ** RETRY_COUNT)))
Expand Down Expand Up @@ -140,7 +150,7 @@ create_combined_ca_bundle() {
ca_files=("$@")

echo "Creating combined CA bundle..."
> "$output_file"
: > "$output_file"

file_count=0
for ca_file in "${ca_files[@]}"; do
Expand Down Expand Up @@ -252,16 +262,14 @@ for cluster in $MANAGED_CLUSTERS; do
KUBECONFIG_FILE="$WORK_DIR/${cluster}-kubeconfig.yaml"
fi

cluster_ca_extracted=false
if extract_cluster_ca "$cluster" "$WORK_DIR/${cluster}-ca.crt" "$KUBECONFIG_FILE"; then
CA_FILES+=("$WORK_DIR/${cluster}-ca.crt")
EXTRACTED_CLUSTERS+=("$cluster")
cluster_ca_extracted=true
echo " Certificate size: $(wc -c < "$WORK_DIR/${cluster}-ca.crt") bytes"
else
echo " ❌ Could not extract CA from $cluster - REQUIRED for DR setup"
fi

# Extract ingress CA from managed cluster
echo "3b.$index Extracting ingress CA from $cluster..."
if extract_ingress_ca "$cluster" "$WORK_DIR/${cluster}-ingress-ca.crt" "$KUBECONFIG_FILE"; then
Expand All @@ -278,7 +286,7 @@ done
echo "4. Validating CA extraction from required clusters..."
MISSING_CLUSTERS=()
for required_cluster in "${REQUIRED_CLUSTERS[@]}"; do
if [[ " ${EXTRACTED_CLUSTERS[@]} " =~ " ${required_cluster} " ]]; then
if array_contains "$required_cluster" "${EXTRACTED_CLUSTERS[@]}"; then
echo " ✅ CA extracted from $required_cluster"
else
echo " ❌ CA NOT extracted from $required_cluster"
Expand Down Expand Up @@ -630,7 +638,7 @@ done
echo "10. Validating verification results..."
MISSING_VERIFICATION_CLUSTERS=()
for required_cluster in "${REQUIRED_VERIFICATION_CLUSTERS[@]}"; do
if [[ " ${VERIFIED_CLUSTERS[@]} " =~ " ${required_cluster} " ]]; then
if array_contains "$required_cluster" "${VERIFIED_CLUSTERS[@]}"; then
echo " ✅ $required_cluster: Certificate distribution verified"
else
echo " ❌ $required_cluster: Certificate distribution NOT verified"
Expand Down
14 changes: 9 additions & 5 deletions scripts/odf-ssl-precheck.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ echo "Starting ODF SSL certificate precheck and distribution..."
echo "This job ensures certificates are properly distributed before DR policies are applied"

# Configuration
CLUSTER_CA_MGT_NAMESPACE="${CLUSTER_CA_MGT_NAMESPACE:-cluster-ca-mgt}"
MIN_CERTIFICATES=15
MIN_BUNDLE_SIZE=20000
MAX_ATTEMPTS=120
Expand Down Expand Up @@ -141,7 +142,7 @@ check_certificate_distribution() {
return 1
fi

bundle_size=$(echo "$bundle_content" | wc -c)
bundle_size=${#bundle_content}
echo " Bundle size: $bundle_size bytes"

if [[ $bundle_size -lt $MIN_BUNDLE_SIZE ]]; then
Expand Down Expand Up @@ -175,19 +176,21 @@ check_certificate_distribution() {
}

# Function to trigger certificate extraction
# shellcheck disable=SC2120
trigger_certificate_extraction() {
echo "Triggering certificate extraction..."

oc delete job odf-ssl-certificate-extractor -n openshift-config --ignore-not-found=true
oc delete job odf-ssl-certificate-extractor -n "$CLUSTER_CA_MGT_NAMESPACE" --ignore-not-found=true
sleep 5

echo "Creating certificate extraction job..."
# shellcheck disable=SC2154,SC2076,SC2000,SC2012,SC2035,SC2086
oc apply -f - <<EOF
apiVersion: batch/v1
kind: Job
metadata:
name: odf-ssl-certificate-extractor
namespace: openshift-config
namespace: ${CLUSTER_CA_MGT_NAMESPACE}
labels:
app.kubernetes.io/name: odf-ssl-certificate-management
app.kubernetes.io/component: certificate-extraction
Expand Down Expand Up @@ -812,7 +815,7 @@ spec:
fi
done
EOF

echo "Certificate extraction job created"

echo "Waiting for certificate extraction to complete..."
Expand All @@ -821,7 +824,7 @@ EOF
attempt=$((attempt + 1))
echo " Attempt $attempt/$MAX_ATTEMPTS"

if oc wait --for=condition=complete job/odf-ssl-certificate-extractor -n openshift-config --timeout=60s 2>/dev/null; then
if oc wait --for=condition=complete job/odf-ssl-certificate-extractor -n "$CLUSTER_CA_MGT_NAMESPACE" --timeout=60s 2>/dev/null; then
echo " ✅ Certificate extraction completed successfully"
return 0
else
Expand Down Expand Up @@ -865,6 +868,7 @@ main_execution() {

echo " Triggering certificate extraction (attempt $attempt/$MAX_ATTEMPTS)..."

# shellcheck disable=SC2119
if trigger_certificate_extraction; then
echo "✅ Certificate extraction completed successfully"
echo " Re-verifying distribution..."
Expand Down
5 changes: 5 additions & 0 deletions templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@
{{- $fromOver := index $over "name" -}}
{{- if $fromOver }}{{ $fromOver }}{{- else if and .Values.regionalDR (index .Values.regionalDR 0) }}{{ (index .Values.regionalDR 0).clusters.secondary.name | default "ocp-secondary" }}{{- else }}ocp-secondary{{ end -}}
{{- end -}}

{{/* Namespace for ODF SSL certificate extraction/precheck workloads */}}
{{- define "opp.clusterCaMgtNamespace" -}}
{{- .Values.clusterCaMgt.namespace | default "cluster-ca-mgt" -}}
{{- end -}}
4 changes: 2 additions & 2 deletions templates/configmap-odf-ssl-playbooks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: odf-ssl-extractor-playbooks
namespace: openshift-config
namespace: {{ include "opp.clusterCaMgtNamespace" . }}
labels:
app.kubernetes.io/name: odf-ssl-certificate-management
data:
Expand All @@ -23,7 +23,7 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: odf-ssl-precheck-playbooks
namespace: open-cluster-management
namespace: {{ include "opp.clusterCaMgtNamespace" . }}
labels:
app.kubernetes.io/name: odf-ssl-certificate-management
data:
Expand Down
4 changes: 3 additions & 1 deletion templates/job-odf-ssl-certificate-extraction.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: batch/v1
kind: Job
metadata:
name: odf-ssl-certificate-extractor
namespace: openshift-config
namespace: {{ include "opp.clusterCaMgtNamespace" . }}
labels:
app.kubernetes.io/name: odf-ssl-certificate-management
app.kubernetes.io/component: certificate-extraction
Expand Down Expand Up @@ -35,6 +35,8 @@ spec:
value: {{ .Values.odfSslCertificateExtractor.clusterReadinessMaxAttempts | default 150 | quote }}
- name: CLUSTER_READINESS_SLEEP_SECONDS
value: {{ .Values.odfSslCertificateExtractor.clusterReadinessSleepSeconds | default 30 | quote }}
- name: CLUSTER_CA_MGT_NAMESPACE
value: {{ include "opp.clusterCaMgtNamespace" . | quote }}
command:
- ansible-playbook
args:
Expand Down
4 changes: 3 additions & 1 deletion templates/job-odf-ssl-certificate-precheck.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: batch/v1
kind: Job
metadata:
name: odf-ssl-certificate-precheck
namespace: open-cluster-management
namespace: {{ include "opp.clusterCaMgtNamespace" . }}
labels:
app.kubernetes.io/name: odf-ssl-certificate-management
app.kubernetes.io/component: certificate-precheck
Expand Down Expand Up @@ -37,6 +37,8 @@ spec:
value: {{ include "opp.primaryClusterName" . | quote }}
- name: SECONDARY_CLUSTER
value: {{ include "opp.secondaryClusterName" . | quote }}
- name: CLUSTER_CA_MGT_NAMESPACE
value: {{ include "opp.clusterCaMgtNamespace" . | quote }}
command:
- ansible-playbook
args:
Expand Down
11 changes: 11 additions & 0 deletions templates/namespace-cluster-ca-mgt.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{{- if .Values.clusterCaMgt.createNamespace }}
apiVersion: v1
kind: Namespace
metadata:
name: {{ include "opp.clusterCaMgtNamespace" . }}
labels:
app.kubernetes.io/name: odf-ssl-certificate-management
app.kubernetes.io/component: ca-workloads
annotations:
argocd.argoproj.io/sync-wave: "0"
{{- end }}
4 changes: 2 additions & 2 deletions templates/rbac-odf-ssl-certificate-precheck.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: odf-ssl-certificate-precheck
namespace: open-cluster-management
namespace: {{ include "opp.clusterCaMgtNamespace" . }}
labels:
app.kubernetes.io/name: odf-ssl-certificate-management
app.kubernetes.io/component: certificate-precheck
Expand Down Expand Up @@ -58,4 +58,4 @@ roleRef:
subjects:
- kind: ServiceAccount
name: odf-ssl-certificate-precheck
namespace: open-cluster-management
namespace: {{ include "opp.clusterCaMgtNamespace" . }}
5 changes: 3 additions & 2 deletions templates/rbac-odf-ssl-extractor.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: odf-ssl-extractor-sa
namespace: openshift-config
namespace: {{ include "opp.clusterCaMgtNamespace" . }}
labels:
app.kubernetes.io/name: odf-ssl-certificate-management
app.kubernetes.io/component: certificate-extraction
Expand All @@ -11,6 +11,7 @@ metadata:
---
# Hub-only permissions for the Job SA. Pushes to managed clusters use each cluster's imported kubeconfig
# (ACM admin-kubeconfig); those calls are authorized on the spoke, not by this ClusterRole.
# Workloads run in clusterCaMgt.namespace; cluster-proxy-ca-bundle remains in openshift-config.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
Expand Down Expand Up @@ -53,7 +54,7 @@ metadata:
subjects:
- kind: ServiceAccount
name: odf-ssl-extractor-sa
namespace: openshift-config
namespace: {{ include "opp.clusterCaMgtNamespace" . }}
roleRef:
kind: ClusterRole
name: odf-ssl-extractor-role
Expand Down
8 changes: 8 additions & 0 deletions values.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
---
# Namespace for ODF SSL extraction/precheck Jobs, playbooks, and RBAC.
# cluster-proxy-ca-bundle remains in openshift-config (Proxy.spec.trustedCA requirement).
clusterCaMgt:
# -- Namespace for ODF SSL certificate extraction and precheck workloads.
namespace: cluster-ca-mgt
# -- Create clusterCaMgt.namespace when installing the chart.
createNamespace: false

# DR pair cluster names - same structure as rdr chart (regionalDR).
# Override via values-hub or overrides so opp-policy and rdr use the same names.
# These MUST match ACM ManagedCluster metadata.name (e.g. mjrtd420-1); otherwise kubeconfig/CA paths and
Expand Down
Loading