Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ base_images:
name: "4.22"
namespace: ocp
tag: base-rhel9
cli-operator-sdk:
name: cli-operator-sdk
namespace: ocp
tag: v1.39.2
nested-podman:
name: nested-podman
namespace: ci
Expand All @@ -11,6 +15,10 @@ base_images:
name: "4.19"
namespace: origin
tag: operator-sdk
tls-scanner-tool:
name: tls-scanner
namespace: tls-scanner
tag: tls-scanner-tool
binary_build_commands: make build
build_root:
from_repository: true
Expand Down Expand Up @@ -247,6 +255,199 @@ tests:
requests:
cpu: 100m
workflow: generic-claim
- always_run: false
as: tls-scanner
optional: true
Comment thread
coderabbitai[bot] marked this conversation as resolved.
steps:
cluster_profile: openshift-org-aws
dependencies:
OO_BUNDLE: external-secrets-operator-bundle
env:
OO_INSTALL_MODE: AllNamespaces
OO_INSTALL_NAMESPACE: external-secrets-operator
OO_SECURITY_CONTEXT: restricted
SCAN_NAMESPACE: external-secrets-operator,external-secrets
SCANNER_CPU: "1"
SCANNER_MEMORY: 1Gi
TLS_13_ENABLE_TLS_ADHERENCE: "true"
TLS_13_TLS_ADHERENCE_POLICY: StrictAllComponents
test:
- ref: tls-13
- as: deploy-operand
cli: latest
commands: |-
set -o errexit
set -o nounset
set -o pipefail

echo "Waiting for external-secrets-operator controller-manager..."
oc wait --for=condition=Available -n external-secrets-operator deployment/external-secrets-operator-controller-manager --timeout=5m

echo "Creating ExternalSecretsConfig CR to trigger operand deployment..."
oc apply -f - <<EOF
apiVersion: operator.openshift.io/v1alpha1
kind: ExternalSecretsConfig
metadata:
name: cluster
spec: {}
EOF

echo "Waiting for external-secrets namespace to be created..."
for i in $(seq 1 60); do
if oc get namespace external-secrets 2>/dev/null; then
echo "Namespace external-secrets found"
break
fi
echo "Waiting for namespace (attempt ${i}/60)..."
sleep 5
done

echo "Waiting for external-secrets operand deployments..."
oc wait --for=create -n external-secrets deployment/external-secrets --timeout=5m
oc wait --for=create -n external-secrets deployment/external-secrets-webhook --timeout=5m
oc wait --for=create -n external-secrets deployment/external-secrets-cert-controller --timeout=5m
oc wait --for=condition=Available -n external-secrets deployment/external-secrets --timeout=5m
oc wait --for=condition=Available -n external-secrets deployment/external-secrets-webhook --timeout=5m
oc wait --for=condition=Available -n external-secrets deployment/external-secrets-cert-controller --timeout=5m

echo "Verifying webhook TLS endpoint is live..."
WEBHOOK_SVC=$(oc get validatingwebhookconfigurations -l app=external-secrets -o jsonpath='{.items[0].webhooks[0].clientConfig.service.name}' 2>/dev/null || true)
WEBHOOK_NS=$(oc get validatingwebhookconfigurations -l app=external-secrets -o jsonpath='{.items[0].webhooks[0].clientConfig.service.namespace}' 2>/dev/null || true)
if [[ -n "${WEBHOOK_SVC}" && -n "${WEBHOOK_NS}" ]]; then
WEBHOOK_PORT=$(oc get validatingwebhookconfigurations -l app=external-secrets -o jsonpath='{.items[0].webhooks[0].clientConfig.service.port}' 2>/dev/null || echo "443")
echo "Found webhook service: ${WEBHOOK_NS}/${WEBHOOK_SVC}:${WEBHOOK_PORT}"
oc get svc -n "${WEBHOOK_NS}" "${WEBHOOK_SVC}" || true
oc get endpoints -n "${WEBHOOK_NS}" "${WEBHOOK_SVC}" || true
else
echo "Warning: could not discover ValidatingWebhookConfiguration with label app=external-secrets"
oc get validatingwebhookconfigurations -o name || true
fi
Comment on lines +313 to +324

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Fail when the TLS paths are not exercised.

The webhook checks ignore missing configuration, services, and endpoints. The reconciliation loop also exits successfully when Ready never becomes True.

The workflow can therefore run tls-scanner-run and pass without proving that the webhook and controller TLS paths were exercised. Return a nonzero status when either verification fails.

Proposed failure checks
         if [[ -n "${WEBHOOK_SVC}" && -n "${WEBHOOK_NS}" ]]; then
           WEBHOOK_PORT=$(oc get validatingwebhookconfigurations -l app=external-secrets -o jsonpath='{.items[0].webhooks[0].clientConfig.service.port}' 2>/dev/null || echo "443")
           echo "Found webhook service: ${WEBHOOK_NS}/${WEBHOOK_SVC}:${WEBHOOK_PORT}"
-          oc get svc -n "${WEBHOOK_NS}" "${WEBHOOK_SVC}" || true
-          oc get endpoints -n "${WEBHOOK_NS}" "${WEBHOOK_SVC}" || true
+          oc get svc -n "${WEBHOOK_NS}" "${WEBHOOK_SVC}"
+          ENDPOINT_IPS=$(oc get endpoints -n "${WEBHOOK_NS}" "${WEBHOOK_SVC}" -o jsonpath='{.subsets[*].addresses[*].ip}')
+          [[ -n "${ENDPOINT_IPS}" ]] || {
+            echo "Webhook service has no ready endpoints" >&2
+            exit 1
+          }
         else
-          echo "Warning: could not discover ValidatingWebhookConfiguration with label app=external-secrets"
+          echo "Could not discover ValidatingWebhookConfiguration with label app=external-secrets" >&2
           oc get validatingwebhookconfigurations -o name || true
+          exit 1
         fi
...
         done
+        if [[ "${STATUS}" != "True" ]]; then
+          oc describe externalsecret tls-scan-dummy -n tls-scanner-exercise || true
+          exit 1
+        fi

Also applies to: 363-372

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ci-operator/config/openshift/external-secrets-operator/openshift-external-secrets-operator-main.yaml`
around lines 314 - 325, Update the webhook verification block around WEBHOOK_SVC
and WEBHOOK_NS to fail with a nonzero status when the
ValidatingWebhookConfiguration, service, or endpoints cannot be discovered or
verified, instead of suppressing errors with true. Also update the
reconciliation readiness check around the Ready condition to fail when Ready
never becomes True, ensuring tls-scanner-run cannot succeed without exercising
both webhook and controller TLS paths.


echo "Creating a test namespace with a SecretStore to exercise the webhook admission path..."
oc create namespace tls-scanner-exercise || true
oc apply -f - <<EOF
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
name: tls-scan-dummy
namespace: tls-scanner-exercise
spec:
provider:
fake:
data:
- key: tls-scan-test
value: dummy
EOF

echo "Creating an ExternalSecret to trigger webhook validation and controller reconciliation..."
oc apply -f - <<EOF
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: tls-scan-dummy
namespace: tls-scanner-exercise
spec:
refreshInterval: 1h
secretStoreRef:
name: tls-scan-dummy
kind: SecretStore
target:
name: tls-scan-dummy-secret
data:
- secretKey: test
remoteRef:
key: tls-scan-test
EOF

echo "Waiting for ExternalSecret to be processed..."
for i in $(seq 1 30); do
STATUS=$(oc get externalsecret tls-scan-dummy -n tls-scanner-exercise -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null || echo "Unknown")
if [[ "${STATUS}" == "True" ]]; then
echo "ExternalSecret reconciled successfully — webhook + controller TLS paths exercised"
break
fi
echo "ExternalSecret status: ${STATUS} (attempt ${i}/30)..."
sleep 5
done
echo "==> Generating self-signed TLS materials for bitwarden-sdk-server..."
CERT_DIR=$(mktemp -d)
export TLS_SECRET_NAME="bitwarden-tls-cert"
openssl ecparam -genkey -name prime256v1 -noout -out "${CERT_DIR}/ca.key" 2>/dev/null
openssl req -new -x509 -key "${CERT_DIR}/ca.key" -sha256 \
-subj "/O=external-secrets-e2e/CN=bitwarden-e2e-ca" \
-days 1 -out "${CERT_DIR}/ca.crt" 2>/dev/null

cat > "${CERT_DIR}/san.cnf" <<'SANEOF'
[req]
distinguished_name = req_dn
req_extensions = v3_req
prompt = no
[req_dn]
O = external-secrets-e2e
CN = bitwarden-sdk-server
[v3_req]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = bitwarden-sdk-server.external-secrets.svc.cluster.local
DNS.2 = external-secrets-bitwarden-sdk-server.external-secrets.svc.cluster.local
DNS.3 = localhost
IP.1 = 127.0.0.1
IP.2 = ::1
SANEOF

openssl ecparam -genkey -name prime256v1 -noout -out "${CERT_DIR}/tls.key" 2>/dev/null
openssl req -new -key "${CERT_DIR}/tls.key" -config "${CERT_DIR}/san.cnf" -out "${CERT_DIR}/tls.csr" 2>/dev/null
openssl x509 -req -in "${CERT_DIR}/tls.csr" -CA "${CERT_DIR}/ca.crt" -CAkey "${CERT_DIR}/ca.key" \
-CAcreateserial -out "${CERT_DIR}/tls.crt" -days 1 -sha256 \
-extensions v3_req -extfile "${CERT_DIR}/san.cnf" 2>/dev/null

echo "Creating TLS secret '${TLS_SECRET_NAME}' in external-secrets namespace..."
oc delete secret "${TLS_SECRET_NAME}" -n external-secrets --ignore-not-found 2>/dev/null
oc create secret generic "${TLS_SECRET_NAME}" -n external-secrets \
--from-file=tls.crt="${CERT_DIR}/tls.crt" \
--from-file=tls.key="${CERT_DIR}/tls.key" \
--from-file=ca.crt="${CERT_DIR}/ca.crt"
rm -rf "${CERT_DIR}"

echo "==> Enabling Bitwarden plugin with TLS secretRef..."
oc patch externalsecretsconfig cluster --type=merge -p "{
\"spec\": {
\"plugins\": {
\"bitwardenSecretManagerProvider\": {
\"mode\": \"Enabled\",
\"secretRef\": { \"name\": \"${TLS_SECRET_NAME}\" }
}
}
}
}"
sleep 10
echo "ExternalSecretsConfig status after patch:"
oc get externalsecretsconfig cluster -o jsonpath='{.status.conditions[*].type}' 2>/dev/null || true
echo ""
oc get externalsecretsconfig cluster -o yaml 2>/dev/null | grep -A5 'conditions:' || true
oc wait externalsecretsconfig/cluster --for=condition=Available --timeout=180s || {
echo "Warning: ExternalSecretsConfig did not reach Available condition, checking bitwarden deployment directly..."
oc get externalsecretsconfig cluster -o yaml 2>/dev/null | grep -A20 'status:' || true
}
oc rollout status deployment/bitwarden-sdk-server -n external-secrets --timeout=180s

echo "Listing all TLS-relevant services the scanner will probe:"
echo "--- external-secrets-operator namespace ---"
oc get svc -n external-secrets-operator -o wide 2>/dev/null || true
echo "--- external-secrets namespace ---"
oc get svc -n external-secrets -o wide 2>/dev/null || true
echo "--- bitwarden-sdk-server service ---"
oc get svc -n external-secrets bitwarden-sdk-server -o wide 2>/dev/null || true
oc get endpoints -n external-secrets bitwarden-sdk-server 2>/dev/null || true
from: src
resources:
requests:
cpu: 100m
- ref: tls-scanner-run
workflow: optional-operators-ci-operator-sdk-aws
zz_generated_metadata:
branch: main
org: openshift
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,94 @@ presubmits:
secret:
secretName: result-aggregator
trigger: (?m)^/test( | .* )images,?($|\s.*)
- agent: kubernetes
always_run: false
branches:
- ^main$
- ^main-
cluster: build01
context: ci/prow/tls-scanner
decorate: true
decoration_config:
sparse_checkout_files:
- .ci-operator.yaml
- images/ci/Dockerfile
- images/ci/Dockerfile.coverage
- images/ci/operand.Dockerfile
labels:
ci-operator.openshift.io/cloud: aws
ci-operator.openshift.io/cloud-cluster-profile: openshift-org-aws
ci.openshift.io/generator: prowgen
job-release: "4.22"
pj-rehearse.openshift.io/can-be-rehearsed: "true"
name: pull-ci-openshift-external-secrets-operator-main-tls-scanner
optional: true
rerun_command: /test tls-scanner
spec:
containers:
- args:
- --gcs-upload-secret=/secrets/gcs/service-account.json
- --image-import-pull-secret=/etc/pull-secret/.dockerconfigjson
- --lease-server-credentials-file=/etc/boskos/credentials
- --report-credentials-file=/etc/report/credentials
- --secret-dir=/secrets/ci-pull-credentials
- --target=tls-scanner
command:
- ci-operator
env:
- name: HTTP_SERVER_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
image: quay-proxy.ci.openshift.org/openshift/ci:ci_ci-operator_latest
imagePullPolicy: Always
name: ""
ports:
- containerPort: 8080
name: http
resources:
requests:
cpu: 10m
volumeMounts:
- mountPath: /etc/boskos
name: boskos
readOnly: true
- mountPath: /secrets/ci-pull-credentials
name: ci-pull-credentials
readOnly: true
- mountPath: /secrets/gcs
name: gcs-credentials
readOnly: true
- mountPath: /secrets/manifest-tool
name: manifest-tool-local-pusher
readOnly: true
- mountPath: /etc/pull-secret
name: pull-secret
readOnly: true
- mountPath: /etc/report
name: result-aggregator
readOnly: true
serviceAccountName: ci-operator
volumes:
- name: boskos
secret:
items:
- key: credentials
path: credentials
secretName: boskos-credentials
- name: ci-pull-credentials
secret:
secretName: ci-pull-credentials
- name: manifest-tool-local-pusher
secret:
secretName: manifest-tool-local-pusher
- name: pull-secret
secret:
secretName: registry-pull-credentials
- name: result-aggregator
secret:
secretName: result-aggregator
trigger: (?m)^/test( | .* )tls-scanner,?($|\s.*)
- agent: kubernetes
always_run: true
branches:
Expand Down