Skip to content
Draft
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: "5.0"
namespace: ocp
tag: base-rhel9
hypershift-operator:
name: hypershift-operator
namespace: hypershift
tag: latest
ocp_builder_rhel-9-golang-1.25-openshift-4.22:
name: builder
namespace: ocp
Expand Down Expand Up @@ -129,6 +133,21 @@ tests:
test:
- ref: tls-scanner-run
workflow: openshift-e2e-aws-ovn-tls-13
- as: periodic-hypershift-tls
interval: 72h
reporter_config:
channel: '#forum-case'
job_states_to_report:
- success
- failure
- error
report_template: '{{if eq .Status.State "success"}} :white_check_mark: Job *{{.Spec.Job}}*
ended with *{{.Status.State}}*. <{{.Status.URL}}|View logs> {{else}} :warning:
Job *{{.Spec.Job}}* ended with *{{.Status.State}}*. <{{.Status.URL}}|View logs>
{{end}}'
steps:
cluster_profile: hypershift-aws
workflow: tls-scanner-hypershift-aws
zz_generated_metadata:
branch: main
org: openshift
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,100 @@ periodics:
- name: result-aggregator
secret:
secretName: result-aggregator
- agent: kubernetes
cluster: build03
decorate: true
decoration_config:
sparse_checkout_files:
- Dockerfile
extra_refs:
- base_ref: main
org: openshift
repo: tls-scanner
sparse_checkout_files:
- Dockerfile
interval: 72h
labels:
ci-operator.openshift.io/cloud: hypershift-aws
ci-operator.openshift.io/cloud-cluster-profile: hypershift-aws
ci.openshift.io/generator: prowgen
pj-rehearse.openshift.io/can-be-rehearsed: "true"
name: periodic-ci-openshift-tls-scanner-main-periodic-hypershift-tls
reporter_config:
slack:
channel: '#forum-case'
job_states_to_report:
- success
- failure
- error
report_template: '{{if eq .Status.State "success"}} :white_check_mark: Job *{{.Spec.Job}}*
ended with *{{.Status.State}}*. <{{.Status.URL}}|View logs> {{else}} :warning:
Job *{{.Spec.Job}}* ended with *{{.Status.State}}*. <{{.Status.URL}}|View
logs> {{end}}'
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=periodic-hypershift-tls
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
- agent: kubernetes
cluster: build03
decorate: true
Expand Down
4 changes: 4 additions & 0 deletions ci-operator/step-registry/hypershift/modern-tls/OWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
approvers:
- gangwgr
reviewers:
- gangwgr
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/bin/bash
set -euo pipefail

echo "Configuring Modern TLS Security Profile for HyperShift cluster..."

export KUBECONFIG=${SHARED_DIR}/kubeconfig

if [[ -f "${SHARED_DIR}/cluster-name" ]]; then
HOSTED_CLUSTER_NAME="$(<"${SHARED_DIR}/cluster-name")"
HOSTED_CLUSTER_NAMESPACE="clusters"
else
HOSTED_CLUSTER_NAME=$(oc get hostedcluster -A -o jsonpath='{.items[0].metadata.name}')
HOSTED_CLUSTER_NAMESPACE=$(oc get hostedcluster -A -o jsonpath='{.items[0].metadata.namespace}')
fi

if [[ -z "${HOSTED_CLUSTER_NAME}" ]]; then
echo "Error: Could not find HostedCluster"
exit 1
fi

HCP_NAMESPACE=$(oc get hostedcontrolplane -A -o jsonpath="{.items[?(@.metadata.name==\"${HOSTED_CLUSTER_NAME}\")].metadata.namespace}" 2>/dev/null || true)
if [[ -z "${HCP_NAMESPACE}" ]]; then
HCP_NAMESPACE="clusters-${HOSTED_CLUSTER_NAME}"
fi

echo "Found HostedCluster: ${HOSTED_CLUSTER_NAME} in namespace ${HOSTED_CLUSTER_NAMESPACE}"
echo "Hosted control plane namespace: ${HCP_NAMESPACE}"

kas_generation="$(oc get deployment -n "${HCP_NAMESPACE}" kube-apiserver -o jsonpath='{.metadata.generation}')"

echo "Applying Modern TLS Security Profile to HostedCluster..."
oc patch hostedcluster -n "${HOSTED_CLUSTER_NAMESPACE}" "${HOSTED_CLUSTER_NAME}" --type=merge -p '{
"spec": {
"configuration": {
"apiServer": {
"tlsSecurityProfile": {
"type": "Modern",
"modern": {}
}
}
}
}
}'

hc_tls_profile=$(oc get hostedcluster -n "${HOSTED_CLUSTER_NAMESPACE}" "${HOSTED_CLUSTER_NAME}" -o jsonpath='{.spec.configuration.apiServer.tlsSecurityProfile.type}')
if [[ "${hc_tls_profile}" != "Modern" ]]; then
echo "Error: HostedCluster TLS Security Profile is '${hc_tls_profile}', expected 'Modern'"
exit 1
fi
echo "✓ HostedCluster spec.configuration.apiServer.tlsSecurityProfile.type is Modern"

echo "Waiting for kube-apiserver to reconcile the TLS profile..."
rollout_deadline=$((SECONDS + 300))
while (( SECONDS < rollout_deadline )); do
current_generation="$(oc get deployment -n "${HCP_NAMESPACE}" kube-apiserver -o jsonpath='{.metadata.generation}')"
if (( current_generation > kas_generation )); then
echo "kube-apiserver generation changed (${kas_generation} -> ${current_generation}), waiting for rollout..."
oc rollout status deployment -n "${HCP_NAMESPACE}" kube-apiserver --timeout=15m
break
fi
sleep 15
done
if (( SECONDS >= rollout_deadline )); then
echo "kube-apiserver generation unchanged after 5m; continuing with TLS verification"
fi

verify_modern_tls_endpoint() {
local api_server api_host api_port

api_server="$(oc whoami --show-server)"
api_host="${api_server#https://}"
api_host="${api_host%:*}"
api_port="${api_server##*:}"

echo "Verifying Modern TLS profile on API server endpoint ${api_host}:${api_port}..."
if ! echo | openssl s_client -connect "${api_host}:${api_port}" -tls1_3 -servername "${api_host}" 2>/dev/null | grep -qE 'Protocol.*TLSv1\.3'; then
echo "Error: API server does not negotiate TLS 1.3"
return 1
fi
if echo | openssl s_client -connect "${api_host}:${api_port}" -tls1_2 -servername "${api_host}" 2>/dev/null | grep -qE 'Protocol.*TLSv1\.2'; then
echo "Error: API server still negotiates TLS 1.2 (expected Modern profile)"
return 1
fi
echo "✓ API server endpoint enforces Modern TLS (TLS 1.3 only)"
}

export KUBECONFIG=${SHARED_DIR}/nested_kubeconfig

echo "Waiting for guest cluster APIServer to reflect Modern TLS profile..."
for i in {1..40}; do
tls_profile=$(oc get apiserver/cluster -o jsonpath='{.spec.tlsSecurityProfile.type}' 2>/dev/null || echo "")
if [[ "$tls_profile" == "Modern" ]]; then
echo "✓ Guest cluster APIServer tlsSecurityProfile.type is Modern"
echo "✓ Modern TLS Security Profile successfully applied"
exit 0
fi
if verify_modern_tls_endpoint; then
echo "Guest cluster APIServer tlsSecurityProfile.type is '${tls_profile}' (HyperShift may not mirror this field)"
echo "✓ Modern TLS Security Profile successfully applied"
exit 0
fi
echo "Waiting for Modern TLS profile to propagate (attempt $i/40)..."
sleep 15
done

tls_profile=$(oc get apiserver/cluster -o jsonpath='{.spec.tlsSecurityProfile.type}' 2>/dev/null || echo "NotFound")
if [[ "$tls_profile" == "Modern" ]]; then
echo "✓ Modern TLS Security Profile successfully applied"
exit 0
fi

echo "Guest cluster APIServer tlsSecurityProfile.type is '${tls_profile}'"
verify_modern_tls_endpoint
echo "✓ Modern TLS Security Profile successfully applied"
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"path": "hypershift/modern-tls/hypershift-modern-tls-ref.yaml",
"owners": {
"approvers": [
"gangwgr"
],
"reviewers": [
"gangwgr"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
ref:
as: hypershift-modern-tls
from_image:
namespace: ocp
name: "5.0"
tag: cli
commands: hypershift-modern-tls-commands.sh
resources:
requests:
cpu: 100m
memory: 200Mi
documentation: |-
Configures Modern TLS Security Profile on a HyperShift hosted cluster.

This step patches the HostedCluster CR to enable Modern TLS profile, which
enforces TLS 1.3 for all API server connections. It waits for the hosted
control plane kube-apiserver to roll out on the management cluster, then
verifies the profile on the guest APIServer object or via a TLS 1.3 endpoint
probe when HyperShift does not mirror the field into the guest cluster.

Note: Due to current HyperShift limitations, the Modern TLS profile may not
propagate to etcd and some other control plane components. This is a known
issue being tracked upstream.
8 changes: 8 additions & 0 deletions ci-operator/step-registry/tls/scanner/hypershift-aws/OWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
approvers:
- richardsonnick
- rhmdnd
- smith-xyz
reviewers:
- richardsonnick
- rhmdnd
- smith-xyz
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"path": "tls/scanner/hypershift-aws/tls-scanner-hypershift-aws-workflow.yaml",
"owners": {
"approvers": [
"richardsonnick",
"rhmdnd",
"smith-xyz"
],
"reviewers": [
"richardsonnick",
"rhmdnd",
"smith-xyz"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
workflow:
as: tls-scanner-hypershift-aws
documentation: |-
The HyperShift AWS TLS scanner workflow provisions an ephemeral HyperShift
hosted cluster with Modern TLS Security Profile enabled and runs the TLS
scanner against both clusters involved in hosted control planes.

HyperShift uses two clusters:
- Management cluster: hosts the hosted control plane pods (kube-apiserver,
etcd, oauth-openshift) in the clusters-<name> namespace on a shared cluster
- Guest (hosted) cluster: the actual OpenShift cluster with worker nodes and
no in-cluster control plane pods

The workflow configures Modern TLS (TLS 1.3) on the hosted cluster and scans
TLS endpoints in both the management control plane and the guest cluster.

The management cluster is hosted in the `osd-hypershift` AWS account and
destroyed after the scan completes.
steps:
pre:
- ref: ipi-install-rbac
- chain: hypershift-setup-root-management-cluster
- chain: hypershift-aws-create
- ref: hypershift-modern-tls
test:
- ref: tls-scanner-hypershift-run
post:
- chain: hypershift-dump
- chain: hypershift-aws-destroy
8 changes: 8 additions & 0 deletions ci-operator/step-registry/tls/scanner/hypershift-run/OWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
approvers:
- richardsonnick
- rhmdnd
- smith-xyz
reviewers:
- richardsonnick
- rhmdnd
- smith-xyz
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"path": "tls/scanner/hypershift-run/tls-scanner-hypershift-run-ref.yaml",
"owners": {
"approvers": [
"richardsonnick",
"rhmdnd",
"smith-xyz"
],
"reviewers": [
"richardsonnick",
"rhmdnd",
"smith-xyz"
]
}
}
Loading