Skip to content

Commit 0c6be8a

Browse files
committed
cert fix
Signed-off-by: Vani Haripriya Mudadla <vmudadla@redhat.com>
1 parent 93eb9af commit 0c6be8a

2 files changed

Lines changed: 12 additions & 79 deletions

File tree

.github/resources/scripts/configure-mlflow.sh

Lines changed: 9 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ KFP_NAMESPACE="${1:?KFP namespace required}"
2929
MLFLOW_NAMESPACE="${2:?MLflow namespace required}"
3030
CONFIG_JSON_PATH="${3:?Path to source config.json required}"
3131

32+
MLFLOW_CA_CONFIGMAP="mlflow-ca-cert"
33+
KFP_CA_BUNDLE_DIR="/kfp/certs"
34+
KFP_CA_BUNDLE_PATH="${KFP_CA_BUNDLE_DIR}/ca.crt"
35+
3236
echo "Services in ${MLFLOW_NAMESPACE} namespace:"
3337
kubectl get svc -n "$MLFLOW_NAMESPACE" --no-headers
3438
MLFLOW_SVC=$(kubectl get svc -n "$MLFLOW_NAMESPACE" --no-headers -o custom-columns=":metadata.name" | grep -i mlflow | head -1)
@@ -43,7 +47,6 @@ MLFLOW_ENDPOINT="https://${MLFLOW_HOST}:${MLFLOW_PORT}${MLFLOW_STATIC_PREFIX}"
4347
echo "MLflow service: $MLFLOW_SVC port=$MLFLOW_PORT endpoint=$MLFLOW_ENDPOINT"
4448

4549
# --- Extract CA certificate from the MLflow TLS secret ---
46-
CA_MOUNT_PATH="/etc/mlflow/tls/ca.crt"
4750
CA_CERT_FILE="/tmp/mlflow-ca.crt"
4851

4952
echo "Extracting MLflow CA certificate..."
@@ -70,71 +73,12 @@ fi
7073
echo "$CA_DATA" | base64 -d > "$CA_CERT_FILE"
7174
echo "CA certificate extracted to $CA_CERT_FILE ($(wc -l < "$CA_CERT_FILE") lines)"
7275

73-
# Create a ConfigMap with the CA cert in the KFP namespace for workflow pods
74-
kubectl create configmap mlflow-ca-cert -n "$KFP_NAMESPACE" \
76+
# ConfigMap consumed by the API server (plugin config) and compiler (driver/launcher pods).
77+
kubectl create configmap "$MLFLOW_CA_CONFIGMAP" -n "$KFP_NAMESPACE" \
7578
--from-file=ca.crt="$CA_CERT_FILE" --dry-run=client -o yaml | kubectl apply -f -
7679

77-
# --- Patch Argo workflow-controller-configmap to mount the CA cert into all workflow pods ---
78-
echo "Patching workflow-controller-configmap to inject MLflow CA into workflow pods..."
79-
80-
EXISTING_MAIN_CONTAINER=$(kubectl get configmap workflow-controller-configmap -n "$KFP_NAMESPACE" \
81-
-o jsonpath='{.data.mainContainer}' 2>/dev/null || echo "")
82-
if [ -n "$EXISTING_MAIN_CONTAINER" ]; then
83-
MAIN_CONTAINER_PATCH=$(echo "$EXISTING_MAIN_CONTAINER" | \
84-
python3 -c "
85-
import sys, json
86-
raw = sys.stdin.read().strip()
87-
try:
88-
cfg = json.loads(raw)
89-
except json.JSONDecodeError:
90-
import yaml
91-
cfg = yaml.safe_load(raw) or {}
92-
vms = cfg.get('volumeMounts', [])
93-
vms = [vm for vm in vms if vm.get('name') != 'mlflow-ca']
94-
vms.append({'name': 'mlflow-ca', 'mountPath': '/etc/mlflow/tls', 'readOnly': True})
95-
cfg['volumeMounts'] = vms
96-
print(json.dumps(cfg))
97-
")
98-
else
99-
MAIN_CONTAINER_PATCH='{"volumeMounts":[{"name":"mlflow-ca","mountPath":"/etc/mlflow/tls","readOnly":true}]}'
100-
fi
101-
102-
EXISTING_WF_DEFAULTS=$(kubectl get configmap workflow-controller-configmap -n "$KFP_NAMESPACE" \
103-
-o jsonpath='{.data.workflowDefaults}' 2>/dev/null || echo "")
104-
if [ -n "$EXISTING_WF_DEFAULTS" ]; then
105-
WF_DEFAULTS_PATCH=$(echo "$EXISTING_WF_DEFAULTS" | \
106-
python3 -c "
107-
import sys, yaml
108-
cfg = yaml.safe_load(sys.stdin) or {}
109-
spec = cfg.setdefault('spec', {})
110-
volumes = spec.setdefault('volumes', [])
111-
volumes = [v for v in volumes if v.get('name') != 'mlflow-ca']
112-
volumes.append({'name': 'mlflow-ca', 'configMap': {'name': 'mlflow-ca-cert'}})
113-
spec['volumes'] = volumes
114-
cfg['spec'] = spec
115-
print(yaml.dump(cfg, default_flow_style=False))
116-
")
117-
else
118-
WF_DEFAULTS_PATCH=$(cat <<'YAML'
119-
spec:
120-
volumes:
121-
- name: mlflow-ca
122-
configMap:
123-
name: mlflow-ca-cert
124-
YAML
125-
)
126-
fi
127-
128-
kubectl patch configmap workflow-controller-configmap -n "$KFP_NAMESPACE" --type=merge \
129-
-p "$(jq -n --arg mc "$MAIN_CONTAINER_PATCH" --arg wd "$WF_DEFAULTS_PATCH" \
130-
'{"data":{"mainContainer":$mc,"workflowDefaults":$wd}}')"
131-
132-
# Restart workflow controller to pick up configmap changes
133-
kubectl rollout restart deployment/workflow-controller -n "$KFP_NAMESPACE"
134-
kubectl rollout status deployment/workflow-controller -n "$KFP_NAMESPACE" --timeout=120s
135-
13680
# --- Build the MLflow plugin config with caBundlePath ---
137-
MLFLOW_PATCH=$(jq -n --arg endpoint "$MLFLOW_ENDPOINT" --arg caBundlePath "$CA_MOUNT_PATH" '{
81+
MLFLOW_PATCH=$(jq -n --arg endpoint "$MLFLOW_ENDPOINT" --arg caBundlePath "$KFP_CA_BUNDLE_PATH" '{
13882
endpoint: $endpoint,
13983
tls: { caBundlePath: $caBundlePath },
14084
settings: { workspacesEnabled: true }
@@ -146,11 +90,11 @@ jq --argjson mlflow "$MLFLOW_PATCH" '. + { plugins: { mlflow: $mlflow } }' \
14690
echo "Patched config.json plugins.mlflow:"
14791
jq '.plugins.mlflow' /tmp/kfp-config.json
14892

149-
# --- Deploy the config and mount the CA cert into the API server ---
93+
# --- Deploy plugin config and wire CA trust on the API server + compiler ---
15094
kubectl create configmap kfp-mlflow-config -n "$KFP_NAMESPACE" \
15195
--from-file=config.json=/tmp/kfp-config.json --dry-run=client -o yaml | kubectl apply -f -
15296
kubectl patch deployment ml-pipeline -n "$KFP_NAMESPACE" --type=strategic -p \
153-
'{"spec":{"template":{"spec":{"volumes":[{"name":"mlflow-cfg","configMap":{"name":"kfp-mlflow-config"}},{"name":"mlflow-ca","configMap":{"name":"mlflow-ca-cert"}}],"containers":[{"name":"ml-pipeline-api-server","volumeMounts":[{"name":"mlflow-cfg","mountPath":"/config/config.json","subPath":"config.json"},{"name":"mlflow-ca","mountPath":"/etc/mlflow/tls","readOnly":true}]}]}}}}'
97+
'{"spec":{"template":{"spec":{"volumes":[{"name":"mlflow-cfg","configMap":{"name":"kfp-mlflow-config"}},{"name":"mlflow-ca","configMap":{"name":"'"$MLFLOW_CA_CONFIGMAP"'"}}],"containers":[{"name":"ml-pipeline-api-server","env":[{"name":"CABUNDLE_CONFIGMAP_NAME","value":"'"$MLFLOW_CA_CONFIGMAP"'"}],"volumeMounts":[{"name":"mlflow-cfg","mountPath":"/config/config.json","subPath":"config.json"},{"name":"mlflow-ca","mountPath":"'"$KFP_CA_BUNDLE_DIR"'","readOnly":true}]}]}}}}'
15498
kubectl rollout status deployment/ml-pipeline -n "$KFP_NAMESPACE" --timeout=180s
15599

156100
pkill -f "kubectl port-forward.*ml-pipeline.*8888" || true

backend/src/v2/common/plugins/mlflow/config.go

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,22 +59,11 @@ func ParseKfpMLflowRuntimeConfig() (*commonmlflow.MLflowRuntimeConfig, error) {
5959
if cfg.AuthType != "kubernetes" {
6060
return nil, fmt.Errorf("unsupported auth type: %s", cfg.AuthType)
6161
}
62-
// Disabling TLS verification is not supported in the driver/launcher
63-
// to prevent CWE-295 (improper certificate validation).
64-
if cfg.InsecureSkipVerify {
62+
if cfg.InsecureSkipVerify || (cfg.TLS != nil && cfg.TLS.InsecureSkipVerify) {
6563
return nil, fmt.Errorf("insecureSkipVerify is not supported")
6664
}
67-
// Preserve the CABundlePath from the runtime config (propagated by the
68-
// API server) so the driver/launcher can verify certificates signed by
69-
// an internal CA (e.g., cert-manager). InsecureSkipVerify is always
70-
// forced to false.
71-
caBundlePath := ""
72-
if cfg.TLS != nil {
73-
caBundlePath = cfg.TLS.CABundlePath
74-
}
75-
cfg.TLS = &commonplugins.TLSConfig{
76-
InsecureSkipVerify: false,
77-
CABundlePath: caBundlePath,
65+
if cfg.TLS == nil {
66+
cfg.TLS = &commonplugins.TLSConfig{}
7867
}
7968
return &cfg, nil
8069
}

0 commit comments

Comments
 (0)