From 42f5ec7c33323132eb17c4bc6c6e71a594acfbe4 Mon Sep 17 00:00:00 2001 From: Alejandro Gullon Date: Mon, 25 May 2026 13:35:09 +0200 Subject: [PATCH 1/5] USHIFT-6746: migrate 23 OTP router tests to Robot Framework MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migrate 23 tests from openshift-tests-private/test/extended/router/microshift.go into the MicroShift repo as Robot Framework tests: Non-disruptive route tests (router-routes.robot): - OCP-60136: reencrypt route via Ingress with destination CA certificate - OCP-60266: edge and passthrough route creation and connectivity - OCP-60283: HTTP route via oc expose and reencrypt route - OCP-72802: namespace ownership default (InterNamespaceAllowed) config - OCP-73152: router-default service as LoadBalancer with route connectivity - OCP-73202: default listening IPs and ports with route connectivity Disruptive config tests (router-config.robot): - OCP-73203: custom listening IPs and ports with route connectivity - OCP-73209: enable/disable router (Removed → Managed cycle) - OCP-77349: tuning options default + custom (env vars + haproxy config) - OCP-80508: custom default certificate with real TLS connectivity - OCP-80510: Old and Intermediate TLS security profiles - OCP-80514: Modern and Custom TLS security profiles - OCP-80517: mTLS Required and Optional client certificate policies - OCP-80518: mTLS allowedSubjectPatterns filter - OCP-80520: wildcard routeAdmissionPolicy - OCP-81996: httpCaptureCookies Prefix match in access logs - OCP-81997: httpCaptureCookies Exact match and maxLength truncation - OCP-82000: httpCaptureHeaders request/response in access logs - OCP-82003: httpCaptureHeaders maxLength adherence - OCP-82004: custom 503/404 error pages - OCP-82014: httpLogFormat with real HAProxy format directives - OCP-82015: syslog logging destination with live rsyslogd pod - OCP-84260: negative logging config validation Skipped OCP-60149 (HTTP Ingress, covered by networking-smoke.robot) and OCP-73621 (namespace ownership toggle, covered by router.robot). Also adds: - test/assets/router/: 8 fixture files from OTP testdata/router/ - test/resources/router.resource: shared keywords for workload deployment, route creation, curl-from-pod, haproxy inspection, cert generation - el98-src@router-extended.sh scenarios (presubmits + releases, bootc el9/el10) - Updates existing router scenarios to reference router.robot explicitly instead of the suites/router/ directory wildcard - Adjusts robocop.toml limits for complex integration tests Co-Authored-By: Claude Sonnet 4.6 pre-commit.check-secrets: ENABLED --- robocop.toml | 6 +- test/assets/router/error-page-404.http | 10 + test/assets/router/error-page-503.http | 10 + .../router/microshift-ingress-destca.yaml | 19 + .../router/microshift-ingress-http.yaml | 16 + test/assets/router/rsyslogd-pod.yaml | 20 + test/assets/router/test-client-pod.yaml | 22 + test/assets/router/web-server-deploy.yaml | 57 + .../router/web-server-signed-deploy.yaml | 94 ++ test/resources/router.resource | 300 ++++++ .../presubmits/el102-src@router-extended.sh | 18 + .../el10/presubmits/el102-src@router.sh | 2 +- .../releases/el102-lrel@osconfig-router.sh | 2 +- .../presubmits/el98-src@router-extended.sh | 18 + .../el9/presubmits/el98-src@router.sh | 2 +- .../el9/releases/el98-lrel@osconfig-router.sh | 2 +- .../presubmits/el98-src@router-extended.sh | 18 + test/scenarios/presubmits/el98-src@router.sh | 2 +- .../releases/el98-lrel@router-extended.sh | 26 + test/scenarios/releases/el98-lrel@router.sh | 2 +- test/suites/router/router-config.robot | 973 ++++++++++++++++++ test/suites/router/router-routes.robot | 294 ++++++ 22 files changed, 1905 insertions(+), 8 deletions(-) create mode 100644 test/assets/router/error-page-404.http create mode 100644 test/assets/router/error-page-503.http create mode 100644 test/assets/router/microshift-ingress-destca.yaml create mode 100644 test/assets/router/microshift-ingress-http.yaml create mode 100644 test/assets/router/rsyslogd-pod.yaml create mode 100644 test/assets/router/test-client-pod.yaml create mode 100644 test/assets/router/web-server-deploy.yaml create mode 100644 test/assets/router/web-server-signed-deploy.yaml create mode 100644 test/resources/router.resource create mode 100644 test/scenarios-bootc/el10/presubmits/el102-src@router-extended.sh create mode 100644 test/scenarios-bootc/el9/presubmits/el98-src@router-extended.sh create mode 100644 test/scenarios/presubmits/el98-src@router-extended.sh create mode 100644 test/scenarios/releases/el98-lrel@router-extended.sh create mode 100644 test/suites/router/router-config.robot create mode 100644 test/suites/router/router-routes.robot diff --git a/robocop.toml b/robocop.toml index 254f1d660f..ad45ece1e0 100644 --- a/robocop.toml +++ b/robocop.toml @@ -15,8 +15,10 @@ ignore = [ ] configure = [ - "too-long-test-case.max_len=40", - "too-many-calls-in-test-case.max_calls=20", + "too-long-test-case.max_len=80", + "too-many-calls-in-test-case.max_calls=45", + "too-many-calls-in-keyword.max_calls=20", + "too-many-arguments.max_args=7", "line-too-long.line_length=200", "file-too-long.max_lines=1000" ] diff --git a/test/assets/router/error-page-404.http b/test/assets/router/error-page-404.http new file mode 100644 index 0000000000..9cce4eddd6 --- /dev/null +++ b/test/assets/router/error-page-404.http @@ -0,0 +1,10 @@ +HTTP/1.0 404 Not Found +Connection: close +Content-Type: text/html + + +Custom:Not Found + +

Custom error page:The requested document was not found.

+ + diff --git a/test/assets/router/error-page-503.http b/test/assets/router/error-page-503.http new file mode 100644 index 0000000000..90c349904e --- /dev/null +++ b/test/assets/router/error-page-503.http @@ -0,0 +1,10 @@ +HTTP/1.0 503 Service Unavailable +Connection: close +Content-Type: text/html + + +Custom:Application Unavailable + +

Custom error page:The requested application is not available.

+ + diff --git a/test/assets/router/microshift-ingress-destca.yaml b/test/assets/router/microshift-ingress-destca.yaml new file mode 100644 index 0000000000..ac3452ff65 --- /dev/null +++ b/test/assets/router/microshift-ingress-destca.yaml @@ -0,0 +1,19 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-ms-reen + annotations: + route.openshift.io/destination-ca-certificate-secret: service-secret + route.openshift.io/termination: reencrypt +spec: + rules: + - host: service-secure-test.example.com + http: + paths: + - backend: + service: + name: service-secure + port: + number: 27443 + path: "/" + pathType: Prefix diff --git a/test/assets/router/microshift-ingress-http.yaml b/test/assets/router/microshift-ingress-http.yaml new file mode 100644 index 0000000000..16fdb304d9 --- /dev/null +++ b/test/assets/router/microshift-ingress-http.yaml @@ -0,0 +1,16 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-on-microshift +spec: + rules: + - host: service-unsecure-test.example.com + http: + paths: + - backend: + service: + name: service-unsecure + port: + number: 27017 + path: "/" + pathType: Prefix diff --git a/test/assets/router/rsyslogd-pod.yaml b/test/assets/router/rsyslogd-pod.yaml new file mode 100644 index 0000000000..07ba1425bc --- /dev/null +++ b/test/assets/router/rsyslogd-pod.yaml @@ -0,0 +1,20 @@ +kind: Pod +apiVersion: v1 +metadata: + name: rsyslogd-pod + labels: + name: rsyslogd +spec: + containers: + - image: quay.io/openshifttest/rsyslogd-container@sha256:e806eb41f05d7cc6eec96bf09c7bcb692f97562d4a983cb019289bd048d9aee2 + name: rsyslogd-container + securityContext: + privileged: true + ports: + - containerPort: 514 + protocol: TCP + - containerPort: 514 + protocol: UDP + resources: + limits: + memory: 340Mi diff --git a/test/assets/router/test-client-pod.yaml b/test/assets/router/test-client-pod.yaml new file mode 100644 index 0000000000..05c2e6638d --- /dev/null +++ b/test/assets/router/test-client-pod.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Pod +metadata: + labels: + app: hello-pod + name: hello-pod +spec: + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + containers: + - image: quay.io/openshifttest/nginx-alpine@sha256:cee6930776b92dc1e93b73f9e5965925d49cff3d2e91e1d071c2f0ff72cbca29 + name: hello-pod + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + ports: + - containerPort: 8080 + - containerPort: 8443 diff --git a/test/assets/router/web-server-deploy.yaml b/test/assets/router/web-server-deploy.yaml new file mode 100644 index 0000000000..9c31424f20 --- /dev/null +++ b/test/assets/router/web-server-deploy.yaml @@ -0,0 +1,57 @@ +apiVersion: v1 +kind: List +items: +- apiVersion: apps/v1 + kind: Deployment + metadata: + name: web-server-deploy + labels: + app: web-server-deploy + spec: + replicas: 1 + selector: + matchLabels: + name: web-server-deploy + template: + metadata: + labels: + name: web-server-deploy + spec: + containers: + - name: nginx + image: quay.io/openshifttest/nginx-alpine@sha256:cee6930776b92dc1e93b73f9e5965925d49cff3d2e91e1d071c2f0ff72cbca29 + ports: + - containerPort: 8080 + name: http + protocol: TCP + - containerPort: 8443 + name: https + protocol: TCP +- kind: Service + apiVersion: v1 + metadata: + labels: + name: service-secure + name: service-secure + spec: + ports: + - name: https + protocol: TCP + port: 27443 + targetPort: 8443 + selector: + name: web-server-deploy +- apiVersion: v1 + kind: Service + metadata: + labels: + name: service-unsecure + name: service-unsecure + spec: + ports: + - name: http + port: 27017 + protocol: TCP + targetPort: 8080 + selector: + name: web-server-deploy \ No newline at end of file diff --git a/test/assets/router/web-server-signed-deploy.yaml b/test/assets/router/web-server-signed-deploy.yaml new file mode 100644 index 0000000000..1a77bb7c09 --- /dev/null +++ b/test/assets/router/web-server-signed-deploy.yaml @@ -0,0 +1,94 @@ +apiVersion: v1 +kind: List +items: +- apiVersion: v1 + kind: ConfigMap + metadata: + name: nginx-config + data: + nginx.conf: | + events { + worker_connections 1024; + } + + http { + server { + listen 8080; + listen [::]:8080; + location / { + root /data/http; + } + } + + server { + listen 8443 ssl http2 default; + listen [::]:8443 ssl http2 default; + server_name _; + ssl_certificate certs/tls.crt; + ssl_certificate_key certs/tls.key; + location / { + root /data/https-default; + } + } + } +- apiVersion: apps/v1 + kind: Deployment + metadata: + name: web-server-deploy + labels: + name: web-server-deploy + spec: + replicas: 1 + selector: + matchExpressions: + - {key: name, operator: In, values: [web-server-deploy]} + template: + metadata: + labels: + name: web-server-deploy + spec: + containers: + - name: nginx + image: quay.io/openshifttest/nginx-alpine@sha256:cee6930776b92dc1e93b73f9e5965925d49cff3d2e91e1d071c2f0ff72cbca29 + volumeMounts: + - name: service-secret + mountPath: /etc/nginx/certs/ + - name: nginx-config + mountPath: /etc/nginx/ + volumes: + - name: service-secret + secret: + secretName: service-secret + - name: nginx-config + configMap: + name: nginx-config +- kind: Service + apiVersion: v1 + metadata: + annotations: + service.beta.openshift.io/serving-cert-secret-name: service-secret + labels: + name: service-secure + name: service-secure + spec: + ports: + - name: https + protocol: TCP + port: 27443 + targetPort: 8443 + selector: + name: web-server-deploy +- apiVersion: v1 + kind: Service + metadata: + labels: + name: service-unsecure + name: service-unsecure + spec: + ports: + - name: http + port: 27017 + protocol: TCP + targetPort: 8080 + selector: + name: web-server-deploy diff --git a/test/resources/router.resource b/test/resources/router.resource new file mode 100644 index 0000000000..4abc7d5592 --- /dev/null +++ b/test/resources/router.resource @@ -0,0 +1,300 @@ +*** Settings *** +Documentation Keywords for router end-to-end testing + +Library OperatingSystem +Library Process +Library String +Library SSHLibrary +Resource oc.resource +Resource common.resource +Resource kubeconfig.resource +Resource microshift-config.resource +Resource microshift-process.resource + + +*** Variables *** +${WEB_SERVER_DEPLOY} ./assets/router/web-server-deploy.yaml +${WEB_SERVER_SIGNED_DEPLOY} ./assets/router/web-server-signed-deploy.yaml +${TEST_CLIENT_POD} ./assets/router/test-client-pod.yaml +${INGRESS_HTTP} ./assets/router/microshift-ingress-http.yaml +${INGRESS_DESTCA} ./assets/router/microshift-ingress-destca.yaml +${RSYSLOGD_POD} ./assets/router/rsyslogd-pod.yaml +${ROUTER_NS} openshift-ingress +${CLIENT_POD_NAME} hello-pod +${CLIENT_POD_LABEL} app\=hello-pod +${WEB_SERVER_LABEL} name\=web-server-deploy + + +*** Keywords *** +Deploy Web Server + [Documentation] Deploy the nginx web server (unsecured) with services. + [Arguments] ${ns}=${NAMESPACE} + Oc Create -f ${WEB_SERVER_DEPLOY} -n ${ns} + Labeled Pod Should Be Ready ${WEB_SERVER_LABEL} ns=${ns} timeout=120s + +Deploy Web Server Signed + [Documentation] Deploy the nginx web server with TLS (service-serving-cert) and services. + [Arguments] ${ns}=${NAMESPACE} + Oc Create -f ${WEB_SERVER_SIGNED_DEPLOY} -n ${ns} + Labeled Pod Should Be Ready ${WEB_SERVER_LABEL} ns=${ns} timeout=120s + +Deploy Test Client Pod + [Documentation] Deploy the test client pod for running curl commands. + [Arguments] ${ns}=${NAMESPACE} + Oc Create -f ${TEST_CLIENT_POD} -n ${ns} + Labeled Pod Should Be Ready ${CLIENT_POD_LABEL} ns=${ns} timeout=120s + +Deploy Rsyslogd Pod + [Documentation] Deploy the rsyslogd pod for syslog testing. + [Arguments] ${ns}=${NAMESPACE} + Oc Create -f ${RSYSLOGD_POD} -n ${ns} + Labeled Pod Should Be Ready name\=rsyslogd ns=${ns} timeout=120s + +Get Web Server Pod Name + [Documentation] Get the name of the first web-server-deploy pod. + [Arguments] ${ns}=${NAMESPACE} + ${name}= Run With Kubeconfig + ... oc get pod -l name=web-server-deploy -n ${ns} -o jsonpath='{.items[0].metadata.name}' + RETURN ${name} + +Create OC Route + [Documentation] Create an OpenShift route of the given type. + ... route_type: http (uses oc expose), or edge/passthrough/reencrypt (uses oc create route) + [Arguments] ${ns} ${route_type} ${route_name} ${service_name} @{extra_args} + IF "${route_type}" == "http" + ${extra}= Catenate SEPARATOR=${SPACE} @{extra_args} + Run With Kubeconfig oc expose -n ${ns} service ${service_name} --name=${route_name} ${extra} + ELSE + ${extra}= Catenate SEPARATOR=${SPACE} @{extra_args} + Run With Kubeconfig oc create route ${route_type} ${route_name} --service=${service_name} -n ${ns} ${extra} + END + +Route Should Be Admitted + [Documentation] Verify the route is admitted by the default ingress controller. + [Arguments] ${route_name} ${ns}=${NAMESPACE} ${timeout}=120s + Wait Until Keyword Succeeds ${timeout} 2s + ... Route Admission Status Should Be ${route_name} ${ns} True + +Route Should Not Be Admitted + [Documentation] Verify the route is NOT admitted by the default ingress controller. + [Arguments] ${route_name} ${ns}=${NAMESPACE} + Wait Until Keyword Succeeds 60s 2s + ... Route Admission Status Should Be ${route_name} ${ns} False + +Route Admission Status Should Be + [Documentation] Helper: assert route admission status equals expected. + [Arguments] ${route_name} ${ns} ${expected} + ${status}= Oc Get JsonPath route ${ns} ${route_name} + ... .status.ingress[0].conditions[0].status + Should Be Equal As Strings ${status} ${expected} + +Curl From Pod + [Documentation] Run curl from a pod via oc exec. Returns stdout. + [Arguments] ${pod_name} ${ns} ${url} ${resolve} @{extra_flags} + ${flags}= Catenate SEPARATOR=${SPACE} @{extra_flags} + ${output}= Run With Kubeconfig + ... oc exec -n ${ns} ${pod_name} -- curl ${url} -sI --resolve ${resolve} --connect-timeout 10 ${flags} + RETURN ${output} + +Wait Until Curl Succeeds From Pod + [Documentation] Retry curl from a pod until response contains expected string. + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${expected}=200 ${timeout}=120s @{extra_flags} + Wait Until Keyword Succeeds + ... ${timeout} + ... 2s + ... Curl From Pod Should Contain + ... ${pod_name} + ... ${ns} + ... ${url} + ... ${resolve} + ... ${expected} + ... @{extra_flags} + +Curl From Pod Should Contain + [Documentation] Helper: curl from pod and assert response contains expected string. + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${expected} @{extra_flags} + ${output}= Curl From Pod ${pod_name} ${ns} ${url} ${resolve} @{extra_flags} + Should Contain ${output} ${expected} + +Get Router Pod Name + [Documentation] Get the name of the router-default pod. + ${name}= Run With Kubeconfig + ... oc get pod -l ingresscontroller.operator.openshift.io/deployment-ingresscontroller=default -n ${ROUTER_NS} -o jsonpath='{.items[0].metadata.name}' + RETURN ${name} + +Get Router Pod IP + [Documentation] Get the pod IP of the router pod. + ${pod_name}= Get Router Pod Name + ${ip}= Oc Get JsonPath pod ${ROUTER_NS} ${pod_name} .status.podIP + RETURN ${ip} + +Router Pod Env Should Have Value + [Documentation] Check an env var value in the router pod. + [Arguments] ${env_name} ${expected_value} + ${actual}= Oc Get JsonPath + ... pod ${ROUTER_NS} ${EMPTY} + ... .items[*].spec.containers[*].env[?(@.name=="${env_name}")].value + Should Be Equal As Strings ${actual} ${expected_value} + +Read Haproxy Config + [Documentation] Read haproxy.config from the router pod. + ${pod_name}= Get Router Pod Name + ${output}= Run With Kubeconfig + ... oc exec -n ${ROUTER_NS} ${pod_name} -- cat haproxy.config + RETURN ${output} + +Get Router Access Logs + [Documentation] Get access logs from the router pod's logs container. + ${output}= Oc Logs deployment/router-default -c logs ${ROUTER_NS} + RETURN ${output} + +Wait For Router Logs To Contain + [Documentation] Wait for the router access logs to contain a specific pattern. + [Arguments] ${pattern} ${timeout}=120s + Wait Until Keyword Succeeds ${timeout} 5s + ... Router Logs Should Contain ${pattern} + +Router Logs Should Contain + [Documentation] Check that router access logs contain a pattern. + [Arguments] ${pattern} + ${logs}= Get Router Access Logs + Should Contain ${logs} ${pattern} + +Wait For Router Ready + [Documentation] Wait for the default router deployment to be available. + Oc Wait namespace/openshift-ingress --for jsonpath='{.status.phase}=Active' --timeout=5m + Named Deployment Should Be Available router-default ${ROUTER_NS} 5m + +Setup Router Config And Restart + [Documentation] Apply drop-in config and restart MicroShift, then wait for router ready. + [Arguments] ${config_content} + Drop In MicroShift Config ${config_content} 10-router + Restart MicroShift + Wait For Router Ready + +Remove Router Config And Restart + [Documentation] Remove the drop-in config and restart MicroShift, then wait for router ready. + Remove Drop In MicroShift Config 10-router + Restart MicroShift + Wait For Router Ready + +Get LB IPs + [Documentation] Get all load balancer IPs of the router-default service as a space-separated string. + ${ips}= Oc Get JsonPath + ... service ${ROUTER_NS} router-default + ... .status.loadBalancer.ingress[*].ip + RETURN ${ips} + +Get LB Port + [Documentation] Get a specific named port of the router-default service. + [Arguments] ${port_name} + ${port}= Oc Get JsonPath + ... service ${ROUTER_NS} router-default + ... .spec.ports[?(@.name=="${port_name}")].port + RETURN ${port} + +Create Configmap From Files + [Documentation] Create a configmap from one or more local file paths. + [Arguments] ${ns} ${name} @{from_files} + ${file_args}= Catenate SEPARATOR=${SPACE} @{from_files} + Run With Kubeconfig oc create configmap ${name} ${file_args} -n ${ns} + +Scale Deployment + [Documentation] Scale a deployment to a given number of replicas. + [Arguments] ${ns} ${deploy_name} ${replicas} + Run With Kubeconfig oc scale deployment/${deploy_name} --replicas=${replicas} -n ${ns} + +Copy Files To Pod + [Documentation] Copy a local path to a pod path via oc cp. + [Arguments] ${ns} ${pod_name} ${src} ${dest} + Run With Kubeconfig oc cp -n ${ns} ${src} ${ns}/${pod_name}:${dest} + +Generate CA Certificate + [Documentation] Generate a self-signed CA key and certificate. + [Arguments] ${ca_key} ${ca_crt} ${ca_subj} + ${result}= Run Process openssl genrsa -out ${ca_key} 2048 shell=True + Should Be Equal As Integers ${result.rc} 0 + ${result}= Run Process + ... openssl req -x509 -new -nodes -key ${ca_key} -sha256 -days 30 -subj "${ca_subj}" -out ${ca_crt} + ... shell=True + Should Be Equal As Integers ${result.rc} 0 + +Generate CSR And Key + [Documentation] Generate a private key and a CSR for the given subject. + [Arguments] ${key_file} ${csr_file} ${subj} + ${result}= Run Process openssl genrsa -out ${key_file} 2048 shell=True + Should Be Equal As Integers ${result.rc} 0 + ${result}= Run Process + ... openssl req -new -key ${key_file} -subj "${subj}" -out ${csr_file} + ... shell=True + Should Be Equal As Integers ${result.rc} 0 + +Sign CSR With CA + [Documentation] Sign a CSR with a CA, writing SAN config to a temp file when provided. + [Arguments] ${csr_file} ${ca_crt} ${ca_key} ${signed_crt} ${san}=${EMPTY} + IF "${san}" != "${EMPTY}" + VAR ${ext_file}= /tmp/router-san-${signed_crt.replace('/', '-')}.cnf + Create File ${ext_file} ${san}\n + ${result}= Run Process + ... openssl x509 -req -in ${csr_file} -CA ${ca_crt} -CAkey ${ca_key} -CAcreateserial -out ${signed_crt} -days 30 -sha256 -extfile ${ext_file} + ... shell=True + Remove File ${ext_file} + ELSE + ${result}= Run Process + ... openssl x509 -req -in ${csr_file} -CA ${ca_crt} -CAkey ${ca_key} -CAcreateserial -out ${signed_crt} -days 30 -sha256 + ... shell=True + END + Should Be Equal As Integers ${result.rc} 0 + +Get First LB IP + [Documentation] Get the first load balancer IP of the router-default service. + ${ip}= Oc Get JsonPath + ... service ${ROUTER_NS} router-default + ... .status.loadBalancer.ingress[0].ip + RETURN ${ip} + +Get Router Deployment Generation + [Documentation] Get the current generation of the router-default deployment. + ${gen}= Oc Get JsonPath + ... deployment ${ROUTER_NS} router-default + ... .metadata.generation + RETURN ${gen} + +Get Host IPs Via SSH + [Documentation] Get all global IPv4 addresses from the MicroShift host. + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command + ... ip -4 addr show scope global | grep -oP 'inet \\K[\\d.]+' + ... sudo=False return_rc=True return_stderr=True return_stdout=True + Should Be Equal As Integers 0 ${rc} + @{ips}= Split String ${stdout} \n + RETURN @{ips} + +Get First Host Interface And IP Via SSH + [Documentation] Get the first non-loopback IPv4 interface name and its IP from the host. + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command + ... ip -4 addr show scope global | awk '/^[0-9]+:/{iface=$2; gsub(":","",iface)} /inet /{print iface, gensub(/\\/.*/, "", 1, $2); exit}' + ... sudo=False + ... return_rc=True + ... return_stderr=True + ... return_stdout=True + Should Be Equal As Integers 0 ${rc} + @{parts}= Split String ${stdout} + ${iface}= Get From List ${parts} 0 + ${ip}= Get From List ${parts} 1 + RETURN ${iface} ${ip} + +Show Invalid Drop In Config Should Fail With + [Documentation] Write an invalid drop-in config, run show-config, verify it fails with expected message, then remove the drop-in. + [Arguments] ${config_content} ${expected_error} + Drop In MicroShift Config ${config_content} 10-router-invalid + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command + ... microshift show-config --mode effective + ... sudo=True return_rc=True return_stderr=True return_stdout=True + Remove Drop In MicroShift Config 10-router-invalid + Should Not Be Equal As Integers ${rc} 0 + Should Contain ${stderr}${stdout} ${expected_error} + +Privileged Namespace + [Documentation] Grant privileged SCC to the default service account in a namespace. + [Arguments] ${ns}=${NAMESPACE} + Run With Kubeconfig oc adm policy add-scc-to-user privileged -z default -n ${ns} diff --git a/test/scenarios-bootc/el10/presubmits/el102-src@router-extended.sh b/test/scenarios-bootc/el10/presubmits/el102-src@router-extended.sh new file mode 100644 index 0000000000..c989fe633a --- /dev/null +++ b/test/scenarios-bootc/el10/presubmits/el102-src@router-extended.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +scenario_create_vms() { + prepare_kickstart host1 kickstart-bootc.ks.template rhel102-bootc-source + launch_vm rhel102-bootc +} + +scenario_remove_vms() { + remove_vm host1 +} + +scenario_run_tests() { + run_tests host1 \ + suites/router/router-routes.robot \ + suites/router/router-config.robot +} diff --git a/test/scenarios-bootc/el10/presubmits/el102-src@router.sh b/test/scenarios-bootc/el10/presubmits/el102-src@router.sh index 5185849f03..85fe4c9b73 100644 --- a/test/scenarios-bootc/el10/presubmits/el102-src@router.sh +++ b/test/scenarios-bootc/el10/presubmits/el102-src@router.sh @@ -13,5 +13,5 @@ scenario_remove_vms() { scenario_run_tests() { run_tests host1 \ - suites/router + suites/router/router.robot } diff --git a/test/scenarios-bootc/el10/releases/el102-lrel@osconfig-router.sh b/test/scenarios-bootc/el10/releases/el102-lrel@osconfig-router.sh index 177e9ad3e6..6fdb06b3d6 100644 --- a/test/scenarios-bootc/el10/releases/el102-lrel@osconfig-router.sh +++ b/test/scenarios-bootc/el10/releases/el102-lrel@osconfig-router.sh @@ -23,7 +23,7 @@ scenario_run_tests() { run_tests host1 \ suites/osconfig/clusterid.robot \ suites/osconfig/systemd-resolved.robot \ - suites/router/ \ + suites/router/router.robot \ suites/otp-workloads/oc-cli.robot \ suites/otp-workloads/statefulset-pvc.robot } diff --git a/test/scenarios-bootc/el9/presubmits/el98-src@router-extended.sh b/test/scenarios-bootc/el9/presubmits/el98-src@router-extended.sh new file mode 100644 index 0000000000..5e34757dc5 --- /dev/null +++ b/test/scenarios-bootc/el9/presubmits/el98-src@router-extended.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +scenario_create_vms() { + prepare_kickstart host1 kickstart-bootc.ks.template rhel98-bootc-source + launch_vm rhel98-bootc +} + +scenario_remove_vms() { + remove_vm host1 +} + +scenario_run_tests() { + run_tests host1 \ + suites/router/router-routes.robot \ + suites/router/router-config.robot +} diff --git a/test/scenarios-bootc/el9/presubmits/el98-src@router.sh b/test/scenarios-bootc/el9/presubmits/el98-src@router.sh index 1f2bc33ce9..7241c7c82d 100644 --- a/test/scenarios-bootc/el9/presubmits/el98-src@router.sh +++ b/test/scenarios-bootc/el9/presubmits/el98-src@router.sh @@ -13,5 +13,5 @@ scenario_remove_vms() { scenario_run_tests() { run_tests host1 \ - suites/router + suites/router/router.robot } diff --git a/test/scenarios-bootc/el9/releases/el98-lrel@osconfig-router.sh b/test/scenarios-bootc/el9/releases/el98-lrel@osconfig-router.sh index 629ce5417e..c6c3c78265 100644 --- a/test/scenarios-bootc/el9/releases/el98-lrel@osconfig-router.sh +++ b/test/scenarios-bootc/el9/releases/el98-lrel@osconfig-router.sh @@ -23,7 +23,7 @@ scenario_run_tests() { run_tests host1 \ suites/osconfig/clusterid.robot \ suites/osconfig/systemd-resolved.robot \ - suites/router/ \ + suites/router/router.robot \ suites/otp-workloads/oc-cli.robot \ suites/otp-workloads/statefulset-pvc.robot } diff --git a/test/scenarios/presubmits/el98-src@router-extended.sh b/test/scenarios/presubmits/el98-src@router-extended.sh new file mode 100644 index 0000000000..f73f17cced --- /dev/null +++ b/test/scenarios/presubmits/el98-src@router-extended.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +scenario_create_vms() { + prepare_kickstart host1 kickstart.ks.template rhel-9.8-microshift-source + launch_vm rhel-9.8 +} + +scenario_remove_vms() { + remove_vm host1 +} + +scenario_run_tests() { + run_tests host1 \ + suites/router/router-routes.robot \ + suites/router/router-config.robot +} diff --git a/test/scenarios/presubmits/el98-src@router.sh b/test/scenarios/presubmits/el98-src@router.sh index 820af8566d..c18c108c5b 100644 --- a/test/scenarios/presubmits/el98-src@router.sh +++ b/test/scenarios/presubmits/el98-src@router.sh @@ -12,5 +12,5 @@ scenario_remove_vms() { } scenario_run_tests() { - run_tests host1 suites/router/ + run_tests host1 suites/router/router.robot } diff --git a/test/scenarios/releases/el98-lrel@router-extended.sh b/test/scenarios/releases/el98-lrel@router-extended.sh new file mode 100644 index 0000000000..302f93c830 --- /dev/null +++ b/test/scenarios/releases/el98-lrel@router-extended.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +start_image="rhel98-brew-lrel-optional" + +scenario_create_vms() { + exit_if_commit_not_found "${start_image}" + + prepare_kickstart host1 kickstart.ks.template "${start_image}" + launch_vm rhel-9.8 --vm_vcpus 4 +} + +scenario_remove_vms() { + exit_if_commit_not_found "${start_image}" + + remove_vm host1 +} + +scenario_run_tests() { + exit_if_commit_not_found "${start_image}" + + run_tests host1 \ + suites/router/router-routes.robot \ + suites/router/router-config.robot +} diff --git a/test/scenarios/releases/el98-lrel@router.sh b/test/scenarios/releases/el98-lrel@router.sh index 91501d6085..999c597083 100644 --- a/test/scenarios/releases/el98-lrel@router.sh +++ b/test/scenarios/releases/el98-lrel@router.sh @@ -20,5 +20,5 @@ scenario_remove_vms() { scenario_run_tests() { exit_if_commit_not_found "${start_image}" - run_tests host1 suites/router/ + run_tests host1 suites/router/router.robot } diff --git a/test/suites/router/router-config.robot b/test/suites/router/router-config.robot new file mode 100644 index 0000000000..6e6b8c6e05 --- /dev/null +++ b/test/suites/router/router-config.robot @@ -0,0 +1,973 @@ +*** Settings *** +Documentation Router ingress controller configuration tests (disruptive) +... Migrated from openshift-tests-private: +... OCP-73203, OCP-73209, OCP-77349, OCP-80508, OCP-80510, OCP-80514, +... OCP-80517, OCP-80518, OCP-80520, OCP-81996, OCP-81997, OCP-82000, +... OCP-82003, OCP-82004, OCP-82014, OCP-82015, OCP-84260 + +Resource ../../resources/common.resource +Resource ../../resources/oc.resource +Resource ../../resources/microshift-config.resource +Resource ../../resources/microshift-process.resource +Resource ../../resources/ostree-health.resource +Resource ../../resources/router.resource + +Suite Setup Setup Suite With Namespace +Suite Teardown Teardown Suite With Namespace + +Test Tags restart slow + + +*** Variables *** +${BASE_DOMAIN} apps.example.com +${ALT_HTTP_PORT} 10080 +${ALT_HTTPS_PORT} 10443 +${ROUTER_DROP_IN} 10-router + +${LOGGING_INVALID_MAXLENGTH_NEG1} SEPARATOR=\n +... --- +... ingress: +... \ \ accessLogging: +... \ \ \ \ httpCaptureCookies: +... \ \ \ \ - matchType: Exact +... \ \ \ \ \ \ maxLength: -1 +... \ \ \ \ \ \ name: foo +... \ \ \ \ status: Enabled + +${LOGGING_INVALID_MAXLENGTH_ZERO} SEPARATOR=\n +... --- +... ingress: +... \ \ accessLogging: +... \ \ \ \ httpCaptureCookies: +... \ \ \ \ - matchType: Exact +... \ \ \ \ \ \ maxLength: 0 +... \ \ \ \ \ \ name: foo +... \ \ \ \ status: Enabled + +${LOGGING_INVALID_COOKIE_NAME} SEPARATOR=\n +... --- +... ingress: +... \ \ accessLogging: +... \ \ \ \ httpCaptureCookies: +... \ \ \ \ - matchType: Exact +... \ \ \ \ \ \ maxLength: 100 +... \ \ \ \ \ \ name: "foo 33#?-" +... \ \ \ \ status: Enabled + +${LOGGING_INVALID_HEADER_MAXLENGTH} SEPARATOR=\n +... --- +... ingress: +... \ \ accessLogging: +... \ \ \ \ httpCaptureHeaders: +... \ \ \ \ \ \ request: +... \ \ \ \ \ \ - maxLength: -1 +... \ \ \ \ \ \ \ \ name: Host +... \ \ \ \ \ \ response: +... \ \ \ \ \ \ - maxLength: 10 +... \ \ \ \ \ \ \ \ name: "Server" +... \ \ \ \ status: Enabled + +${LOGGING_INVALID_STATUS} SEPARATOR=\n +... --- +... ingress: +... \ \ accessLogging: +... \ \ \ \ httpCaptureHeaders: +... \ \ \ \ \ \ request: +... \ \ \ \ \ \ - maxLength: 10 +... \ \ \ \ \ \ \ \ name: Host +... \ \ \ \ status: Enable + +${LOGGING_COOKIES_NO_STATUS} SEPARATOR=\n +... --- +... ingress: +... \ \ accessLogging: +... \ \ \ \ httpCaptureCookies: +... \ \ \ \ - matchType: Prefix +... \ \ \ \ \ \ maxLength: 100 +... \ \ \ \ \ \ namePrefix: foo + + +*** Test Cases *** +Custom Listening IPs And Ports + [Documentation] Verify configuring a specific listen address and custom HTTP/HTTPS ports + ... causes the router LB to expose only that IP on the custom ports, and routes + ... are reachable through those ports. + ... OCP-73203 + + ${iface} ${host_ip}= Get First Host Interface And IP Via SSH + ${config}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ listenAddress: + ... \ \ - ${iface} + ... \ \ ports: + ... \ \ \ \ http: ${ALT_HTTP_PORT} + ... \ \ \ \ https: ${ALT_HTTPS_PORT} + Setup Router Config And Restart ${config} + + ${lb_ips}= Get LB IPs + Should Contain ${lb_ips} ${host_ip} + ${http_port}= Get LB Port http + Should Be Equal As Strings ${http_port} ${ALT_HTTP_PORT} + ${https_port}= Get LB Port https + Should Be Equal As Strings ${https_port} ${ALT_HTTPS_PORT} + + Deploy Web Server Signed + Deploy Test Client Pod + VAR ${http_host}= service-unsecure-ocp73203.${BASE_DOMAIN} + VAR ${edge_host}= route-edge-ocp73203.${BASE_DOMAIN} + VAR ${pass_host}= route-passth-ocp73203.${BASE_DOMAIN} + VAR ${reen_host}= route-reen-ocp73203.${BASE_DOMAIN} + Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${http_host} + Create OC Route ${NAMESPACE} edge route-edge service-unsecure --hostname=${edge_host} + Create OC Route ${NAMESPACE} passthrough route-passth service-secure --hostname=${pass_host} + Create OC Route ${NAMESPACE} reencrypt route-reen service-secure --hostname=${reen_host} + Route Should Be Admitted route-reen + + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${http_host}:${ALT_HTTP_PORT} ${http_host}:${ALT_HTTP_PORT}:${host_ip} 200 + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${edge_host}:${ALT_HTTPS_PORT} ${edge_host}:${ALT_HTTPS_PORT}:${host_ip} 200 -k + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${pass_host}:${ALT_HTTPS_PORT} ${pass_host}:${ALT_HTTPS_PORT}:${host_ip} 200 -k + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${reen_host}:${ALT_HTTPS_PORT} ${reen_host}:${ALT_HTTPS_PORT}:${host_ip} 200 -k + [Teardown] Remove Router Config And Restart + +Enable Disable Router + [Documentation] Verify setting ingress status to Removed deletes the openshift-ingress namespace, + ... and setting it back to Managed restores the router LB with correct IPs and ports. + ... OCP-73209 + + ${config_removed}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ status: Removed + Setup Router Config And Restart ${config_removed} + Oc Wait namespace/openshift-ingress --for=delete --timeout=300s + + ${config_managed}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ status: Managed + Setup Router Config And Restart ${config_managed} + + ${svc_type}= Oc Get JsonPath service ${ROUTER_NS} router-default .spec.type + Should Be Equal As Strings ${svc_type} LoadBalancer + ${http_port}= Get LB Port http + Should Be Equal As Strings ${http_port} 80 + ${https_port}= Get LB Port https + Should Be Equal As Strings ${https_port} 443 + ${lb_ips}= Get LB IPs + Should Not Be Empty ${lb_ips} + [Teardown] Remove Router Config And Restart + +Tuning Options Customization + [Documentation] Verify default tuning env vars and haproxy config values, then apply + ... custom tuning and verify all values are updated. + ... OCP-77349 + + VAR ${http_host}= service-unsecure-ocp77349.${BASE_DOMAIN} + Deploy Web Server + Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${http_host} + + Router Pod Env Should Have Value ROUTER_BUF_SIZE 32768 + Router Pod Env Should Have Value ROUTER_MAX_REWRITE_SIZE 8192 + Router Pod Env Should Have Value ROUTER_DEFAULT_CLIENT_TIMEOUT 30s + Router Pod Env Should Have Value ROUTER_CLIENT_FIN_TIMEOUT 1s + Router Pod Env Should Have Value ROUTER_DEFAULT_SERVER_TIMEOUT 30s + Router Pod Env Should Have Value ROUTER_DEFAULT_SERVER_FIN_TIMEOUT 1s + Router Pod Env Should Have Value ROUTER_DEFAULT_TUNNEL_TIMEOUT 1h + Router Pod Env Should Have Value ROUTER_INSPECT_DELAY 5s + Router Pod Env Should Have Value ROUTER_THREADS 4 + Router Pod Env Should Have Value ROUTER_MAX_CONNECTIONS 50000 + + ${haproxy}= Read Haproxy Config + Should Contain ${haproxy} tune.bufsize 32768 + Should Contain ${haproxy} tune.maxrewrite 8192 + Should Contain ${haproxy} timeout client 30s + Should Contain ${haproxy} timeout server 30s + Should Contain ${haproxy} timeout tunnel 1h + Should Contain ${haproxy} nbthread 4 + Should Contain ${haproxy} maxconn 50000 + + ${config}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ forwardedHeaderPolicy: "Replace" + ... \ \ httpCompression: + ... \ \ \ \ mimeTypes: + ... \ \ \ \ - "image" + ... \ \ logEmptyRequests: "Ignore" + ... \ \ tuningOptions: + ... \ \ \ \ clientFinTimeout: "2s" + ... \ \ \ \ clientTimeout: "60s" + ... \ \ \ \ headerBufferBytes: 65536 + ... \ \ \ \ headerBufferMaxRewriteBytes: 16384 + ... \ \ \ \ healthCheckInterval: "10s" + ... \ \ \ \ maxConnections: 100000 + ... \ \ \ \ serverFinTimeout: "2s" + ... \ \ \ \ serverTimeout: "60s" + ... \ \ \ \ threadCount: 8 + ... \ \ \ \ tlsInspectDelay: "10s" + ... \ \ \ \ tunnelTimeout: "2h" + Setup Router Config And Restart ${config} + + Router Pod Env Should Have Value ROUTER_BUF_SIZE 65536 + Router Pod Env Should Have Value ROUTER_MAX_REWRITE_SIZE 16384 + Router Pod Env Should Have Value ROUTER_DEFAULT_CLIENT_TIMEOUT 60s + Router Pod Env Should Have Value ROUTER_CLIENT_FIN_TIMEOUT 2s + Router Pod Env Should Have Value ROUTER_DEFAULT_SERVER_TIMEOUT 60s + Router Pod Env Should Have Value ROUTER_DEFAULT_SERVER_FIN_TIMEOUT 2s + Router Pod Env Should Have Value ROUTER_DEFAULT_TUNNEL_TIMEOUT 2h + Router Pod Env Should Have Value ROUTER_INSPECT_DELAY 10s + Router Pod Env Should Have Value ROUTER_THREADS 8 + Router Pod Env Should Have Value ROUTER_MAX_CONNECTIONS 100000 + + ${haproxy}= Read Haproxy Config + Should Contain ${haproxy} tune.bufsize 65536 + Should Contain ${haproxy} tune.maxrewrite 16384 + Should Contain ${haproxy} timeout client 60s + Should Contain ${haproxy} timeout server 60s + Should Contain ${haproxy} timeout tunnel 2h + Should Contain ${haproxy} nbthread 8 + Should Contain ${haproxy} maxconn 100000 + [Teardown] Remove Router Config And Restart + +Custom Default Certificate + [Documentation] Verify a custom TLS certificate secret can be configured as the default + ... ingress certificate, and that routes use the custom cert for TLS. + ... OCP-80508 + [Setup] Prepare Custom Cert For Test 80508 route-edge80508.${BASE_DOMAIN} + + ${config}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ certificateSecret: "router-test-cert" + Setup Router Config And Restart ${config} + + Create OC Route ${NAMESPACE} edge route-edge service-unsecure --hostname=${CERT_EDGE_HOST} + Route Should Be Admitted route-edge + + ${vol}= Oc Get JsonPath + ... deployment ${ROUTER_NS} router-default + ... ..volumes[?(@.name=="default-certificate")].secret.secretName + Should Contain ${vol} router-test-cert + + ${router_pod}= Get Router Pod Name + ${cert_info}= Run With Kubeconfig + ... oc exec -n ${ROUTER_NS} ${router_pod} -- openssl x509 -noout -in /etc/pki/tls/private/tls.crt -text + Should Contain ${cert_info} CN = MS-default-CA + + Deploy Web Server + Deploy Test Client Pod + Copy Files To Pod ${NAMESPACE} ${CLIENT_POD_NAME} ${CERT_TMPDIR} /data/certs + ${router_ip}= Get Router Pod IP + VAR ${resolve}= ${CERT_EDGE_HOST}:443:${router_ip} + + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${CERT_EDGE_HOST} ${resolve} 200 + ... --cacert /data/certs/ca.crt --cert /data/certs/usr.crt --key /data/certs/usr.key + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${CERT_EDGE_HOST} ${resolve} 200 -k + [Teardown] Run Keywords + ... Remove Router Config And Restart + ... AND Run With Kubeconfig oc delete secret router-test-cert -n ${ROUTER_NS} --ignore-not-found + +Old And Intermediate TLS Profiles + [Documentation] Verify the default Intermediate TLS profile cipher settings, then apply Old + ... profile and verify updated cipher settings, then restore Intermediate. + ... OCP-80510 + + Router Pod Env Should Have Value SSL_MIN_VERSION TLSv1.2 + ${ciphers}= Oc Get JsonPath + ... pod ${ROUTER_NS} ${EMPTY} + ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_CIPHERSUITES")].value + Should Contain ${ciphers} TLS_AES_128_GCM_SHA256 + + ${config_old}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ tlsSecurityProfile: + ... \ \ \ \ old: {} + ... \ \ \ \ type: Old + Setup Router Config And Restart ${config_old} + + Router Pod Env Should Have Value SSL_MIN_VERSION TLSv1.1 + ${ciphers}= Oc Get JsonPath + ... pod ${ROUTER_NS} ${EMPTY} + ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_CIPHERS")].value + Should Contain ${ciphers} DES-CBC3-SHA + + ${config_intermediate}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ tlsSecurityProfile: + ... \ \ \ \ intermediate: {} + ... \ \ \ \ type: Intermediate + Setup Router Config And Restart ${config_intermediate} + + Router Pod Env Should Have Value SSL_MIN_VERSION TLSv1.2 + ${ciphers}= Oc Get JsonPath + ... pod ${ROUTER_NS} ${EMPTY} + ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_CIPHERSUITES")].value + Should Contain ${ciphers} TLS_AES_128_GCM_SHA256 + [Teardown] Remove Router Config And Restart + +Modern And Custom TLS Profiles + [Documentation] Verify Modern TLS profile enforces TLSv1.3 in env vars and haproxy config, + ... then apply a Custom profile with specific ciphers. + ... OCP-80514 + + ${config_modern}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ tlsSecurityProfile: + ... \ \ \ \ modern: {} + ... \ \ \ \ type: Modern + Setup Router Config And Restart ${config_modern} + + Router Pod Env Should Have Value SSL_MIN_VERSION TLSv1.3 + ${ciphers}= Oc Get JsonPath + ... pod ${ROUTER_NS} ${EMPTY} + ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_CIPHERSUITES")].value + Should Contain ${ciphers} TLS_AES_128_GCM_SHA256 + ${haproxy}= Read Haproxy Config + Should Contain ${haproxy} ssl-default-bind-options ssl-min-ver TLSv1.3 + + ${config_custom}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ tlsSecurityProfile: + ... \ \ \ \ custom: + ... \ \ \ \ \ \ ciphers: + ... \ \ \ \ \ \ - DHE-RSA-AES256-GCM-SHA384 + ... \ \ \ \ \ \ - ECDHE-ECDSA-AES256-GCM-SHA384 + ... \ \ \ \ \ \ minTLSVersion: VersionTLS12 + ... \ \ \ \ type: Custom + Setup Router Config And Restart ${config_custom} + + Router Pod Env Should Have Value SSL_MIN_VERSION TLSv1.2 + ${ciphers}= Oc Get JsonPath + ... pod ${ROUTER_NS} ${EMPTY} + ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_CIPHERS")].value + Should Contain ${ciphers} DHE-RSA-AES256-GCM-SHA384 + [Teardown] Remove Router Config And Restart + +MTLS Optional And Required Policy + [Documentation] Verify mTLS with clientCertificatePolicy Required rejects connections without + ... client cert, and Optional policy allows them. + ... OCP-80517 + [Setup] Prepare MTLS Cert For Test 80517 route-edge80517.${BASE_DOMAIN} + + Run With Kubeconfig oc create configmap ocp80517 --from-file=ca-bundle.pem=${MTLS_CA_CRT} -n ${ROUTER_NS} + + ${env}= Oc Get JsonPath + ... pod ${ROUTER_NS} ${EMPTY} + ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_MUTUAL_TLS_AUTH")].value + Should Be Empty ${env} + + ${config_required}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ clientTLS: + ... \ \ \ \ clientCA: + ... \ \ \ \ \ \ name: "ocp80517" + ... \ \ \ \ clientCertificatePolicy: "Required" + Setup Router Config And Restart ${config_required} + + Router Pod Env Should Have Value ROUTER_MUTUAL_TLS_AUTH required + + Deploy Web Server + Deploy Test Client Pod + Copy Files To Pod ${NAMESPACE} ${CLIENT_POD_NAME} ${MTLS_TMPDIR} /data/certs + Create OC Route ${NAMESPACE} edge route-edge + ... service-unsecure + ... --hostname=${MTLS_EDGE_HOST} + ... --cert=${MTLS_USR_CRT} + ... --key=${MTLS_USR_KEY} + Route Should Be Admitted route-edge + + ${router_ip}= Get Router Pod IP + VAR ${resolve}= ${MTLS_EDGE_HOST}:443:${router_ip} + + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} https://${MTLS_EDGE_HOST} ${resolve} 200 OK + ... --cacert /data/certs/ca.crt --cert /data/certs/usr.crt --key /data/certs/usr.key + + ${output}= Curl From Pod ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${MTLS_EDGE_HOST} ${resolve} -skv + Should Contain ${output} SSL_read + + ${config_optional}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ clientTLS: + ... \ \ \ \ clientCA: + ... \ \ \ \ \ \ name: "ocp80517" + ... \ \ \ \ clientCertificatePolicy: "Optional" + Setup Router Config And Restart ${config_optional} + + Router Pod Env Should Have Value ROUTER_MUTUAL_TLS_AUTH optional + + ${router_ip}= Get Router Pod IP + VAR ${resolve}= ${MTLS_EDGE_HOST}:443:${router_ip} + + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} https://${MTLS_EDGE_HOST} ${resolve} 200 OK + ... --cacert /data/certs/ca.crt --cert /data/certs/usr.crt --key /data/certs/usr.key + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} https://${MTLS_EDGE_HOST} ${resolve} 200 OK -k + [Teardown] Run Keywords + ... Remove Router Config And Restart + ... AND Run With Kubeconfig oc delete configmap ocp80517 -n ${ROUTER_NS} --ignore-not-found + +MTLS Subject Filter + [Documentation] Verify mTLS with allowedSubjectPatterns allows a cert matching the CN filter + ... and blocks a cert not matching it. + ... OCP-80518 + [Setup] Prepare Two MTLS Certs For Test 80518 route-edge80518.${BASE_DOMAIN} route2-edge80518.${BASE_DOMAIN} + + Run With Kubeconfig oc create configmap ocp80518 --from-file=ca-bundle.pem=${MTLS2_CA_CRT} -n ${ROUTER_NS} + + ${config}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ clientTLS: + ... \ \ \ \ allowedSubjectPatterns: ["/CN=example-test.com"] + ... \ \ \ \ clientCA: + ... \ \ \ \ \ \ name: "ocp80518" + ... \ \ \ \ clientCertificatePolicy: "Required" + Setup Router Config And Restart ${config} + + ${env}= Oc Get JsonPath + ... pod ${ROUTER_NS} ${EMPTY} + ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_MUTUAL_TLS_AUTH_FILTER")].value + Should Contain ${env} example-test.com + + Deploy Web Server + Deploy Test Client Pod + Copy Files To Pod ${NAMESPACE} ${CLIENT_POD_NAME} ${MTLS2_TMPDIR} /data/certs + Create OC Route ${NAMESPACE} edge route-edge + ... service-unsecure --hostname=${MTLS2_HOST1} + ... --cert=${MTLS2_USR_CRT1} --key=${MTLS2_USR_KEY1} + Create OC Route ${NAMESPACE} edge route-edge2 + ... service-unsecure --hostname=${MTLS2_HOST2} + ... --cert=${MTLS2_USR_CRT2} --key=${MTLS2_USR_KEY2} + Route Should Be Admitted route-edge + Route Should Be Admitted route-edge2 + + ${router_ip}= Get Router Pod IP + + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${MTLS2_HOST1} ${MTLS2_HOST1}:443:${router_ip} 200 OK + ... --cacert /data/certs/ca.crt --cert /data/certs/usr1.crt --key /data/certs/usr1.key + + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${MTLS2_HOST2} ${MTLS2_HOST2}:443:${router_ip} 403 + ... --cacert /data/certs/ca.crt --cert /data/certs/usr2.crt --key /data/certs/usr2.key + [Teardown] Run Keywords + ... Remove Router Config And Restart + ... AND Run With Kubeconfig oc delete configmap ocp80518 -n ${ROUTER_NS} --ignore-not-found + +Wildcard Route Admission Policy + [Documentation] Verify WildcardsDisallowed rejects wildcard routes, WildcardsAllowed admits them, + ... and reverting to WildcardsDisallowed rejects them again. + ... OCP-80520 + [Setup] Run Keywords + ... Deploy Web Server + ... AND Deploy Test Client Pod + + VAR ${wildcard_host}= wildcard.${BASE_DOMAIN} + VAR ${any_host}= any.${BASE_DOMAIN} + + ${env}= Oc Get JsonPath + ... pod ${ROUTER_NS} ${EMPTY} + ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_ALLOW_WILDCARD_ROUTES")].value + Should Be Equal As Strings ${env} false + + Create OC Route ${NAMESPACE} http unsecure80520 service-unsecure + ... --hostname=${wildcard_host} --wildcard-policy=Subdomain + Route Should Not Be Admitted unsecure80520 + + ${config_allowed}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ routeAdmissionPolicy: + ... \ \ \ \ wildcardPolicy: "WildcardsAllowed" + Setup Router Config And Restart ${config_allowed} + + Router Pod Env Should Have Value ROUTER_ALLOW_WILDCARD_ROUTES true + Route Should Be Admitted unsecure80520 + + ${router_ip}= Get Router Pod IP + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${wildcard_host} ${wildcard_host}:80:${router_ip} 200 + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${any_host} ${any_host}:80:${router_ip} 200 + + ${config_disallowed}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ routeAdmissionPolicy: + ... \ \ \ \ wildcardPolicy: "WildcardsDisallowed" + Setup Router Config And Restart ${config_disallowed} + + Router Pod Env Should Have Value ROUTER_ALLOW_WILDCARD_ROUTES false + Route Should Not Be Admitted unsecure80520 + [Teardown] Remove Router Config And Restart + +HTTP Capture Cookies Prefix Match + [Documentation] Verify httpCaptureCookies with Prefix match captures cookies matching the + ... prefix in router logs across HTTP, edge, and reencrypt routes. + ... OCP-81996 + + ${config}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ accessLogging: + ... \ \ \ \ httpCaptureCookies: + ... \ \ \ \ - matchType: Prefix + ... \ \ \ \ \ \ maxLength: 100 + ... \ \ \ \ \ \ namePrefix: foo + ... \ \ \ \ status: Enabled + Setup Router Config And Restart ${config} + + Deploy Web Server Signed + Deploy Test Client Pod + VAR ${routehost}= route-unsec81996.${BASE_DOMAIN} + VAR ${edge_host}= route-edge81996.${BASE_DOMAIN} + VAR ${reen_host}= route-reen81996.${BASE_DOMAIN} + Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${routehost} + Route Should Be Admitted route-http + Create OC Route ${NAMESPACE} edge route-edge service-unsecure --hostname=${edge_host} + Route Should Be Admitted route-edge + Create OC Route ${NAMESPACE} reencrypt route-reen service-secure --hostname=${reen_host} + Route Should Be Admitted route-reen + + ${router_ip}= Get Router Pod IP + + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${routehost}/index.html ${routehost}:80:${router_ip} 200 -b fo=nobar + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${routehost}/index.html ${routehost}:80:${router_ip} 200 -b foo=bar + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${routehost}/index.html ${routehost}:80:${router_ip} 200 -b foo22=bar22 + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${edge_host}/index.html ${edge_host}:443:${router_ip} 200 -b foo=barforedge -k + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${reen_host}/index.html ${reen_host}:443:${router_ip} 200 -b foo=barforreen -k + + Wait For Router Logs To Contain foo=bar + Wait For Router Logs To Contain foo22=bar22 + Wait For Router Logs To Contain foo=barforedge + Wait For Router Logs To Contain foo=barforreen + ${logs}= Get Router Access Logs + Should Not Contain ${logs} fo=nobar + [Teardown] Remove Router Config And Restart + +HTTP Capture Cookies Exact Match And MaxLength + [Documentation] Verify httpCaptureCookies with Exact match captures only exact-named cookies, + ... and maxLength truncates cookie values in logs. + ... OCP-81997 + + ${config}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ accessLogging: + ... \ \ \ \ httpCaptureCookies: + ... \ \ \ \ - matchType: Exact + ... \ \ \ \ \ \ maxLength: 100 + ... \ \ \ \ \ \ name: foo + ... \ \ \ \ status: Enabled + Setup Router Config And Restart ${config} + + Deploy Web Server + Deploy Test Client Pod + VAR ${routehost}= route-unsec81997.${BASE_DOMAIN} + Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${routehost} + Route Should Be Admitted route-http + + ${router_ip}= Get Router Pod IP + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${routehost}/index.html ${routehost}:80:${router_ip} 200 -b fooor=nobar + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${routehost}/index.html ${routehost}:80:${router_ip} 200 -b foo=bar + + Wait For Router Logs To Contain foo=bar + ${logs}= Get Router Access Logs + Should Not Contain ${logs} fooor=nobar + + ${config2}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ accessLogging: + ... \ \ \ \ httpCaptureCookies: + ... \ \ \ \ - matchType: Exact + ... \ \ \ \ \ \ maxLength: 10 + ... \ \ \ \ \ \ name: foo + ... \ \ \ \ status: Enabled + Setup Router Config And Restart ${config2} + ${router_ip}= Get Router Pod IP + + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${routehost}/index.html ${routehost}:80:${router_ip} 200 -b foo=bar89abdef + + Wait For Router Logs To Contain foo=bar89a + ${logs}= Get Router Access Logs + Should Not Contain ${logs} foo=bar89ab + [Teardown] Remove Router Config And Restart + +HTTP Capture Headers Request And Response + [Documentation] Verify httpCaptureHeaders captures request Host and response Server headers + ... in router logs, including for edge and reencrypt routes. + ... OCP-82000 + + ${config}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ accessLogging: + ... \ \ \ \ httpCaptureHeaders: + ... \ \ \ \ \ \ request: + ... \ \ \ \ \ \ - maxLength: 120 + ... \ \ \ \ \ \ \ \ name: Host + ... \ \ \ \ \ \ response: + ... \ \ \ \ \ \ - maxLength: 120 + ... \ \ \ \ \ \ \ \ name: "Server" + ... \ \ \ \ status: Enabled + Setup Router Config And Restart ${config} + + Deploy Web Server Signed + Deploy Test Client Pod + VAR ${routehost}= route-unsec82000.${BASE_DOMAIN} + VAR ${edge_host}= route-edge82000.${BASE_DOMAIN} + VAR ${reen_host}= route-reen82000.${BASE_DOMAIN} + Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${routehost} + Route Should Be Admitted route-http + Create OC Route ${NAMESPACE} edge route-edge service-unsecure --hostname=${edge_host} + Route Should Be Admitted route-edge + Create OC Route ${NAMESPACE} reencrypt route-reen service-secure --hostname=${reen_host} + Route Should Be Admitted route-reen + + ${router_pod}= Get Router Pod Name + ${haproxy}= Run With Kubeconfig + ... oc exec -n ${ROUTER_NS} ${router_pod} -- grep -A 20 "frontend fe_sni" haproxy.config + Should Contain ${haproxy} capture request header Host len 120 + Should Contain ${haproxy} capture response header Server len 120 + + ${router_ip}= Get Router Pod IP + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${routehost}/index.html ${routehost}:80:${router_ip} 200 + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${edge_host}/index.html ${edge_host}:443:${router_ip} 200 -k + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${reen_host}/index.html ${reen_host}:443:${router_ip} 200 -k + + Wait For Router Logs To Contain ${routehost} + Wait For Router Logs To Contain ${edge_host} + Wait For Router Logs To Contain ${reen_host} + [Teardown] Remove Router Config And Restart + +HTTP Capture Headers MaxLength Adherence + [Documentation] Verify httpCaptureHeaders maxLength truncates captured header values in logs. + ... OCP-82003 + + VAR ${routehost}= route-unsec82003.${BASE_DOMAIN} + + ${config}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ accessLogging: + ... \ \ \ \ httpCaptureHeaders: + ... \ \ \ \ \ \ request: + ... \ \ \ \ \ \ - maxLength: 16 + ... \ \ \ \ \ \ \ \ name: Host + ... \ \ \ \ \ \ response: + ... \ \ \ \ \ \ - maxLength: 5 + ... \ \ \ \ \ \ \ \ name: "Server" + ... \ \ \ \ status: Enabled + Setup Router Config And Restart ${config} + + Deploy Web Server + Deploy Test Client Pod + Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${routehost} + Route Should Be Admitted route-http + + ${router_ip}= Get Router Pod IP + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${routehost}/index.html ${routehost}:80:${router_ip} 200 + + # route-unsec82003.apps.e is 16 chars, so the full hostname should not appear + Wait For Router Logs To Contain route-unsec82003.ap + ${logs}= Get Router Access Logs + Should Not Contain ${logs} ${routehost} + # nginx server version is 5+ chars, so only "nginx" should appear without the version + Should Contain ${logs} nginx + Should Not Contain ${logs} nginx/ + [Teardown] Remove Router Config And Restart + +Custom HTTP Error Pages + [Documentation] Verify custom 503 and 404 error pages are served when configured via + ... httpErrorCodePages configmap. + ... OCP-82004 + + Create Configmap From Files ${ROUTER_NS} custom-82004-error-code-pages + ... --from-file=./assets/router/error-page-503.http + ... --from-file=./assets/router/error-page-404.http + + ${config}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ httpErrorCodePages: + ... \ \ \ \ name: custom-82004-error-code-pages + Setup Router Config And Restart ${config} + + Deploy Web Server + Deploy Test Client Pod + VAR ${routehost}= route-unsec82004.${BASE_DOMAIN} + VAR ${noexist_host}= not-exist82004.${BASE_DOMAIN} + Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${routehost} + Route Should Be Admitted route-http + + ${router_pod}= Get Router Pod Name + ${error503}= Run With Kubeconfig + ... oc exec -n ${ROUTER_NS} ${router_pod} -- cat /var/lib/haproxy/errorfiles/error-page-503.http + Should Contain ${error503} Custom:Application Unavailable + ${error404}= Run With Kubeconfig + ... oc exec -n ${ROUTER_NS} ${router_pod} -- cat /var/lib/haproxy/errorfiles/error-page-404.http + Should Contain ${error404} Custom:Not Found + + ${router_ip}= Get Router Pod IP + ${output}= Run With Kubeconfig + ... oc exec -n ${NAMESPACE} ${CLIENT_POD_NAME} -- curl http://${noexist_host} -s --resolve ${noexist_host}:80:${router_ip} --connect-timeout 10 + Should Contain ${output} Custom:Not Found + + Scale Deployment ${NAMESPACE} web-server-deploy 0 + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${routehost} ${routehost}:80:${router_ip} Custom:Application Unavailable + [Teardown] Run Keywords + ... Remove Router Config And Restart + ... AND Run With Kubeconfig oc delete configmap custom-82004-error-code-pages -n ${ROUTER_NS} --ignore-not-found + +HTTP Log Format + [Documentation] Verify httpLogFormat with HAProxy format directives produces structured log + ... output with the correct format. + ... OCP-82014 + + ${config}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ accessLogging: + ... \ \ \ \ httpLogFormat: "%{+Q}r" + ... \ \ \ \ status: Enabled + Setup Router Config And Restart ${config} + + Deploy Web Server + Deploy Test Client Pod + VAR ${routehost}= route-unsec82014.${BASE_DOMAIN} + Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${routehost} + Route Should Be Admitted route-http + + ${router_ip}= Get Router Pod IP + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${routehost}/path/second/index.html ${routehost}:80:${router_ip} 200 + + Wait For Router Logs To Contain /path/second/index.html + ${logs}= Get Router Access Logs + Should Match Regexp ${logs} haproxy\\[[0-9]+\\]: "HEAD /path/second/index.html HTTP + + ${config2}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ accessLogging: + ... \ \ \ \ httpLogFormat: "%ci:%cp %si:%sp %HU %ST" + ... \ \ \ \ status: Enabled + Setup Router Config And Restart ${config2} + ${router_ip}= Get Router Pod IP + + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${routehost}/path/second/index.html ${routehost}:80:${router_ip} 200 + + Wait For Router Logs To Contain /path/second/index.html + ${logs}= Get Router Access Logs + Should Match Regexp ${logs} + ... haproxy\\[[0-9]+\\]: [0-9\\.a-fA-F:]+:[0-9]+ [0-9\\.a-fA-F:]+:8080 /path/second/index.html 200 + [Teardown] Remove Router Config And Restart + +Syslog Logging Destination + [Documentation] Verify logging to a syslog server delivers router access logs to the syslog pod, + ... and changing the facility is reflected in the haproxy global config. + ... OCP-82015 + + Privileged Namespace + Deploy Rsyslogd Pod + Deploy Web Server + Deploy Test Client Pod + ${syslog_ip}= Oc Get JsonPath pod ${NAMESPACE} rsyslogd-pod .status.podIP + + ${config}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ accessLogging: + ... \ \ \ \ destination: + ... \ \ \ \ \ \ syslog: + ... \ \ \ \ \ \ \ \ address: ${syslog_ip} + ... \ \ \ \ \ \ \ \ port: 514 + ... \ \ \ \ \ \ type: Syslog + ... \ \ \ \ status: Enabled + Setup Router Config And Restart ${config} + + VAR ${routehost}= route-unsec82015.${BASE_DOMAIN} + Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${routehost} + Route Should Be Admitted route-http + + ${router_pod}= Get Router Pod Name + ${haproxy}= Read Haproxy Config + Should Contain ${haproxy} log ${syslog_ip}:514 len 1024 local1 info + + ${router_ip}= Get Router Pod IP + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${routehost}/path/second/index.html ${routehost}:80:${router_ip} 200 + + Wait Until Keyword Succeeds 60s 3s + ... Syslog Pod Should Contain /path/second/index.html + + ${config2}= Catenate SEPARATOR=\n + ... --- + ... ingress: + ... \ \ accessLogging: + ... \ \ \ \ destination: + ... \ \ \ \ \ \ syslog: + ... \ \ \ \ \ \ \ \ address: ${syslog_ip} + ... \ \ \ \ \ \ \ \ port: 514 + ... \ \ \ \ \ \ \ \ facility: local2 + ... \ \ \ \ \ \ type: Syslog + ... \ \ \ \ status: Enabled + Setup Router Config And Restart ${config2} + + ${haproxy}= Read Haproxy Config + Should Contain ${haproxy} log ${syslog_ip}:514 len 1024 local2 info + [Teardown] Remove Router Config And Restart + +Negative Logging Config Validation + [Documentation] Verify invalid logging configurations are rejected by microshift show-config, + ... and that setting httpCaptureCookies without status: Enabled does not activate logging. + ... OCP-84260 + + Show Invalid Drop In Config Should Fail With + ... ${LOGGING_INVALID_MAXLENGTH_NEG1} Must be between 1 and 1024 + Show Invalid Drop In Config Should Fail With + ... ${LOGGING_INVALID_MAXLENGTH_ZERO} Must be between 1 and 1024 + Show Invalid Drop In Config Should Fail With + ... ${LOGGING_INVALID_COOKIE_NAME} contains invalid characters + Show Invalid Drop In Config Should Fail With + ... ${LOGGING_INVALID_HEADER_MAXLENGTH} maxLength must be at least 1 + Show Invalid Drop In Config Should Fail With + ... ${LOGGING_INVALID_STATUS} invalid access logging status: Enable + + ${gen_before}= Get Router Deployment Generation + Drop In MicroShift Config ${LOGGING_COOKIES_NO_STATUS} 10-router + Restart MicroShift + Wait For Router Ready + ${gen_after}= Get Router Deployment Generation + Should Be Equal As Strings ${gen_before} ${gen_after} + + ${haproxy}= Read Haproxy Config + Should Not Contain ${haproxy} capture cookie foo len 100 + + [Teardown] Remove Router Config And Restart + + +*** Keywords *** +Prepare Custom Cert For Test + [Documentation] Generate CA and user cert for custom certificate test, create TLS secret. + [Arguments] ${case_id} ${edge_host} + VAR ${tmpdir}= /tmp/ocp-${case_id} + Create Directory ${tmpdir} + VAR ${CERT_TMPDIR}= ${tmpdir} scope=TEST + VAR ${CERT_EDGE_HOST}= ${edge_host} scope=TEST + + Generate CA Certificate + ... ${tmpdir}/ca.key ${tmpdir}/ca.crt /CN=MS-default-CA + + ${san}= Catenate SEPARATOR=\n + ... [ v3_req ] + ... subjectAltName = @alt_names + ... [ alt_names ] + ... DNS.1 = *.${BASE_DOMAIN} + Generate CSR And Key ${tmpdir}/usr.key ${tmpdir}/usr.csr /CN=example-ne.com + Sign CSR With CA ${tmpdir}/usr.csr ${tmpdir}/ca.crt ${tmpdir}/ca.key ${tmpdir}/usr.crt ${san} + + Run With Kubeconfig + ... oc create secret tls router-test-cert --cert=${tmpdir}/ca.crt --key=${tmpdir}/ca.key -n ${ROUTER_NS} + Deploy Web Server + +Prepare MTLS Cert For Test + [Documentation] Generate CA and client cert for mTLS tests. + [Arguments] ${case_id} ${edge_host} + VAR ${tmpdir}= /tmp/ocp-${case_id}-ca + Create Directory ${tmpdir} + VAR ${MTLS_TMPDIR}= ${tmpdir} scope=TEST + VAR ${MTLS_EDGE_HOST}= ${edge_host} scope=TEST + VAR ${MTLS_CA_CRT}= ${tmpdir}/ca.crt scope=TEST + VAR ${MTLS_USR_CRT}= ${tmpdir}/usr.crt scope=TEST + VAR ${MTLS_USR_KEY}= ${tmpdir}/usr.key scope=TEST + + Generate CA Certificate ${tmpdir}/ca.key ${tmpdir}/ca.crt /CN=MS-Test-Root-CA + Generate CSR And Key ${tmpdir}/usr.key ${tmpdir}/usr.csr /CN=example-test.com + VAR ${san}= subjectAltName = DNS.1:*.${BASE_DOMAIN},DNS.2:${edge_host} + Sign CSR With CA ${tmpdir}/usr.csr ${tmpdir}/ca.crt ${tmpdir}/ca.key ${tmpdir}/usr.crt ${san} + +Prepare Two MTLS Certs For Test + [Documentation] Generate CA and two client certs with different subjects for mTLS subject filter test. + [Arguments] ${case_id} ${host1} ${host2} + VAR ${tmpdir}= /tmp/ocp-${case_id}-ca + Create Directory ${tmpdir} + VAR ${MTLS2_TMPDIR}= ${tmpdir} scope=TEST + VAR ${MTLS2_CA_CRT}= ${tmpdir}/ca.crt scope=TEST + VAR ${MTLS2_HOST1}= ${host1} scope=TEST + VAR ${MTLS2_HOST2}= ${host2} scope=TEST + VAR ${MTLS2_USR_CRT1}= ${tmpdir}/usr1.crt scope=TEST + VAR ${MTLS2_USR_KEY1}= ${tmpdir}/usr1.key scope=TEST + VAR ${MTLS2_USR_CRT2}= ${tmpdir}/usr2.crt scope=TEST + VAR ${MTLS2_USR_KEY2}= ${tmpdir}/usr2.key scope=TEST + + Generate CA Certificate ${tmpdir}/ca.key ${tmpdir}/ca.crt /CN=MS-Test-Root-CA + Generate CSR And Key ${tmpdir}/usr1.key ${tmpdir}/usr1.csr /CN=example-test.com + VAR ${san1}= subjectAltName = DNS.1:*.${BASE_DOMAIN},DNS.2:${host1} + Sign CSR With CA ${tmpdir}/usr1.csr ${tmpdir}/ca.crt ${tmpdir}/ca.key ${tmpdir}/usr1.crt ${san1} + Generate CSR And Key ${tmpdir}/usr2.key ${tmpdir}/usr2.csr /CN=example-test2.com + VAR ${san2}= subjectAltName = DNS.1:*.${BASE_DOMAIN},DNS.2:${host2} + Sign CSR With CA ${tmpdir}/usr2.csr ${tmpdir}/ca.crt ${tmpdir}/ca.key ${tmpdir}/usr2.crt ${san2} + +Syslog Pod Should Contain + [Documentation] Check that the rsyslogd pod logs contain a pattern. + [Arguments] ${pattern} + ${logs}= Oc Logs rsyslogd-pod --tail=20 ${NAMESPACE} + Should Contain ${logs} ${pattern} diff --git a/test/suites/router/router-routes.robot b/test/suites/router/router-routes.robot new file mode 100644 index 0000000000..89dcc3eb45 --- /dev/null +++ b/test/suites/router/router-routes.robot @@ -0,0 +1,294 @@ +*** Settings *** +Documentation Router end-to-end route tests +... Migrated from openshift-tests-private: +... OCP-60136, OCP-60266, OCP-60283, OCP-72802, OCP-73152, OCP-73202 + +Resource ../../resources/common.resource +Resource ../../resources/oc.resource +Resource ../../resources/microshift-network.resource +Resource ../../resources/router.resource + +Suite Setup Setup Suite With Namespace +Suite Teardown Teardown Suite With Namespace + +Test Tags slow + + +*** Variables *** +${BASE_DOMAIN} apps.example.com + + +*** Test Cases *** +Reencrypt Route Via Ingress With Destination CA + [Documentation] Verify a reencrypt route created via a Kubernetes Ingress resource with + ... destination CA certificate is admitted and reachable. + ... OCP-60136 + [Setup] Setup Reencrypt Ingress Test + + ${router_ip}= Get Router Pod IP + ${srv_pod}= Get Web Server Pod Name + Wait Until Curl Succeeds From Pod + ... ${srv_pod} ${NAMESPACE} + ... https://service-secure-test.example.com:443 service-secure-test.example.com:443:${router_ip} + ... 200 -k + ${haproxy}= Read Haproxy Config + Should Contain ${haproxy} backend be_secure:${NAMESPACE}:ingress-ms-reen + [Teardown] Teardown Reencrypt Ingress Test + +Edge And Passthrough Routes + [Documentation] Verify edge-terminated and passthrough route creation and connectivity. + ... OCP-60266 + [Setup] Deploy Web Server + + ${router_ip}= Get Router Pod IP + ${srv_pod}= Get Web Server Pod Name + VAR ${pass_host}= route-pass-60266.${BASE_DOMAIN} + VAR ${edge_host}= route-edge-60266.${BASE_DOMAIN} + + Create OC Route ${NAMESPACE} passthrough ms-pass service-secure + ... --hostname=${pass_host} + Route Should Be Admitted ms-pass + Wait Until Curl Succeeds From Pod + ... ${srv_pod} ${NAMESPACE} + ... https://${pass_host}:443 ${pass_host}:443:${router_ip} + ... 200 -k + ${haproxy}= Read Haproxy Config + Should Contain ${haproxy} backend be_tcp:${NAMESPACE}:ms-pass + + Create OC Route ${NAMESPACE} edge ms-edge service-unsecure + ... --hostname=${edge_host} + Route Should Be Admitted ms-edge + Wait Until Curl Succeeds From Pod + ... ${srv_pod} ${NAMESPACE} + ... https://${edge_host}:443 ${edge_host}:443:${router_ip} + ... 200 -k + ${haproxy}= Read Haproxy Config + Should Contain ${haproxy} backend be_edge_http:${NAMESPACE}:ms-edge + + [Teardown] Run Keywords + ... Oc Delete route/ms-pass route/ms-edge -n ${NAMESPACE} + ... AND Oc Delete -f ${WEB_SERVER_DEPLOY} -n ${NAMESPACE} + +HTTP And Reencrypt Routes + [Documentation] Verify HTTP route via oc expose and reencrypt route creation and connectivity. + ... OCP-60283 + [Setup] Deploy Web Server Signed + + ${router_ip}= Get Router Pod IP + ${srv_pod}= Get Web Server Pod Name + VAR ${http_host}= route-http-60283.${BASE_DOMAIN} + VAR ${reen_host}= route-reen-60283.${BASE_DOMAIN} + + Create OC Route ${NAMESPACE} http ms-http service-unsecure + ... --hostname=${http_host} + Route Should Be Admitted ms-http + Wait Until Curl Succeeds From Pod + ... ${srv_pod} ${NAMESPACE} + ... http://${http_host}:80 ${http_host}:80:${router_ip} + ... 200 + ${haproxy}= Read Haproxy Config + Should Contain ${haproxy} backend be_http:${NAMESPACE}:ms-http + + Create OC Route ${NAMESPACE} reencrypt ms-reen service-secure + ... --hostname=${reen_host} + Route Should Be Admitted ms-reen + Wait Until Curl Succeeds From Pod + ... ${srv_pod} ${NAMESPACE} + ... https://${reen_host}:443 ${reen_host}:443:${router_ip} + ... 200 -k + ${haproxy}= Read Haproxy Config + Should Contain ${haproxy} backend be_secure:${NAMESPACE}:ms-reen + + [Teardown] Run Keywords + ... Oc Delete route/ms-http route/ms-reen -n ${NAMESPACE} + ... AND Oc Delete -f ${WEB_SERVER_SIGNED_DEPLOY} -n ${NAMESPACE} + +Namespace Ownership Default Config + [Documentation] Verify the default InterNamespaceAllowed config allows routes from different + ... namespaces to share the same hostname with different paths. + ... OCP-72802 + [Setup] Setup Two Namespace Test + + ${router_ip}= Get Router Pod IP + VAR ${http_host}= service-unsecure-ocp72802.${BASE_DOMAIN} + VAR ${edge_host}= route-edge-ocp72802.${BASE_DOMAIN} + VAR ${reen_host}= route-reen-ocp72802.${BASE_DOMAIN} + + ${env}= Oc Get JsonPath + ... pod ${ROUTER_NS} ${EMPTY} + ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_DISABLE_NAMESPACE_OWNERSHIP_CHECK")].value + Should Be Equal As Strings ${env} true + + Create OC Route ${NS1} http service-unsecure service-unsecure + ... --hostname=${http_host} --path=/path + Create OC Route ${NS1} edge route-edge service-unsecure + ... --hostname=${edge_host} --path=/path + Create OC Route ${NS1} reencrypt route-reen service-secure + ... --hostname=${reen_host} --path=/path + Create OC Route ${NS2} http service-unsecure service-unsecure + ... --hostname=${http_host} --path=/test + Create OC Route ${NS2} edge route-edge service-unsecure + ... --hostname=${edge_host} --path=/test + Create OC Route ${NS2} reencrypt route-reen service-secure + ... --hostname=${reen_host} --path=/test + + Route Should Be Admitted service-unsecure ${NS1} + Route Should Be Admitted route-edge ${NS1} + Route Should Be Admitted route-reen ${NS1} + Route Should Be Admitted service-unsecure ${NS2} + Route Should Be Admitted route-edge ${NS2} + Route Should Be Admitted route-reen ${NS2} + + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NS1} + ... http://${http_host}/path/index.html ${http_host}:80:${router_ip} + ... 200 + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NS1} + ... http://${http_host}/test/index.html ${http_host}:80:${router_ip} + ... 200 + + [Teardown] Teardown Two Namespace Test + +Router Load Balancer Service Type + [Documentation] Verify the router-default service is of type LoadBalancer with IPs assigned, + ... and that all route types are reachable through the LB IP. + ... OCP-73152 + [Setup] Run Keywords + ... Deploy Web Server Signed + ... AND Deploy Test Client Pod + + ${svc_type}= Oc Get JsonPath service ${ROUTER_NS} router-default .spec.type + Should Be Equal As Strings ${svc_type} LoadBalancer + ${lb_ips}= Get LB IPs + Should Not Be Empty ${lb_ips} + + VAR ${http_host}= service-unsecure-ocp73152.${BASE_DOMAIN} + VAR ${edge_host}= route-edge-ocp73152.${BASE_DOMAIN} + VAR ${pass_host}= route-passth-ocp73152.${BASE_DOMAIN} + VAR ${reen_host}= route-reen-ocp73152.${BASE_DOMAIN} + + Create OC Route ${NAMESPACE} http route-http service-unsecure + ... --hostname=${http_host} + Create OC Route ${NAMESPACE} edge route-edge service-unsecure + ... --hostname=${edge_host} + Create OC Route ${NAMESPACE} passthrough route-passth service-secure + ... --hostname=${pass_host} + Create OC Route ${NAMESPACE} reencrypt route-reen service-secure + ... --hostname=${reen_host} + Route Should Be Admitted route-reen + + ${lb_ip}= Fetch From Left ${lb_ips} ${SPACE} + + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${http_host} ${http_host}:80:${lb_ip} + ... 200 + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${edge_host} ${edge_host}:443:${lb_ip} + ... 200 -k + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${pass_host} ${pass_host}:443:${lb_ip} + ... 200 -k + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${reen_host} ${reen_host}:443:${lb_ip} + ... 200 -k + + [Teardown] Run Keywords + ... Oc Delete route/route-http route/route-edge route/route-passth route/route-reen -n ${NAMESPACE} + ... AND Oc Delete -f ${WEB_SERVER_SIGNED_DEPLOY} -n ${NAMESPACE} + ... AND Oc Delete -f ${TEST_CLIENT_POD} -n ${NAMESPACE} + +Default Listening IPs And Ports + [Documentation] Verify the router-default service LB IPs match all host IPs, default ports + ... are 80 and 443, and all route types are reachable through each LB IP. + ... OCP-73202 + [Setup] Run Keywords + ... Deploy Web Server Signed + ... AND Deploy Test Client Pod + + ${http_port}= Get LB Port http + Should Be Equal As Strings ${http_port} 80 + ${https_port}= Get LB Port https + Should Be Equal As Strings ${https_port} 443 + + ${lb_ips}= Get LB IPs + Should Not Be Empty ${lb_ips} + @{host_ips}= Get Host IPs Via SSH + ${sorted_host_ips}= Evaluate " ".join(sorted(${host_ips})) + ${sorted_lb_ips}= Evaluate " ".join(sorted("${lb_ips}".split())) + Should Be Equal As Strings ${sorted_lb_ips} ${sorted_host_ips} + + VAR ${http_host}= service-unsecure-ocp73202.${BASE_DOMAIN} + VAR ${edge_host}= route-edge-ocp73202.${BASE_DOMAIN} + VAR ${pass_host}= route-passth-ocp73202.${BASE_DOMAIN} + VAR ${reen_host}= route-reen-ocp73202.${BASE_DOMAIN} + + Create OC Route ${NAMESPACE} http route-http service-unsecure + ... --hostname=${http_host} + Create OC Route ${NAMESPACE} edge route-edge service-unsecure + ... --hostname=${edge_host} + Create OC Route ${NAMESPACE} passthrough route-passth service-secure + ... --hostname=${pass_host} + Create OC Route ${NAMESPACE} reencrypt route-reen service-secure + ... --hostname=${reen_host} + Route Should Be Admitted route-reen + + @{ips}= Split String ${lb_ips} + FOR ${lb_ip} IN @{ips} + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${http_host} ${http_host}:80:${lb_ip} + ... 200 + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${edge_host} ${edge_host}:443:${lb_ip} + ... 200 -k + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${pass_host} ${pass_host}:443:${lb_ip} + ... 200 -k + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${reen_host} ${reen_host}:443:${lb_ip} + ... 200 -k + END + + [Teardown] Run Keywords + ... Oc Delete route/route-http route/route-edge route/route-passth route/route-reen -n ${NAMESPACE} + ... AND Oc Delete -f ${WEB_SERVER_SIGNED_DEPLOY} -n ${NAMESPACE} + ... AND Oc Delete -f ${TEST_CLIENT_POD} -n ${NAMESPACE} + + +*** Keywords *** +Setup Reencrypt Ingress Test + [Documentation] Deploy web-server-signed and apply the destCA ingress. + Deploy Web Server Signed + Oc Create -f ${INGRESS_DESTCA} -n ${NAMESPACE} + Route Should Be Admitted ingress-ms-reen + +Teardown Reencrypt Ingress Test + [Documentation] Delete the destCA ingress and web-server deployment. + Oc Delete -f ${INGRESS_DESTCA} -n ${NAMESPACE} + Oc Delete -f ${WEB_SERVER_SIGNED_DEPLOY} -n ${NAMESPACE} + +Setup Two Namespace Test + [Documentation] Create two extra namespaces and deploy workloads in each. + VAR ${NS1}= ${NAMESPACE}-ocp72802-1 + VAR ${NS2}= ${NAMESPACE}-ocp72802-2 + VAR ${NS1}= ${NS1} scope=TEST + VAR ${NS2}= ${NS2} scope=TEST + Create Namespace ${NS1} + Create Namespace ${NS2} + Deploy Test Client Pod ${NS1} + Deploy Web Server ${NS1} + Deploy Test Client Pod ${NS2} + Deploy Web Server ${NS2} + +Teardown Two Namespace Test + [Documentation] Delete the extra namespaces. + Remove Namespace ${NS1} + Remove Namespace ${NS2} From ba69fa0c9ec9c115ca2dacc33fd45f2054ee199f Mon Sep 17 00:00:00 2001 From: Alejandro Gullon Date: Mon, 25 May 2026 15:05:05 +0200 Subject: [PATCH 2/5] USHIFT-6746: move router-extended scenarios to releases only Remove router-extended scenarios from presubmits and add them under releases for bootc el9 and el10. Non-disruptive smoke tests belong in presubmits; the full router-extended suite (with many disruptive restarts) is better suited for release validation. Co-Authored-By: Claude Sonnet 4.6 pre-commit.check-secrets: ENABLED --- .../presubmits/el102-src@router-extended.sh | 18 ------------- .../releases/el102-lrel@router-extended.sh | 26 +++++++++++++++++++ .../presubmits/el98-src@router-extended.sh | 18 ------------- .../el9/releases/el98-lrel@router-extended.sh | 26 +++++++++++++++++++ .../presubmits/el98-src@router-extended.sh | 18 ------------- 5 files changed, 52 insertions(+), 54 deletions(-) delete mode 100644 test/scenarios-bootc/el10/presubmits/el102-src@router-extended.sh create mode 100644 test/scenarios-bootc/el10/releases/el102-lrel@router-extended.sh delete mode 100644 test/scenarios-bootc/el9/presubmits/el98-src@router-extended.sh create mode 100644 test/scenarios-bootc/el9/releases/el98-lrel@router-extended.sh delete mode 100644 test/scenarios/presubmits/el98-src@router-extended.sh diff --git a/test/scenarios-bootc/el10/presubmits/el102-src@router-extended.sh b/test/scenarios-bootc/el10/presubmits/el102-src@router-extended.sh deleted file mode 100644 index c989fe633a..0000000000 --- a/test/scenarios-bootc/el10/presubmits/el102-src@router-extended.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -scenario_create_vms() { - prepare_kickstart host1 kickstart-bootc.ks.template rhel102-bootc-source - launch_vm rhel102-bootc -} - -scenario_remove_vms() { - remove_vm host1 -} - -scenario_run_tests() { - run_tests host1 \ - suites/router/router-routes.robot \ - suites/router/router-config.robot -} diff --git a/test/scenarios-bootc/el10/releases/el102-lrel@router-extended.sh b/test/scenarios-bootc/el10/releases/el102-lrel@router-extended.sh new file mode 100644 index 0000000000..5e7f13f12e --- /dev/null +++ b/test/scenarios-bootc/el10/releases/el102-lrel@router-extended.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +start_image="rhel102-bootc-brew-lrel-optional" + +scenario_create_vms() { + exit_if_image_not_found "${start_image}" + + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" + launch_vm rhel102-bootc --vm_vcpus 4 +} + +scenario_remove_vms() { + exit_if_image_not_found "${start_image}" + + remove_vm host1 +} + +scenario_run_tests() { + exit_if_image_not_found "${start_image}" + + run_tests host1 \ + suites/router/router-routes.robot \ + suites/router/router-config.robot +} diff --git a/test/scenarios-bootc/el9/presubmits/el98-src@router-extended.sh b/test/scenarios-bootc/el9/presubmits/el98-src@router-extended.sh deleted file mode 100644 index 5e34757dc5..0000000000 --- a/test/scenarios-bootc/el9/presubmits/el98-src@router-extended.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -scenario_create_vms() { - prepare_kickstart host1 kickstart-bootc.ks.template rhel98-bootc-source - launch_vm rhel98-bootc -} - -scenario_remove_vms() { - remove_vm host1 -} - -scenario_run_tests() { - run_tests host1 \ - suites/router/router-routes.robot \ - suites/router/router-config.robot -} diff --git a/test/scenarios-bootc/el9/releases/el98-lrel@router-extended.sh b/test/scenarios-bootc/el9/releases/el98-lrel@router-extended.sh new file mode 100644 index 0000000000..75986c5142 --- /dev/null +++ b/test/scenarios-bootc/el9/releases/el98-lrel@router-extended.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +start_image="rhel98-bootc-brew-lrel-optional" + +scenario_create_vms() { + exit_if_image_not_found "${start_image}" + + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" + launch_vm rhel98-bootc --vm_vcpus 4 +} + +scenario_remove_vms() { + exit_if_image_not_found "${start_image}" + + remove_vm host1 +} + +scenario_run_tests() { + exit_if_image_not_found "${start_image}" + + run_tests host1 \ + suites/router/router-routes.robot \ + suites/router/router-config.robot +} diff --git a/test/scenarios/presubmits/el98-src@router-extended.sh b/test/scenarios/presubmits/el98-src@router-extended.sh deleted file mode 100644 index f73f17cced..0000000000 --- a/test/scenarios/presubmits/el98-src@router-extended.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -scenario_create_vms() { - prepare_kickstart host1 kickstart.ks.template rhel-9.8-microshift-source - launch_vm rhel-9.8 -} - -scenario_remove_vms() { - remove_vm host1 -} - -scenario_run_tests() { - run_tests host1 \ - suites/router/router-routes.robot \ - suites/router/router-config.robot -} From d8a7c7ff6ff6c3bf5e52a95196190895211433ad Mon Sep 17 00:00:00 2001 From: Alejandro Gullon Date: Mon, 25 May 2026 15:53:20 +0200 Subject: [PATCH 3/5] USHIFT-6746: refactor router tests to comply with robocop limits Revert robocop.toml to original limits and refactor the new robot tests to comply without configuration changes: - Fix LEN07: reduce Wait Until Curl Succeeds From Pod and Curl From Pod Should Contain to 5 args; add specialized HTTPS/cookie/client-cert curl keyword variants in router.resource - Fix LEN04/LEN06: extract long test bodies into helper keywords and move YAML config strings to the Variables section - Fix LEN03: split Prepare Two MTLS Certs, Curl All Cookie Routes, Verify Header Capture, and Verify Syslog Logging into sub-keywords - Fix VAR10: uppercase non-local TEST-scoped variables consistently Co-Authored-By: Claude Sonnet 4.6 pre-commit.check-secrets: ENABLED --- robocop.toml | 6 +- test/resources/router.resource | 137 +++- test/suites/router/router-config.robot | 944 +++++++++++++------------ test/suites/router/router-routes.robot | 221 +++--- 4 files changed, 683 insertions(+), 625 deletions(-) diff --git a/robocop.toml b/robocop.toml index ad45ece1e0..254f1d660f 100644 --- a/robocop.toml +++ b/robocop.toml @@ -15,10 +15,8 @@ ignore = [ ] configure = [ - "too-long-test-case.max_len=80", - "too-many-calls-in-test-case.max_calls=45", - "too-many-calls-in-keyword.max_calls=20", - "too-many-arguments.max_args=7", + "too-long-test-case.max_len=40", + "too-many-calls-in-test-case.max_calls=20", "line-too-long.line_length=200", "file-too-long.max_lines=1000" ] diff --git a/test/resources/router.resource b/test/resources/router.resource index 4abc7d5592..d65267bdb9 100644 --- a/test/resources/router.resource +++ b/test/resources/router.resource @@ -88,34 +88,115 @@ Route Admission Status Should Be ... .status.ingress[0].conditions[0].status Should Be Equal As Strings ${status} ${expected} +Create And Admit Four Route Types + [Documentation] Create HTTP, edge, passthrough, and reencrypt routes and wait for reencrypt to be admitted. + [Arguments] ${http_host} ${edge_host} ${pass_host} ${reen_host} + Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${http_host} + Create OC Route ${NAMESPACE} edge route-edge service-unsecure --hostname=${edge_host} + Create OC Route ${NAMESPACE} passthrough route-passth service-secure --hostname=${pass_host} + Create OC Route ${NAMESPACE} reencrypt route-reen service-secure --hostname=${reen_host} + Route Should Be Admitted route-reen + Curl From Pod [Documentation] Run curl from a pod via oc exec. Returns stdout. - [Arguments] ${pod_name} ${ns} ${url} ${resolve} @{extra_flags} - ${flags}= Catenate SEPARATOR=${SPACE} @{extra_flags} + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${flags}=${EMPTY} ${output}= Run With Kubeconfig ... oc exec -n ${ns} ${pod_name} -- curl ${url} -sI --resolve ${resolve} --connect-timeout 10 ${flags} RETURN ${output} +Curl From Pod Should Contain + [Documentation] Curl from a pod and assert response contains expected string (no extra flags). + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${expected}=200 + ${output}= Curl From Pod ${pod_name} ${ns} ${url} ${resolve} + Should Contain ${output} ${expected} + Wait Until Curl Succeeds From Pod - [Documentation] Retry curl from a pod until response contains expected string. - [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${expected}=200 ${timeout}=120s @{extra_flags} - Wait Until Keyword Succeeds - ... ${timeout} - ... 2s - ... Curl From Pod Should Contain - ... ${pod_name} - ... ${ns} - ... ${url} - ... ${resolve} - ... ${expected} - ... @{extra_flags} + [Documentation] Retry curl from a pod (no extra flags) until response contains expected string. + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${expected}=200 + Wait Until Keyword Succeeds 120s 2s + ... Curl From Pod Should Contain ${pod_name} ${ns} ${url} ${resolve} ${expected} + +Curl HTTPS From Pod Should Contain + [Documentation] Curl HTTPS from a pod using -k, assert response contains expected string. + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${expected}=200 + ${output}= Curl From Pod ${pod_name} ${ns} ${url} ${resolve} -k + Should Contain ${output} ${expected} -Curl From Pod Should Contain - [Documentation] Helper: curl from pod and assert response contains expected string. - [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${expected} @{extra_flags} - ${output}= Curl From Pod ${pod_name} ${ns} ${url} ${resolve} @{extra_flags} +Wait Until HTTPS Curl Succeeds From Pod + [Documentation] Retry HTTPS curl (with -k) from a pod until response contains expected string. + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${expected}=200 + Wait Until Keyword Succeeds 120s 2s + ... Curl HTTPS From Pod Should Contain ${pod_name} ${ns} ${url} ${resolve} ${expected} + +Curl With Cookie Should Return 200 + [Documentation] Curl from a pod with a cookie and assert 200 response. + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${cookie} + ${output}= Curl From Pod ${pod_name} ${ns} ${url} ${resolve} -b ${cookie} + Should Contain ${output} 200 + +Wait Until Curl With Cookie Succeeds From Pod + [Documentation] Retry curl with a cookie until 200 response. + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${cookie} + Wait Until Keyword Succeeds 120s 2s + ... Curl With Cookie Should Return 200 ${pod_name} ${ns} ${url} ${resolve} ${cookie} + +HTTPS Curl With Cookie Should Return 200 + [Documentation] Curl HTTPS from a pod with a cookie (using -k) and assert 200 response. + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${cookie} + ${output}= Curl From Pod ${pod_name} ${ns} ${url} ${resolve} -k -b ${cookie} + Should Contain ${output} 200 + +Wait Until HTTPS Curl With Cookie Succeeds From Pod + [Documentation] Retry HTTPS curl with a cookie until 200 response. + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${cookie} + Wait Until Keyword Succeeds 120s 2s + ... HTTPS Curl With Cookie Should Return 200 ${pod_name} ${ns} ${url} ${resolve} ${cookie} + +Curl With Client Cert Should Return + [Documentation] Curl with client cert from /data/certs/ and assert expected response. + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${expected}=200 OK + ${output}= Curl From Pod ${pod_name} ${ns} ${url} ${resolve} + ... --cacert /data/certs/ca.crt --cert /data/certs/usr.crt --key /data/certs/usr.key Should Contain ${output} ${expected} +Wait Until Curl With Client Cert Succeeds + [Documentation] Retry curl with client cert until expected response. + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${expected}=200 OK + Wait Until Keyword Succeeds 120s 2s + ... Curl With Client Cert Should Return ${pod_name} ${ns} ${url} ${resolve} ${expected} + +Curl With Cert File Should Return 200 + [Documentation] Curl with a specific cert file prefix from /data/certs/ and assert 200 response. + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${cert_prefix} + ${output}= Curl From Pod ${pod_name} ${ns} ${url} ${resolve} + ... --cacert /data/certs/ca.crt --cert /data/certs/${cert_prefix}.crt --key /data/certs/${cert_prefix}.key + Should Contain ${output} 200 OK + +Wait Until Curl With Cert File Succeeds + [Documentation] Retry curl with specific cert file until 200 response. + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${cert_prefix} + Wait Until Keyword Succeeds 120s 2s + ... Curl With Cert File Should Return 200 ${pod_name} ${ns} ${url} ${resolve} ${cert_prefix} + +Curl With Cert File Should Return 403 + [Documentation] Curl with a specific cert file prefix from /data/certs/ and assert 403 response. + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${cert_prefix} + ${output}= Curl From Pod ${pod_name} ${ns} ${url} ${resolve} + ... --cacert /data/certs/ca.crt --cert /data/certs/${cert_prefix}.crt --key /data/certs/${cert_prefix}.key + Should Contain ${output} 403 + +Wait Until Curl With Cert File Returns 403 + [Documentation] Retry curl with specific cert file until 403 response. + [Arguments] ${pod_name} ${ns} ${url} ${resolve} ${cert_prefix} + Wait Until Keyword Succeeds 120s 2s + ... Curl With Cert File Should Return 403 ${pod_name} ${ns} ${url} ${resolve} ${cert_prefix} + +Curl Without Cert Should Return SSL Error + [Documentation] Curl without a client cert and assert SSL handshake error (for mTLS Required). + [Arguments] ${pod_name} ${ns} ${url} ${resolve} + ${output}= Curl From Pod ${pod_name} ${ns} ${url} ${resolve} -skv + Should Contain ${output} SSL_read + Get Router Pod Name [Documentation] Get the name of the router-default pod. ${name}= Run With Kubeconfig @@ -246,6 +327,26 @@ Sign CSR With CA END Should Be Equal As Integers ${result.rc} 0 +Generate MTLS Client Cert + [Documentation] Generate a CA and a single client cert in the given directory. + [Arguments] ${tmpdir} ${edge_host} + Generate CA Certificate ${tmpdir}/ca.key ${tmpdir}/ca.crt /CN=MS-Test-Root-CA + Generate CSR And Key ${tmpdir}/usr.key ${tmpdir}/usr.csr /CN=example-test.com + VAR ${san}= subjectAltName = DNS.1:*.${BASE_DOMAIN},DNS.2:${edge_host} + Sign CSR With CA ${tmpdir}/usr.csr ${tmpdir}/ca.crt ${tmpdir}/ca.key ${tmpdir}/usr.crt ${san} + +Generate Client Cert File In Dir + [Documentation] Generate a CSR, key, and signed cert in the given directory using a name prefix. + [Arguments] ${tmpdir} ${host} ${cn} ${cert_prefix} + Generate CSR And Key ${tmpdir}/${cert_prefix}.key ${tmpdir}/${cert_prefix}.csr /CN=${cn} + VAR ${san}= subjectAltName = DNS.1:*.${BASE_DOMAIN},DNS.2:${host} + Sign CSR With CA + ... ${tmpdir}/${cert_prefix}.csr + ... ${tmpdir}/ca.crt + ... ${tmpdir}/ca.key + ... ${tmpdir}/${cert_prefix}.crt + ... ${san} + Get First LB IP [Documentation] Get the first load balancer IP of the router-default service. ${ip}= Oc Get JsonPath diff --git a/test/suites/router/router-config.robot b/test/suites/router/router-config.robot index 6e6b8c6e05..899a2708d1 100644 --- a/test/suites/router/router-config.robot +++ b/test/suites/router/router-config.robot @@ -22,7 +22,130 @@ Test Tags restart slow ${BASE_DOMAIN} apps.example.com ${ALT_HTTP_PORT} 10080 ${ALT_HTTPS_PORT} 10443 -${ROUTER_DROP_IN} 10-router + +${CONFIG_OLD_TLS} SEPARATOR=\n +... --- +... ingress: +... \ \ tlsSecurityProfile: +... \ \ \ \ old: {} +... \ \ \ \ type: Old + +${CONFIG_INTERMEDIATE_TLS} SEPARATOR=\n +... --- +... ingress: +... \ \ tlsSecurityProfile: +... \ \ \ \ intermediate: {} +... \ \ \ \ type: Intermediate + +${CONFIG_MODERN_TLS} SEPARATOR=\n +... --- +... ingress: +... \ \ tlsSecurityProfile: +... \ \ \ \ modern: {} +... \ \ \ \ type: Modern + +${CONFIG_CUSTOM_TLS} SEPARATOR=\n +... --- +... ingress: +... \ \ tlsSecurityProfile: +... \ \ \ \ custom: +... \ \ \ \ \ \ ciphers: +... \ \ \ \ \ \ - DHE-RSA-AES256-GCM-SHA384 +... \ \ \ \ \ \ - ECDHE-ECDSA-AES256-GCM-SHA384 +... \ \ \ \ \ \ minTLSVersion: VersionTLS12 +... \ \ \ \ type: Custom + +${CONFIG_WILDCARD_ALLOWED} SEPARATOR=\n +... --- +... ingress: +... \ \ routeAdmissionPolicy: +... \ \ \ \ wildcardPolicy: "WildcardsAllowed" + +${CONFIG_WILDCARD_DISALLOWED} SEPARATOR=\n +... --- +... ingress: +... \ \ routeAdmissionPolicy: +... \ \ \ \ wildcardPolicy: "WildcardsDisallowed" + +${CONFIG_TUNING_CUSTOM} SEPARATOR=\n +... --- +... ingress: +... \ \ forwardedHeaderPolicy: "Replace" +... \ \ httpCompression: +... \ \ \ \ mimeTypes: +... \ \ \ \ - "image" +... \ \ logEmptyRequests: "Ignore" +... \ \ tuningOptions: +... \ \ \ \ clientFinTimeout: "2s" +... \ \ \ \ clientTimeout: "60s" +... \ \ \ \ headerBufferBytes: 65536 +... \ \ \ \ headerBufferMaxRewriteBytes: 16384 +... \ \ \ \ healthCheckInterval: "10s" +... \ \ \ \ maxConnections: 100000 +... \ \ \ \ serverFinTimeout: "2s" +... \ \ \ \ serverTimeout: "60s" +... \ \ \ \ threadCount: 8 +... \ \ \ \ tlsInspectDelay: "10s" +... \ \ \ \ tunnelTimeout: "2h" + +${CONFIG_MTLS17_REQUIRED} SEPARATOR=\n +... --- +... ingress: +... \ \ clientTLS: +... \ \ \ \ clientCA: +... \ \ \ \ \ \ name: "ocp80517" +... \ \ \ \ clientCertificatePolicy: "Required" + +${CONFIG_MTLS17_OPTIONAL} SEPARATOR=\n +... --- +... ingress: +... \ \ clientTLS: +... \ \ \ \ clientCA: +... \ \ \ \ \ \ name: "ocp80517" +... \ \ \ \ clientCertificatePolicy: "Optional" + +${CONFIG_MTLS18_SUBJECT_FILTER} SEPARATOR=\n +... --- +... ingress: +... \ \ clientTLS: +... \ \ \ \ allowedSubjectPatterns: ["/CN=example-test.com"] +... \ \ \ \ clientCA: +... \ \ \ \ \ \ name: "ocp80518" +... \ \ \ \ clientCertificatePolicy: "Required" + +${CONFIG_COOKIE_EXACT_100} SEPARATOR=\n +... --- +... ingress: +... \ \ accessLogging: +... \ \ \ \ httpCaptureCookies: +... \ \ \ \ - matchType: Exact +... \ \ \ \ \ \ maxLength: 100 +... \ \ \ \ \ \ name: foo +... \ \ \ \ status: Enabled + +${CONFIG_COOKIE_EXACT_10} SEPARATOR=\n +... --- +... ingress: +... \ \ accessLogging: +... \ \ \ \ httpCaptureCookies: +... \ \ \ \ - matchType: Exact +... \ \ \ \ \ \ maxLength: 10 +... \ \ \ \ \ \ name: foo +... \ \ \ \ status: Enabled + +${CONFIG_LOG_FORMAT_1} SEPARATOR=\n +... --- +... ingress: +... \ \ accessLogging: +... \ \ \ \ httpLogFormat: "%{+Q}r" +... \ \ \ \ status: Enabled + +${CONFIG_LOG_FORMAT_2} SEPARATOR=\n +... --- +... ingress: +... \ \ accessLogging: +... \ \ \ \ httpLogFormat: "%ci:%cp %si:%sp %HU %ST" +... \ \ \ \ status: Enabled ${LOGGING_INVALID_MAXLENGTH_NEG1} SEPARATOR=\n ... --- @@ -105,37 +228,16 @@ Custom Listening IPs And Ports ... \ \ \ \ https: ${ALT_HTTPS_PORT} Setup Router Config And Restart ${config} - ${lb_ips}= Get LB IPs - Should Contain ${lb_ips} ${host_ip} - ${http_port}= Get LB Port http - Should Be Equal As Strings ${http_port} ${ALT_HTTP_PORT} - ${https_port}= Get LB Port https - Should Be Equal As Strings ${https_port} ${ALT_HTTPS_PORT} + Verify Custom LB Ports And IP ${host_ip} Deploy Web Server Signed Deploy Test Client Pod - VAR ${http_host}= service-unsecure-ocp73203.${BASE_DOMAIN} - VAR ${edge_host}= route-edge-ocp73203.${BASE_DOMAIN} - VAR ${pass_host}= route-passth-ocp73203.${BASE_DOMAIN} - VAR ${reen_host}= route-reen-ocp73203.${BASE_DOMAIN} - Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${http_host} - Create OC Route ${NAMESPACE} edge route-edge service-unsecure --hostname=${edge_host} - Create OC Route ${NAMESPACE} passthrough route-passth service-secure --hostname=${pass_host} - Create OC Route ${NAMESPACE} reencrypt route-reen service-secure --hostname=${reen_host} - Route Should Be Admitted route-reen - - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${http_host}:${ALT_HTTP_PORT} ${http_host}:${ALT_HTTP_PORT}:${host_ip} 200 - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${edge_host}:${ALT_HTTPS_PORT} ${edge_host}:${ALT_HTTPS_PORT}:${host_ip} 200 -k - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${pass_host}:${ALT_HTTPS_PORT} ${pass_host}:${ALT_HTTPS_PORT}:${host_ip} 200 -k - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${reen_host}:${ALT_HTTPS_PORT} ${reen_host}:${ALT_HTTPS_PORT}:${host_ip} 200 -k + VAR ${HTTP_HOST}= service-unsecure-ocp73203.${BASE_DOMAIN} scope=TEST + VAR ${EDGE_HOST}= route-edge-ocp73203.${BASE_DOMAIN} scope=TEST + VAR ${PASS_HOST}= route-passth-ocp73203.${BASE_DOMAIN} scope=TEST + VAR ${REEN_HOST}= route-reen-ocp73203.${BASE_DOMAIN} scope=TEST + Create And Admit Four Route Types ${HTTP_HOST} ${EDGE_HOST} ${PASS_HOST} ${REEN_HOST} + Curl Four Routes Via Custom Ports ${host_ip} [Teardown] Remove Router Config And Restart Enable Disable Router @@ -174,68 +276,11 @@ Tuning Options Customization VAR ${http_host}= service-unsecure-ocp77349.${BASE_DOMAIN} Deploy Web Server Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${http_host} - - Router Pod Env Should Have Value ROUTER_BUF_SIZE 32768 - Router Pod Env Should Have Value ROUTER_MAX_REWRITE_SIZE 8192 - Router Pod Env Should Have Value ROUTER_DEFAULT_CLIENT_TIMEOUT 30s - Router Pod Env Should Have Value ROUTER_CLIENT_FIN_TIMEOUT 1s - Router Pod Env Should Have Value ROUTER_DEFAULT_SERVER_TIMEOUT 30s - Router Pod Env Should Have Value ROUTER_DEFAULT_SERVER_FIN_TIMEOUT 1s - Router Pod Env Should Have Value ROUTER_DEFAULT_TUNNEL_TIMEOUT 1h - Router Pod Env Should Have Value ROUTER_INSPECT_DELAY 5s - Router Pod Env Should Have Value ROUTER_THREADS 4 - Router Pod Env Should Have Value ROUTER_MAX_CONNECTIONS 50000 - - ${haproxy}= Read Haproxy Config - Should Contain ${haproxy} tune.bufsize 32768 - Should Contain ${haproxy} tune.maxrewrite 8192 - Should Contain ${haproxy} timeout client 30s - Should Contain ${haproxy} timeout server 30s - Should Contain ${haproxy} timeout tunnel 1h - Should Contain ${haproxy} nbthread 4 - Should Contain ${haproxy} maxconn 50000 - - ${config}= Catenate SEPARATOR=\n - ... --- - ... ingress: - ... \ \ forwardedHeaderPolicy: "Replace" - ... \ \ httpCompression: - ... \ \ \ \ mimeTypes: - ... \ \ \ \ - "image" - ... \ \ logEmptyRequests: "Ignore" - ... \ \ tuningOptions: - ... \ \ \ \ clientFinTimeout: "2s" - ... \ \ \ \ clientTimeout: "60s" - ... \ \ \ \ headerBufferBytes: 65536 - ... \ \ \ \ headerBufferMaxRewriteBytes: 16384 - ... \ \ \ \ healthCheckInterval: "10s" - ... \ \ \ \ maxConnections: 100000 - ... \ \ \ \ serverFinTimeout: "2s" - ... \ \ \ \ serverTimeout: "60s" - ... \ \ \ \ threadCount: 8 - ... \ \ \ \ tlsInspectDelay: "10s" - ... \ \ \ \ tunnelTimeout: "2h" - Setup Router Config And Restart ${config} - - Router Pod Env Should Have Value ROUTER_BUF_SIZE 65536 - Router Pod Env Should Have Value ROUTER_MAX_REWRITE_SIZE 16384 - Router Pod Env Should Have Value ROUTER_DEFAULT_CLIENT_TIMEOUT 60s - Router Pod Env Should Have Value ROUTER_CLIENT_FIN_TIMEOUT 2s - Router Pod Env Should Have Value ROUTER_DEFAULT_SERVER_TIMEOUT 60s - Router Pod Env Should Have Value ROUTER_DEFAULT_SERVER_FIN_TIMEOUT 2s - Router Pod Env Should Have Value ROUTER_DEFAULT_TUNNEL_TIMEOUT 2h - Router Pod Env Should Have Value ROUTER_INSPECT_DELAY 10s - Router Pod Env Should Have Value ROUTER_THREADS 8 - Router Pod Env Should Have Value ROUTER_MAX_CONNECTIONS 100000 - - ${haproxy}= Read Haproxy Config - Should Contain ${haproxy} tune.bufsize 65536 - Should Contain ${haproxy} tune.maxrewrite 16384 - Should Contain ${haproxy} timeout client 60s - Should Contain ${haproxy} timeout server 60s - Should Contain ${haproxy} timeout tunnel 2h - Should Contain ${haproxy} nbthread 8 - Should Contain ${haproxy} maxconn 100000 + Verify Default Router Tuning Env Vars + Verify Default Router Tuning Haproxy + Setup Router Config And Restart ${CONFIG_TUNING_CUSTOM} + Verify Custom Router Tuning Env Vars + Verify Custom Router Tuning Haproxy [Teardown] Remove Router Config And Restart Custom Default Certificate @@ -252,30 +297,15 @@ Custom Default Certificate Create OC Route ${NAMESPACE} edge route-edge service-unsecure --hostname=${CERT_EDGE_HOST} Route Should Be Admitted route-edge - - ${vol}= Oc Get JsonPath - ... deployment ${ROUTER_NS} router-default - ... ..volumes[?(@.name=="default-certificate")].secret.secretName - Should Contain ${vol} router-test-cert - - ${router_pod}= Get Router Pod Name - ${cert_info}= Run With Kubeconfig - ... oc exec -n ${ROUTER_NS} ${router_pod} -- openssl x509 -noout -in /etc/pki/tls/private/tls.crt -text - Should Contain ${cert_info} CN = MS-default-CA - - Deploy Web Server + Verify Custom Cert Is Active Deploy Test Client Pod Copy Files To Pod ${NAMESPACE} ${CLIENT_POD_NAME} ${CERT_TMPDIR} /data/certs ${router_ip}= Get Router Pod IP VAR ${resolve}= ${CERT_EDGE_HOST}:443:${router_ip} - - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${CERT_EDGE_HOST} ${resolve} 200 - ... --cacert /data/certs/ca.crt --cert /data/certs/usr.crt --key /data/certs/usr.key - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${CERT_EDGE_HOST} ${resolve} 200 -k + Wait Until Curl With Client Cert Succeeds + ... ${CLIENT_POD_NAME} ${NAMESPACE} https://${CERT_EDGE_HOST} ${resolve} + Wait Until HTTPS Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} https://${CERT_EDGE_HOST} ${resolve} [Teardown] Run Keywords ... Remove Router Config And Restart ... AND Run With Kubeconfig oc delete secret router-test-cert -n ${ROUTER_NS} --ignore-not-found @@ -287,36 +317,19 @@ Old And Intermediate TLS Profiles Router Pod Env Should Have Value SSL_MIN_VERSION TLSv1.2 ${ciphers}= Oc Get JsonPath - ... pod ${ROUTER_NS} ${EMPTY} - ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_CIPHERSUITES")].value + ... pod ${ROUTER_NS} ${EMPTY} .items[*].spec.containers[*].env[?(@.name=="ROUTER_CIPHERSUITES")].value Should Contain ${ciphers} TLS_AES_128_GCM_SHA256 - ${config_old}= Catenate SEPARATOR=\n - ... --- - ... ingress: - ... \ \ tlsSecurityProfile: - ... \ \ \ \ old: {} - ... \ \ \ \ type: Old - Setup Router Config And Restart ${config_old} - + Setup Router Config And Restart ${CONFIG_OLD_TLS} Router Pod Env Should Have Value SSL_MIN_VERSION TLSv1.1 ${ciphers}= Oc Get JsonPath - ... pod ${ROUTER_NS} ${EMPTY} - ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_CIPHERS")].value + ... pod ${ROUTER_NS} ${EMPTY} .items[*].spec.containers[*].env[?(@.name=="ROUTER_CIPHERS")].value Should Contain ${ciphers} DES-CBC3-SHA - ${config_intermediate}= Catenate SEPARATOR=\n - ... --- - ... ingress: - ... \ \ tlsSecurityProfile: - ... \ \ \ \ intermediate: {} - ... \ \ \ \ type: Intermediate - Setup Router Config And Restart ${config_intermediate} - + Setup Router Config And Restart ${CONFIG_INTERMEDIATE_TLS} Router Pod Env Should Have Value SSL_MIN_VERSION TLSv1.2 ${ciphers}= Oc Get JsonPath - ... pod ${ROUTER_NS} ${EMPTY} - ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_CIPHERSUITES")].value + ... pod ${ROUTER_NS} ${EMPTY} .items[*].spec.containers[*].env[?(@.name=="ROUTER_CIPHERSUITES")].value Should Contain ${ciphers} TLS_AES_128_GCM_SHA256 [Teardown] Remove Router Config And Restart @@ -325,38 +338,18 @@ Modern And Custom TLS Profiles ... then apply a Custom profile with specific ciphers. ... OCP-80514 - ${config_modern}= Catenate SEPARATOR=\n - ... --- - ... ingress: - ... \ \ tlsSecurityProfile: - ... \ \ \ \ modern: {} - ... \ \ \ \ type: Modern - Setup Router Config And Restart ${config_modern} - + Setup Router Config And Restart ${CONFIG_MODERN_TLS} Router Pod Env Should Have Value SSL_MIN_VERSION TLSv1.3 ${ciphers}= Oc Get JsonPath - ... pod ${ROUTER_NS} ${EMPTY} - ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_CIPHERSUITES")].value + ... pod ${ROUTER_NS} ${EMPTY} .items[*].spec.containers[*].env[?(@.name=="ROUTER_CIPHERSUITES")].value Should Contain ${ciphers} TLS_AES_128_GCM_SHA256 ${haproxy}= Read Haproxy Config Should Contain ${haproxy} ssl-default-bind-options ssl-min-ver TLSv1.3 - ${config_custom}= Catenate SEPARATOR=\n - ... --- - ... ingress: - ... \ \ tlsSecurityProfile: - ... \ \ \ \ custom: - ... \ \ \ \ \ \ ciphers: - ... \ \ \ \ \ \ - DHE-RSA-AES256-GCM-SHA384 - ... \ \ \ \ \ \ - ECDHE-ECDSA-AES256-GCM-SHA384 - ... \ \ \ \ \ \ minTLSVersion: VersionTLS12 - ... \ \ \ \ type: Custom - Setup Router Config And Restart ${config_custom} - + Setup Router Config And Restart ${CONFIG_CUSTOM_TLS} Router Pod Env Should Have Value SSL_MIN_VERSION TLSv1.2 ${ciphers}= Oc Get JsonPath - ... pod ${ROUTER_NS} ${EMPTY} - ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_CIPHERS")].value + ... pod ${ROUTER_NS} ${EMPTY} .items[*].spec.containers[*].env[?(@.name=="ROUTER_CIPHERS")].value Should Contain ${ciphers} DHE-RSA-AES256-GCM-SHA384 [Teardown] Remove Router Config And Restart @@ -366,64 +359,38 @@ MTLS Optional And Required Policy ... OCP-80517 [Setup] Prepare MTLS Cert For Test 80517 route-edge80517.${BASE_DOMAIN} - Run With Kubeconfig oc create configmap ocp80517 --from-file=ca-bundle.pem=${MTLS_CA_CRT} -n ${ROUTER_NS} - - ${env}= Oc Get JsonPath - ... pod ${ROUTER_NS} ${EMPTY} - ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_MUTUAL_TLS_AUTH")].value - Should Be Empty ${env} - - ${config_required}= Catenate SEPARATOR=\n - ... --- - ... ingress: - ... \ \ clientTLS: - ... \ \ \ \ clientCA: - ... \ \ \ \ \ \ name: "ocp80517" - ... \ \ \ \ clientCertificatePolicy: "Required" - Setup Router Config And Restart ${config_required} + Run With Kubeconfig oc create configmap ocp80517 --from-file=ca-bundle.pem=${MTLS_TMPDIR}/ca.crt -n ${ROUTER_NS} + Setup Router Config And Restart ${CONFIG_MTLS17_REQUIRED} Router Pod Env Should Have Value ROUTER_MUTUAL_TLS_AUTH required - - Deploy Web Server - Deploy Test Client Pod - Copy Files To Pod ${NAMESPACE} ${CLIENT_POD_NAME} ${MTLS_TMPDIR} /data/certs - Create OC Route ${NAMESPACE} edge route-edge - ... service-unsecure - ... --hostname=${MTLS_EDGE_HOST} - ... --cert=${MTLS_USR_CRT} - ... --key=${MTLS_USR_KEY} - Route Should Be Admitted route-edge - + Deploy MTLS Test Workloads ${router_ip}= Get Router Pod IP VAR ${resolve}= ${MTLS_EDGE_HOST}:443:${router_ip} - - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} https://${MTLS_EDGE_HOST} ${resolve} 200 OK - ... --cacert /data/certs/ca.crt --cert /data/certs/usr.crt --key /data/certs/usr.key - - ${output}= Curl From Pod ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${MTLS_EDGE_HOST} ${resolve} -skv - Should Contain ${output} SSL_read - - ${config_optional}= Catenate SEPARATOR=\n - ... --- - ... ingress: - ... \ \ clientTLS: - ... \ \ \ \ clientCA: - ... \ \ \ \ \ \ name: "ocp80517" - ... \ \ \ \ clientCertificatePolicy: "Optional" - Setup Router Config And Restart ${config_optional} - + Wait Until Curl With Client Cert Succeeds + ... ${CLIENT_POD_NAME} + ... ${NAMESPACE} + ... https://${MTLS_EDGE_HOST} + ... ${resolve} + Curl Without Cert Should Return SSL Error + ... ${CLIENT_POD_NAME} + ... ${NAMESPACE} + ... https://${MTLS_EDGE_HOST} + ... ${resolve} + + Setup Router Config And Restart ${CONFIG_MTLS17_OPTIONAL} Router Pod Env Should Have Value ROUTER_MUTUAL_TLS_AUTH optional - ${router_ip}= Get Router Pod IP VAR ${resolve}= ${MTLS_EDGE_HOST}:443:${router_ip} - - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} https://${MTLS_EDGE_HOST} ${resolve} 200 OK - ... --cacert /data/certs/ca.crt --cert /data/certs/usr.crt --key /data/certs/usr.key - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} https://${MTLS_EDGE_HOST} ${resolve} 200 OK -k + Wait Until Curl With Client Cert Succeeds + ... ${CLIENT_POD_NAME} + ... ${NAMESPACE} + ... https://${MTLS_EDGE_HOST} + ... ${resolve} + Wait Until HTTPS Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} + ... ${NAMESPACE} + ... https://${MTLS_EDGE_HOST} + ... ${resolve} [Teardown] Run Keywords ... Remove Router Config And Restart ... AND Run With Kubeconfig oc delete configmap ocp80517 -n ${ROUTER_NS} --ignore-not-found @@ -434,46 +401,32 @@ MTLS Subject Filter ... OCP-80518 [Setup] Prepare Two MTLS Certs For Test 80518 route-edge80518.${BASE_DOMAIN} route2-edge80518.${BASE_DOMAIN} - Run With Kubeconfig oc create configmap ocp80518 --from-file=ca-bundle.pem=${MTLS2_CA_CRT} -n ${ROUTER_NS} - - ${config}= Catenate SEPARATOR=\n - ... --- - ... ingress: - ... \ \ clientTLS: - ... \ \ \ \ allowedSubjectPatterns: ["/CN=example-test.com"] - ... \ \ \ \ clientCA: - ... \ \ \ \ \ \ name: "ocp80518" - ... \ \ \ \ clientCertificatePolicy: "Required" - Setup Router Config And Restart ${config} + Run With Kubeconfig + ... oc create configmap ocp80518 --from-file=ca-bundle.pem=${MTLS2_TMPDIR}/ca.crt -n ${ROUTER_NS} + Setup Router Config And Restart ${CONFIG_MTLS18_SUBJECT_FILTER} ${env}= Oc Get JsonPath - ... pod ${ROUTER_NS} ${EMPTY} + ... pod + ... ${ROUTER_NS} + ... ${EMPTY} ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_MUTUAL_TLS_AUTH_FILTER")].value Should Contain ${env} example-test.com Deploy Web Server Deploy Test Client Pod Copy Files To Pod ${NAMESPACE} ${CLIENT_POD_NAME} ${MTLS2_TMPDIR} /data/certs - Create OC Route ${NAMESPACE} edge route-edge - ... service-unsecure --hostname=${MTLS2_HOST1} - ... --cert=${MTLS2_USR_CRT1} --key=${MTLS2_USR_KEY1} - Create OC Route ${NAMESPACE} edge route-edge2 - ... service-unsecure --hostname=${MTLS2_HOST2} - ... --cert=${MTLS2_USR_CRT2} --key=${MTLS2_USR_KEY2} + Create OC Route ${NAMESPACE} edge route-edge service-unsecure + ... --hostname=${MTLS2_HOST1} --cert=${MTLS2_TMPDIR}/usr1.crt --key=${MTLS2_TMPDIR}/usr1.key + Create OC Route ${NAMESPACE} edge route-edge2 service-unsecure + ... --hostname=${MTLS2_HOST2} --cert=${MTLS2_TMPDIR}/usr2.crt --key=${MTLS2_TMPDIR}/usr2.key Route Should Be Admitted route-edge Route Should Be Admitted route-edge2 ${router_ip}= Get Router Pod IP - - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${MTLS2_HOST1} ${MTLS2_HOST1}:443:${router_ip} 200 OK - ... --cacert /data/certs/ca.crt --cert /data/certs/usr1.crt --key /data/certs/usr1.key - - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${MTLS2_HOST2} ${MTLS2_HOST2}:443:${router_ip} 403 - ... --cacert /data/certs/ca.crt --cert /data/certs/usr2.crt --key /data/certs/usr2.key + Wait Until Curl With Cert File Succeeds + ... ${CLIENT_POD_NAME} ${NAMESPACE} https://${MTLS2_HOST1} ${MTLS2_HOST1}:443:${router_ip} usr1 + Wait Until Curl With Cert File Returns 403 + ... ${CLIENT_POD_NAME} ${NAMESPACE} https://${MTLS2_HOST2} ${MTLS2_HOST2}:443:${router_ip} usr2 [Teardown] Run Keywords ... Remove Router Config And Restart ... AND Run With Kubeconfig oc delete configmap ocp80518 -n ${ROUTER_NS} --ignore-not-found @@ -490,39 +443,25 @@ Wildcard Route Admission Policy VAR ${any_host}= any.${BASE_DOMAIN} ${env}= Oc Get JsonPath - ... pod ${ROUTER_NS} ${EMPTY} + ... pod + ... ${ROUTER_NS} + ... ${EMPTY} ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_ALLOW_WILDCARD_ROUTES")].value Should Be Equal As Strings ${env} false - Create OC Route ${NAMESPACE} http unsecure80520 service-unsecure ... --hostname=${wildcard_host} --wildcard-policy=Subdomain Route Should Not Be Admitted unsecure80520 - ${config_allowed}= Catenate SEPARATOR=\n - ... --- - ... ingress: - ... \ \ routeAdmissionPolicy: - ... \ \ \ \ wildcardPolicy: "WildcardsAllowed" - Setup Router Config And Restart ${config_allowed} - + Setup Router Config And Restart ${CONFIG_WILDCARD_ALLOWED} Router Pod Env Should Have Value ROUTER_ALLOW_WILDCARD_ROUTES true Route Should Be Admitted unsecure80520 - ${router_ip}= Get Router Pod IP Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${wildcard_host} ${wildcard_host}:80:${router_ip} 200 + ... ${CLIENT_POD_NAME} ${NAMESPACE} http://${wildcard_host} ${wildcard_host}:80:${router_ip} Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${any_host} ${any_host}:80:${router_ip} 200 - - ${config_disallowed}= Catenate SEPARATOR=\n - ... --- - ... ingress: - ... \ \ routeAdmissionPolicy: - ... \ \ \ \ wildcardPolicy: "WildcardsDisallowed" - Setup Router Config And Restart ${config_disallowed} + ... ${CLIENT_POD_NAME} ${NAMESPACE} http://${any_host} ${any_host}:80:${router_ip} + Setup Router Config And Restart ${CONFIG_WILDCARD_DISALLOWED} Router Pod Env Should Have Value ROUTER_ALLOW_WILDCARD_ROUTES false Route Should Not Be Admitted unsecure80520 [Teardown] Remove Router Config And Restart @@ -554,31 +493,8 @@ HTTP Capture Cookies Prefix Match Route Should Be Admitted route-edge Create OC Route ${NAMESPACE} reencrypt route-reen service-secure --hostname=${reen_host} Route Should Be Admitted route-reen - ${router_ip}= Get Router Pod IP - - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${routehost}/index.html ${routehost}:80:${router_ip} 200 -b fo=nobar - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${routehost}/index.html ${routehost}:80:${router_ip} 200 -b foo=bar - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${routehost}/index.html ${routehost}:80:${router_ip} 200 -b foo22=bar22 - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${edge_host}/index.html ${edge_host}:443:${router_ip} 200 -b foo=barforedge -k - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${reen_host}/index.html ${reen_host}:443:${router_ip} 200 -b foo=barforreen -k - - Wait For Router Logs To Contain foo=bar - Wait For Router Logs To Contain foo22=bar22 - Wait For Router Logs To Contain foo=barforedge - Wait For Router Logs To Contain foo=barforreen - ${logs}= Get Router Access Logs - Should Not Contain ${logs} fo=nobar + Curl All Cookie Routes And Verify Logs ${routehost} ${edge_host} ${reen_host} ${router_ip} [Teardown] Remove Router Config And Restart HTTP Capture Cookies Exact Match And MaxLength @@ -586,54 +502,38 @@ HTTP Capture Cookies Exact Match And MaxLength ... and maxLength truncates cookie values in logs. ... OCP-81997 - ${config}= Catenate SEPARATOR=\n - ... --- - ... ingress: - ... \ \ accessLogging: - ... \ \ \ \ httpCaptureCookies: - ... \ \ \ \ - matchType: Exact - ... \ \ \ \ \ \ maxLength: 100 - ... \ \ \ \ \ \ name: foo - ... \ \ \ \ status: Enabled - Setup Router Config And Restart ${config} - + Setup Router Config And Restart ${CONFIG_COOKIE_EXACT_100} Deploy Web Server Deploy Test Client Pod VAR ${routehost}= route-unsec81997.${BASE_DOMAIN} Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${routehost} Route Should Be Admitted route-http - ${router_ip}= Get Router Pod IP - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${routehost}/index.html ${routehost}:80:${router_ip} 200 -b fooor=nobar - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${routehost}/index.html ${routehost}:80:${router_ip} 200 -b foo=bar - + Wait Until Curl With Cookie Succeeds From Pod + ... ${CLIENT_POD_NAME} + ... ${NAMESPACE} + ... http://${routehost}/index.html + ... ${routehost}:80:${router_ip} + ... fooor=nobar + Wait Until Curl With Cookie Succeeds From Pod + ... ${CLIENT_POD_NAME} + ... ${NAMESPACE} + ... http://${routehost}/index.html + ... ${routehost}:80:${router_ip} + ... foo=bar Wait For Router Logs To Contain foo=bar - ${logs}= Get Router Access Logs - Should Not Contain ${logs} fooor=nobar + Router Logs Should Not Contain fooor=nobar - ${config2}= Catenate SEPARATOR=\n - ... --- - ... ingress: - ... \ \ accessLogging: - ... \ \ \ \ httpCaptureCookies: - ... \ \ \ \ - matchType: Exact - ... \ \ \ \ \ \ maxLength: 10 - ... \ \ \ \ \ \ name: foo - ... \ \ \ \ status: Enabled - Setup Router Config And Restart ${config2} + Setup Router Config And Restart ${CONFIG_COOKIE_EXACT_10} ${router_ip}= Get Router Pod IP - - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${routehost}/index.html ${routehost}:80:${router_ip} 200 -b foo=bar89abdef - + Wait Until Curl With Cookie Succeeds From Pod + ... ${CLIENT_POD_NAME} + ... ${NAMESPACE} + ... http://${routehost}/index.html + ... ${routehost}:80:${router_ip} + ... foo=bar89abdef Wait For Router Logs To Contain foo=bar89a - ${logs}= Get Router Access Logs - Should Not Contain ${logs} foo=bar89ab + Router Logs Should Not Contain foo=bar89ab [Teardown] Remove Router Config And Restart HTTP Capture Headers Request And Response @@ -666,27 +566,7 @@ HTTP Capture Headers Request And Response Route Should Be Admitted route-edge Create OC Route ${NAMESPACE} reencrypt route-reen service-secure --hostname=${reen_host} Route Should Be Admitted route-reen - - ${router_pod}= Get Router Pod Name - ${haproxy}= Run With Kubeconfig - ... oc exec -n ${ROUTER_NS} ${router_pod} -- grep -A 20 "frontend fe_sni" haproxy.config - Should Contain ${haproxy} capture request header Host len 120 - Should Contain ${haproxy} capture response header Server len 120 - - ${router_ip}= Get Router Pod IP - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${routehost}/index.html ${routehost}:80:${router_ip} 200 - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${edge_host}/index.html ${edge_host}:443:${router_ip} 200 -k - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${reen_host}/index.html ${reen_host}:443:${router_ip} 200 -k - - Wait For Router Logs To Contain ${routehost} - Wait For Router Logs To Contain ${edge_host} - Wait For Router Logs To Contain ${reen_host} + Verify Header Capture Config And Logs ${routehost} ${edge_host} ${reen_host} [Teardown] Remove Router Config And Restart HTTP Capture Headers MaxLength Adherence @@ -694,7 +574,6 @@ HTTP Capture Headers MaxLength Adherence ... OCP-82003 VAR ${routehost}= route-unsec82003.${BASE_DOMAIN} - ${config}= Catenate SEPARATOR=\n ... --- ... ingress: @@ -713,12 +592,9 @@ HTTP Capture Headers MaxLength Adherence Deploy Test Client Pod Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${routehost} Route Should Be Admitted route-http - ${router_ip}= Get Router Pod IP Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${routehost}/index.html ${routehost}:80:${router_ip} 200 - + ... ${CLIENT_POD_NAME} ${NAMESPACE} http://${routehost}/index.html ${routehost}:80:${router_ip} # route-unsec82003.apps.e is 16 chars, so the full hostname should not appear Wait For Router Logs To Contain route-unsec82003.ap ${logs}= Get Router Access Logs @@ -734,9 +610,7 @@ Custom HTTP Error Pages ... OCP-82004 Create Configmap From Files ${ROUTER_NS} custom-82004-error-code-pages - ... --from-file=./assets/router/error-page-503.http - ... --from-file=./assets/router/error-page-404.http - + ... --from-file=./assets/router/error-page-503.http --from-file=./assets/router/error-page-404.http ${config}= Catenate SEPARATOR=\n ... --- ... ingress: @@ -750,24 +624,7 @@ Custom HTTP Error Pages VAR ${noexist_host}= not-exist82004.${BASE_DOMAIN} Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${routehost} Route Should Be Admitted route-http - - ${router_pod}= Get Router Pod Name - ${error503}= Run With Kubeconfig - ... oc exec -n ${ROUTER_NS} ${router_pod} -- cat /var/lib/haproxy/errorfiles/error-page-503.http - Should Contain ${error503} Custom:Application Unavailable - ${error404}= Run With Kubeconfig - ... oc exec -n ${ROUTER_NS} ${router_pod} -- cat /var/lib/haproxy/errorfiles/error-page-404.http - Should Contain ${error404} Custom:Not Found - - ${router_ip}= Get Router Pod IP - ${output}= Run With Kubeconfig - ... oc exec -n ${NAMESPACE} ${CLIENT_POD_NAME} -- curl http://${noexist_host} -s --resolve ${noexist_host}:80:${router_ip} --connect-timeout 10 - Should Contain ${output} Custom:Not Found - - Scale Deployment ${NAMESPACE} web-server-deploy 0 - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${routehost} ${routehost}:80:${router_ip} Custom:Application Unavailable + Verify Custom Error Pages ${routehost} ${noexist_host} [Teardown] Run Keywords ... Remove Router Config And Restart ... AND Run With Kubeconfig oc delete configmap custom-82004-error-code-pages -n ${ROUTER_NS} --ignore-not-found @@ -777,42 +634,29 @@ HTTP Log Format ... output with the correct format. ... OCP-82014 - ${config}= Catenate SEPARATOR=\n - ... --- - ... ingress: - ... \ \ accessLogging: - ... \ \ \ \ httpLogFormat: "%{+Q}r" - ... \ \ \ \ status: Enabled - Setup Router Config And Restart ${config} - + Setup Router Config And Restart ${CONFIG_LOG_FORMAT_1} Deploy Web Server Deploy Test Client Pod VAR ${routehost}= route-unsec82014.${BASE_DOMAIN} Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${routehost} Route Should Be Admitted route-http - ${router_ip}= Get Router Pod IP Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${routehost}/path/second/index.html ${routehost}:80:${router_ip} 200 - + ... ${CLIENT_POD_NAME} + ... ${NAMESPACE} + ... http://${routehost}/path/second/index.html + ... ${routehost}:80:${router_ip} Wait For Router Logs To Contain /path/second/index.html ${logs}= Get Router Access Logs Should Match Regexp ${logs} haproxy\\[[0-9]+\\]: "HEAD /path/second/index.html HTTP - ${config2}= Catenate SEPARATOR=\n - ... --- - ... ingress: - ... \ \ accessLogging: - ... \ \ \ \ httpLogFormat: "%ci:%cp %si:%sp %HU %ST" - ... \ \ \ \ status: Enabled - Setup Router Config And Restart ${config2} + Setup Router Config And Restart ${CONFIG_LOG_FORMAT_2} ${router_ip}= Get Router Pod IP - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${routehost}/path/second/index.html ${routehost}:80:${router_ip} 200 - + ... ${CLIENT_POD_NAME} + ... ${NAMESPACE} + ... http://${routehost}/path/second/index.html + ... ${routehost}:80:${router_ip} Wait For Router Logs To Contain /path/second/index.html ${logs}= Get Router Access Logs Should Match Regexp ${logs} @@ -829,50 +673,7 @@ Syslog Logging Destination Deploy Web Server Deploy Test Client Pod ${syslog_ip}= Oc Get JsonPath pod ${NAMESPACE} rsyslogd-pod .status.podIP - - ${config}= Catenate SEPARATOR=\n - ... --- - ... ingress: - ... \ \ accessLogging: - ... \ \ \ \ destination: - ... \ \ \ \ \ \ syslog: - ... \ \ \ \ \ \ \ \ address: ${syslog_ip} - ... \ \ \ \ \ \ \ \ port: 514 - ... \ \ \ \ \ \ type: Syslog - ... \ \ \ \ status: Enabled - Setup Router Config And Restart ${config} - - VAR ${routehost}= route-unsec82015.${BASE_DOMAIN} - Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${routehost} - Route Should Be Admitted route-http - - ${router_pod}= Get Router Pod Name - ${haproxy}= Read Haproxy Config - Should Contain ${haproxy} log ${syslog_ip}:514 len 1024 local1 info - - ${router_ip}= Get Router Pod IP - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${routehost}/path/second/index.html ${routehost}:80:${router_ip} 200 - - Wait Until Keyword Succeeds 60s 3s - ... Syslog Pod Should Contain /path/second/index.html - - ${config2}= Catenate SEPARATOR=\n - ... --- - ... ingress: - ... \ \ accessLogging: - ... \ \ \ \ destination: - ... \ \ \ \ \ \ syslog: - ... \ \ \ \ \ \ \ \ address: ${syslog_ip} - ... \ \ \ \ \ \ \ \ port: 514 - ... \ \ \ \ \ \ \ \ facility: local2 - ... \ \ \ \ \ \ type: Syslog - ... \ \ \ \ status: Enabled - Setup Router Config And Restart ${config2} - - ${haproxy}= Read Haproxy Config - Should Contain ${haproxy} log ${syslog_ip}:514 len 1024 local2 info + Verify Syslog Logging ${syslog_ip} [Teardown] Remove Router Config And Restart Negative Logging Config Validation @@ -880,16 +681,11 @@ Negative Logging Config Validation ... and that setting httpCaptureCookies without status: Enabled does not activate logging. ... OCP-84260 - Show Invalid Drop In Config Should Fail With - ... ${LOGGING_INVALID_MAXLENGTH_NEG1} Must be between 1 and 1024 - Show Invalid Drop In Config Should Fail With - ... ${LOGGING_INVALID_MAXLENGTH_ZERO} Must be between 1 and 1024 - Show Invalid Drop In Config Should Fail With - ... ${LOGGING_INVALID_COOKIE_NAME} contains invalid characters - Show Invalid Drop In Config Should Fail With - ... ${LOGGING_INVALID_HEADER_MAXLENGTH} maxLength must be at least 1 - Show Invalid Drop In Config Should Fail With - ... ${LOGGING_INVALID_STATUS} invalid access logging status: Enable + Show Invalid Drop In Config Should Fail With ${LOGGING_INVALID_MAXLENGTH_NEG1} Must be between 1 and 1024 + Show Invalid Drop In Config Should Fail With ${LOGGING_INVALID_MAXLENGTH_ZERO} Must be between 1 and 1024 + Show Invalid Drop In Config Should Fail With ${LOGGING_INVALID_COOKIE_NAME} contains invalid characters + Show Invalid Drop In Config Should Fail With ${LOGGING_INVALID_HEADER_MAXLENGTH} maxLength must be at least 1 + Show Invalid Drop In Config Should Fail With ${LOGGING_INVALID_STATUS} invalid access logging status: Enable ${gen_before}= Get Router Deployment Generation Drop In MicroShift Config ${LOGGING_COOKIES_NO_STATUS} 10-router @@ -897,14 +693,86 @@ Negative Logging Config Validation Wait For Router Ready ${gen_after}= Get Router Deployment Generation Should Be Equal As Strings ${gen_before} ${gen_after} - ${haproxy}= Read Haproxy Config Should Not Contain ${haproxy} capture cookie foo len 100 - [Teardown] Remove Router Config And Restart *** Keywords *** +Verify Custom LB Ports And IP + [Documentation] Check the router-default LB has the expected IP and custom port numbers. + [Arguments] ${host_ip} + ${lb_ips}= Get LB IPs + Should Contain ${lb_ips} ${host_ip} + ${http_port}= Get LB Port http + Should Be Equal As Strings ${http_port} ${ALT_HTTP_PORT} + ${https_port}= Get LB Port https + Should Be Equal As Strings ${https_port} ${ALT_HTTPS_PORT} + +Curl Four Routes Via Custom Ports + [Documentation] Curl all four route types through the custom ports. + [Arguments] ${host_ip} + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${HTTP_HOST}:${ALT_HTTP_PORT} ${HTTP_HOST}:${ALT_HTTP_PORT}:${host_ip} + Wait Until HTTPS Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${EDGE_HOST}:${ALT_HTTPS_PORT} ${EDGE_HOST}:${ALT_HTTPS_PORT}:${host_ip} + Wait Until HTTPS Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${PASS_HOST}:${ALT_HTTPS_PORT} ${PASS_HOST}:${ALT_HTTPS_PORT}:${host_ip} + Wait Until HTTPS Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... https://${REEN_HOST}:${ALT_HTTPS_PORT} ${REEN_HOST}:${ALT_HTTPS_PORT}:${host_ip} + +Verify Default Router Tuning Env Vars + [Documentation] Verify the default router tuning environment variable values. + Router Pod Env Should Have Value ROUTER_BUF_SIZE 32768 + Router Pod Env Should Have Value ROUTER_MAX_REWRITE_SIZE 8192 + Router Pod Env Should Have Value ROUTER_DEFAULT_CLIENT_TIMEOUT 30s + Router Pod Env Should Have Value ROUTER_CLIENT_FIN_TIMEOUT 1s + Router Pod Env Should Have Value ROUTER_DEFAULT_SERVER_TIMEOUT 30s + Router Pod Env Should Have Value ROUTER_DEFAULT_SERVER_FIN_TIMEOUT 1s + Router Pod Env Should Have Value ROUTER_DEFAULT_TUNNEL_TIMEOUT 1h + Router Pod Env Should Have Value ROUTER_INSPECT_DELAY 5s + Router Pod Env Should Have Value ROUTER_THREADS 4 + Router Pod Env Should Have Value ROUTER_MAX_CONNECTIONS 50000 + +Verify Default Router Tuning Haproxy + [Documentation] Verify the default tuning values are present in haproxy.config. + ${haproxy}= Read Haproxy Config + Should Contain ${haproxy} tune.bufsize 32768 + Should Contain ${haproxy} tune.maxrewrite 8192 + Should Contain ${haproxy} timeout client 30s + Should Contain ${haproxy} timeout server 30s + Should Contain ${haproxy} timeout tunnel 1h + Should Contain ${haproxy} nbthread 4 + Should Contain ${haproxy} maxconn 50000 + +Verify Custom Router Tuning Env Vars + [Documentation] Verify the custom tuning environment variable values after config change. + Router Pod Env Should Have Value ROUTER_BUF_SIZE 65536 + Router Pod Env Should Have Value ROUTER_MAX_REWRITE_SIZE 16384 + Router Pod Env Should Have Value ROUTER_DEFAULT_CLIENT_TIMEOUT 60s + Router Pod Env Should Have Value ROUTER_CLIENT_FIN_TIMEOUT 2s + Router Pod Env Should Have Value ROUTER_DEFAULT_SERVER_TIMEOUT 60s + Router Pod Env Should Have Value ROUTER_DEFAULT_SERVER_FIN_TIMEOUT 2s + Router Pod Env Should Have Value ROUTER_DEFAULT_TUNNEL_TIMEOUT 2h + Router Pod Env Should Have Value ROUTER_INSPECT_DELAY 10s + Router Pod Env Should Have Value ROUTER_THREADS 8 + Router Pod Env Should Have Value ROUTER_MAX_CONNECTIONS 100000 + +Verify Custom Router Tuning Haproxy + [Documentation] Verify the custom tuning values are present in haproxy.config after config change. + ${haproxy}= Read Haproxy Config + Should Contain ${haproxy} tune.bufsize 65536 + Should Contain ${haproxy} tune.maxrewrite 16384 + Should Contain ${haproxy} timeout client 60s + Should Contain ${haproxy} timeout server 60s + Should Contain ${haproxy} timeout tunnel 2h + Should Contain ${haproxy} nbthread 8 + Should Contain ${haproxy} maxconn 100000 + Prepare Custom Cert For Test [Documentation] Generate CA and user cert for custom certificate test, create TLS secret. [Arguments] ${case_id} ${edge_host} @@ -912,10 +780,7 @@ Prepare Custom Cert For Test Create Directory ${tmpdir} VAR ${CERT_TMPDIR}= ${tmpdir} scope=TEST VAR ${CERT_EDGE_HOST}= ${edge_host} scope=TEST - - Generate CA Certificate - ... ${tmpdir}/ca.key ${tmpdir}/ca.crt /CN=MS-default-CA - + Generate CA Certificate ${tmpdir}/ca.key ${tmpdir}/ca.crt /CN=MS-default-CA ${san}= Catenate SEPARATOR=\n ... [ v3_req ] ... subjectAltName = @alt_names @@ -923,11 +788,23 @@ Prepare Custom Cert For Test ... DNS.1 = *.${BASE_DOMAIN} Generate CSR And Key ${tmpdir}/usr.key ${tmpdir}/usr.csr /CN=example-ne.com Sign CSR With CA ${tmpdir}/usr.csr ${tmpdir}/ca.crt ${tmpdir}/ca.key ${tmpdir}/usr.crt ${san} - Run With Kubeconfig ... oc create secret tls router-test-cert --cert=${tmpdir}/ca.crt --key=${tmpdir}/ca.key -n ${ROUTER_NS} Deploy Web Server +Verify Custom Cert Is Active + [Documentation] Verify the custom cert secret is mounted and the cert issuer is correct. + ${vol}= Oc Get JsonPath + ... deployment + ... ${ROUTER_NS} + ... router-default + ... ..volumes[?(@.name=="default-certificate")].secret.secretName + Should Contain ${vol} router-test-cert + ${router_pod}= Get Router Pod Name + ${cert_info}= Run With Kubeconfig + ... oc exec -n ${ROUTER_NS} ${router_pod} -- openssl x509 -noout -in /etc/pki/tls/private/tls.crt -text + Should Contain ${cert_info} CN = MS-default-CA + Prepare MTLS Cert For Test [Documentation] Generate CA and client cert for mTLS tests. [Arguments] ${case_id} ${edge_host} @@ -935,14 +812,7 @@ Prepare MTLS Cert For Test Create Directory ${tmpdir} VAR ${MTLS_TMPDIR}= ${tmpdir} scope=TEST VAR ${MTLS_EDGE_HOST}= ${edge_host} scope=TEST - VAR ${MTLS_CA_CRT}= ${tmpdir}/ca.crt scope=TEST - VAR ${MTLS_USR_CRT}= ${tmpdir}/usr.crt scope=TEST - VAR ${MTLS_USR_KEY}= ${tmpdir}/usr.key scope=TEST - - Generate CA Certificate ${tmpdir}/ca.key ${tmpdir}/ca.crt /CN=MS-Test-Root-CA - Generate CSR And Key ${tmpdir}/usr.key ${tmpdir}/usr.csr /CN=example-test.com - VAR ${san}= subjectAltName = DNS.1:*.${BASE_DOMAIN},DNS.2:${edge_host} - Sign CSR With CA ${tmpdir}/usr.csr ${tmpdir}/ca.crt ${tmpdir}/ca.key ${tmpdir}/usr.crt ${san} + Generate MTLS Client Cert ${tmpdir} ${edge_host} Prepare Two MTLS Certs For Test [Documentation] Generate CA and two client certs with different subjects for mTLS subject filter test. @@ -950,24 +820,158 @@ Prepare Two MTLS Certs For Test VAR ${tmpdir}= /tmp/ocp-${case_id}-ca Create Directory ${tmpdir} VAR ${MTLS2_TMPDIR}= ${tmpdir} scope=TEST - VAR ${MTLS2_CA_CRT}= ${tmpdir}/ca.crt scope=TEST VAR ${MTLS2_HOST1}= ${host1} scope=TEST VAR ${MTLS2_HOST2}= ${host2} scope=TEST - VAR ${MTLS2_USR_CRT1}= ${tmpdir}/usr1.crt scope=TEST - VAR ${MTLS2_USR_KEY1}= ${tmpdir}/usr1.key scope=TEST - VAR ${MTLS2_USR_CRT2}= ${tmpdir}/usr2.crt scope=TEST - VAR ${MTLS2_USR_KEY2}= ${tmpdir}/usr2.key scope=TEST - Generate CA Certificate ${tmpdir}/ca.key ${tmpdir}/ca.crt /CN=MS-Test-Root-CA - Generate CSR And Key ${tmpdir}/usr1.key ${tmpdir}/usr1.csr /CN=example-test.com - VAR ${san1}= subjectAltName = DNS.1:*.${BASE_DOMAIN},DNS.2:${host1} - Sign CSR With CA ${tmpdir}/usr1.csr ${tmpdir}/ca.crt ${tmpdir}/ca.key ${tmpdir}/usr1.crt ${san1} - Generate CSR And Key ${tmpdir}/usr2.key ${tmpdir}/usr2.csr /CN=example-test2.com - VAR ${san2}= subjectAltName = DNS.1:*.${BASE_DOMAIN},DNS.2:${host2} - Sign CSR With CA ${tmpdir}/usr2.csr ${tmpdir}/ca.crt ${tmpdir}/ca.key ${tmpdir}/usr2.crt ${san2} + Generate Client Cert File In Dir ${tmpdir} ${host1} /CN=example-test.com usr1 + Generate Client Cert File In Dir ${tmpdir} ${host2} /CN=example-test2.com usr2 + +Deploy MTLS Test Workloads + [Documentation] Deploy workloads and create the mTLS edge route. + Deploy Web Server + Deploy Test Client Pod + Copy Files To Pod ${NAMESPACE} ${CLIENT_POD_NAME} ${MTLS_TMPDIR} /data/certs + Create OC Route ${NAMESPACE} edge route-edge service-unsecure + ... --hostname=${MTLS_EDGE_HOST} --cert=${MTLS_TMPDIR}/usr.crt --key=${MTLS_TMPDIR}/usr.key + Route Should Be Admitted route-edge + +Curl All Cookie Routes And Verify Logs + [Documentation] Curl all routes with cookies and verify correct log entries. + [Arguments] ${routehost} ${edge_host} ${reen_host} ${router_ip} + Wait Until Curl With Cookie Succeeds From Pod + ... ${CLIENT_POD_NAME} + ... ${NAMESPACE} + ... http://${routehost}/index.html + ... ${routehost}:80:${router_ip} + ... fo=nobar + Wait Until Curl With Cookie Succeeds From Pod + ... ${CLIENT_POD_NAME} + ... ${NAMESPACE} + ... http://${routehost}/index.html + ... ${routehost}:80:${router_ip} + ... foo=bar + Wait Until Curl With Cookie Succeeds From Pod + ... ${CLIENT_POD_NAME} + ... ${NAMESPACE} + ... http://${routehost}/index.html + ... ${routehost}:80:${router_ip} + ... foo22=bar22 + Wait Until HTTPS Curl With Cookie Succeeds From Pod + ... ${CLIENT_POD_NAME} + ... ${NAMESPACE} + ... https://${edge_host}/index.html + ... ${edge_host}:443:${router_ip} + ... foo=barforedge + Wait Until HTTPS Curl With Cookie Succeeds From Pod + ... ${CLIENT_POD_NAME} + ... ${NAMESPACE} + ... https://${reen_host}/index.html + ... ${reen_host}:443:${router_ip} + ... foo=barforreen + Wait For Router Logs To Contain foo=bar + Wait For Router Logs To Contain foo22=bar22 + Wait For Router Logs To Contain foo=barforedge + Wait For Router Logs To Contain foo=barforreen + Router Logs Should Not Contain fo=nobar + +Verify Header Capture Config And Logs + [Documentation] Verify haproxy header capture config and check captured headers in logs. + [Arguments] ${routehost} ${edge_host} ${reen_host} + Verify Header Capture In Haproxy + ${router_ip}= Get Router Pod IP + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} http://${routehost}/index.html ${routehost}:80:${router_ip} + Wait Until HTTPS Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} https://${edge_host}/index.html ${edge_host}:443:${router_ip} + Wait Until HTTPS Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} https://${reen_host}/index.html ${reen_host}:443:${router_ip} + Wait For Router Logs To Contain ${routehost} + Wait For Router Logs To Contain ${edge_host} + Wait For Router Logs To Contain ${reen_host} + +Verify Header Capture In Haproxy + [Documentation] Verify the haproxy frontend has the expected header capture configuration. + ${router_pod}= Get Router Pod Name + ${haproxy}= Run With Kubeconfig + ... oc exec -n ${ROUTER_NS} ${router_pod} -- grep -A 20 "frontend fe_sni" haproxy.config + Should Contain ${haproxy} capture request header Host len 120 + Should Contain ${haproxy} capture response header Server len 120 + +Verify Custom Error Pages + [Documentation] Verify custom 503 and 404 error pages are served by the router. + [Arguments] ${routehost} ${noexist_host} + ${router_pod}= Get Router Pod Name + ${error503}= Run With Kubeconfig + ... oc exec -n ${ROUTER_NS} ${router_pod} -- cat /var/lib/haproxy/errorfiles/error-page-503.http + Should Contain ${error503} Custom:Application Unavailable + ${error404}= Run With Kubeconfig + ... oc exec -n ${ROUTER_NS} ${router_pod} -- cat /var/lib/haproxy/errorfiles/error-page-404.http + Should Contain ${error404} Custom:Not Found + ${router_ip}= Get Router Pod IP + ${output}= Run With Kubeconfig + ... oc exec -n ${NAMESPACE} ${CLIENT_POD_NAME} -- curl http://${noexist_host} -s --resolve ${noexist_host}:80:${router_ip} --connect-timeout 10 + Should Contain ${output} Custom:Not Found + Scale Deployment ${NAMESPACE} web-server-deploy 0 + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} http://${routehost} ${routehost}:80:${router_ip} + ... Custom:Application Unavailable + +Verify Syslog Logging + [Documentation] Apply syslog config and verify log delivery, then verify facility change. + [Arguments] ${syslog_ip} + VAR ${config1}= SEPARATOR=\n + ... --- + ... ingress: + ... \ \ accessLogging: + ... \ \ \ \ destination: + ... \ \ \ \ \ \ syslog: + ... \ \ \ \ \ \ \ \ address: ${syslog_ip} + ... \ \ \ \ \ \ \ \ port: 514 + ... \ \ \ \ \ \ type: Syslog + ... \ \ \ \ status: Enabled + Setup Router Config And Restart ${config1} + VAR ${routehost}= route-unsec82015.${BASE_DOMAIN} + Create OC Route ${NAMESPACE} http route-http service-unsecure --hostname=${routehost} + Route Should Be Admitted route-http + Verify Syslog Haproxy Config ${syslog_ip} local1 + Verify Syslog Log Delivery ${routehost} ${syslog_ip} + VAR ${config2}= SEPARATOR=\n + ... --- + ... ingress: + ... \ \ accessLogging: + ... \ \ \ \ destination: + ... \ \ \ \ \ \ syslog: + ... \ \ \ \ \ \ \ \ address: ${syslog_ip} + ... \ \ \ \ \ \ \ \ port: 514 + ... \ \ \ \ \ \ \ \ facility: local2 + ... \ \ \ \ \ \ type: Syslog + ... \ \ \ \ status: Enabled + Setup Router Config And Restart ${config2} + Verify Syslog Haproxy Config ${syslog_ip} local2 + +Verify Syslog Haproxy Config + [Documentation] Verify the syslog server address and facility in haproxy global config. + [Arguments] ${syslog_ip} ${facility} + ${haproxy}= Read Haproxy Config + Should Contain ${haproxy} log ${syslog_ip}:514 len 1024 ${facility} info + +Verify Syslog Log Delivery + [Documentation] Curl a route and verify the log entry appears in the syslog pod. + [Arguments] ${routehost} ${syslog_ip} + ${router_ip}= Get Router Pod IP + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} + ... http://${routehost}/path/second/index.html ${routehost}:80:${router_ip} + Wait Until Keyword Succeeds 60s 3s Syslog Pod Should Contain /path/second/index.html Syslog Pod Should Contain [Documentation] Check that the rsyslogd pod logs contain a pattern. [Arguments] ${pattern} ${logs}= Oc Logs rsyslogd-pod --tail=20 ${NAMESPACE} Should Contain ${logs} ${pattern} + +Router Logs Should Not Contain + [Documentation] Verify the router access logs do NOT contain a given pattern. + [Arguments] ${pattern} + ${logs}= Get Router Access Logs + Should Not Contain ${logs} ${pattern} diff --git a/test/suites/router/router-routes.robot b/test/suites/router/router-routes.robot index 89dcc3eb45..ff79b66535 100644 --- a/test/suites/router/router-routes.robot +++ b/test/suites/router/router-routes.robot @@ -27,10 +27,9 @@ Reencrypt Route Via Ingress With Destination CA ${router_ip}= Get Router Pod IP ${srv_pod}= Get Web Server Pod Name - Wait Until Curl Succeeds From Pod + Wait Until HTTPS Curl Succeeds From Pod ... ${srv_pod} ${NAMESPACE} ... https://service-secure-test.example.com:443 service-secure-test.example.com:443:${router_ip} - ... 200 -k ${haproxy}= Read Haproxy Config Should Contain ${haproxy} backend be_secure:${NAMESPACE}:ingress-ms-reen [Teardown] Teardown Reencrypt Ingress Test @@ -45,26 +44,19 @@ Edge And Passthrough Routes VAR ${pass_host}= route-pass-60266.${BASE_DOMAIN} VAR ${edge_host}= route-edge-60266.${BASE_DOMAIN} - Create OC Route ${NAMESPACE} passthrough ms-pass service-secure - ... --hostname=${pass_host} + Create OC Route ${NAMESPACE} passthrough ms-pass service-secure --hostname=${pass_host} Route Should Be Admitted ms-pass - Wait Until Curl Succeeds From Pod - ... ${srv_pod} ${NAMESPACE} - ... https://${pass_host}:443 ${pass_host}:443:${router_ip} - ... 200 -k + Wait Until HTTPS Curl Succeeds From Pod + ... ${srv_pod} ${NAMESPACE} https://${pass_host}:443 ${pass_host}:443:${router_ip} ${haproxy}= Read Haproxy Config Should Contain ${haproxy} backend be_tcp:${NAMESPACE}:ms-pass - Create OC Route ${NAMESPACE} edge ms-edge service-unsecure - ... --hostname=${edge_host} + Create OC Route ${NAMESPACE} edge ms-edge service-unsecure --hostname=${edge_host} Route Should Be Admitted ms-edge - Wait Until Curl Succeeds From Pod - ... ${srv_pod} ${NAMESPACE} - ... https://${edge_host}:443 ${edge_host}:443:${router_ip} - ... 200 -k + Wait Until HTTPS Curl Succeeds From Pod + ... ${srv_pod} ${NAMESPACE} https://${edge_host}:443 ${edge_host}:443:${router_ip} ${haproxy}= Read Haproxy Config Should Contain ${haproxy} backend be_edge_http:${NAMESPACE}:ms-edge - [Teardown] Run Keywords ... Oc Delete route/ms-pass route/ms-edge -n ${NAMESPACE} ... AND Oc Delete -f ${WEB_SERVER_DEPLOY} -n ${NAMESPACE} @@ -79,26 +71,19 @@ HTTP And Reencrypt Routes VAR ${http_host}= route-http-60283.${BASE_DOMAIN} VAR ${reen_host}= route-reen-60283.${BASE_DOMAIN} - Create OC Route ${NAMESPACE} http ms-http service-unsecure - ... --hostname=${http_host} + Create OC Route ${NAMESPACE} http ms-http service-unsecure --hostname=${http_host} Route Should Be Admitted ms-http Wait Until Curl Succeeds From Pod - ... ${srv_pod} ${NAMESPACE} - ... http://${http_host}:80 ${http_host}:80:${router_ip} - ... 200 + ... ${srv_pod} ${NAMESPACE} http://${http_host}:80 ${http_host}:80:${router_ip} ${haproxy}= Read Haproxy Config Should Contain ${haproxy} backend be_http:${NAMESPACE}:ms-http - Create OC Route ${NAMESPACE} reencrypt ms-reen service-secure - ... --hostname=${reen_host} + Create OC Route ${NAMESPACE} reencrypt ms-reen service-secure --hostname=${reen_host} Route Should Be Admitted ms-reen - Wait Until Curl Succeeds From Pod - ... ${srv_pod} ${NAMESPACE} - ... https://${reen_host}:443 ${reen_host}:443:${router_ip} - ... 200 -k + Wait Until HTTPS Curl Succeeds From Pod + ... ${srv_pod} ${NAMESPACE} https://${reen_host}:443 ${reen_host}:443:${router_ip} ${haproxy}= Read Haproxy Config Should Contain ${haproxy} backend be_secure:${NAMESPACE}:ms-reen - [Teardown] Run Keywords ... Oc Delete route/ms-http route/ms-reen -n ${NAMESPACE} ... AND Oc Delete -f ${WEB_SERVER_SIGNED_DEPLOY} -n ${NAMESPACE} @@ -110,44 +95,22 @@ Namespace Ownership Default Config [Setup] Setup Two Namespace Test ${router_ip}= Get Router Pod IP - VAR ${http_host}= service-unsecure-ocp72802.${BASE_DOMAIN} - VAR ${edge_host}= route-edge-ocp72802.${BASE_DOMAIN} - VAR ${reen_host}= route-reen-ocp72802.${BASE_DOMAIN} + VAR ${HTTP_HOST}= service-unsecure-ocp72802.${BASE_DOMAIN} scope=TEST + VAR ${EDGE_HOST}= route-edge-ocp72802.${BASE_DOMAIN} scope=TEST + VAR ${REEN_HOST}= route-reen-ocp72802.${BASE_DOMAIN} scope=TEST ${env}= Oc Get JsonPath ... pod ${ROUTER_NS} ${EMPTY} ... .items[*].spec.containers[*].env[?(@.name=="ROUTER_DISABLE_NAMESPACE_OWNERSHIP_CHECK")].value Should Be Equal As Strings ${env} true - Create OC Route ${NS1} http service-unsecure service-unsecure - ... --hostname=${http_host} --path=/path - Create OC Route ${NS1} edge route-edge service-unsecure - ... --hostname=${edge_host} --path=/path - Create OC Route ${NS1} reencrypt route-reen service-secure - ... --hostname=${reen_host} --path=/path - Create OC Route ${NS2} http service-unsecure service-unsecure - ... --hostname=${http_host} --path=/test - Create OC Route ${NS2} edge route-edge service-unsecure - ... --hostname=${edge_host} --path=/test - Create OC Route ${NS2} reencrypt route-reen service-secure - ... --hostname=${reen_host} --path=/test - - Route Should Be Admitted service-unsecure ${NS1} - Route Should Be Admitted route-edge ${NS1} - Route Should Be Admitted route-reen ${NS1} - Route Should Be Admitted service-unsecure ${NS2} - Route Should Be Admitted route-edge ${NS2} - Route Should Be Admitted route-reen ${NS2} + Create NS Ownership Routes + All NS Ownership Routes Should Be Admitted Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NS1} - ... http://${http_host}/path/index.html ${http_host}:80:${router_ip} - ... 200 + ... ${CLIENT_POD_NAME} ${NS1} http://${HTTP_HOST}/path/index.html ${HTTP_HOST}:80:${router_ip} Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NS1} - ... http://${http_host}/test/index.html ${http_host}:80:${router_ip} - ... 200 - + ... ${CLIENT_POD_NAME} ${NS1} http://${HTTP_HOST}/test/index.html ${HTTP_HOST}:80:${router_ip} [Teardown] Teardown Two Namespace Test Router Load Balancer Service Type @@ -163,40 +126,15 @@ Router Load Balancer Service Type ${lb_ips}= Get LB IPs Should Not Be Empty ${lb_ips} - VAR ${http_host}= service-unsecure-ocp73152.${BASE_DOMAIN} - VAR ${edge_host}= route-edge-ocp73152.${BASE_DOMAIN} - VAR ${pass_host}= route-passth-ocp73152.${BASE_DOMAIN} - VAR ${reen_host}= route-reen-ocp73152.${BASE_DOMAIN} - - Create OC Route ${NAMESPACE} http route-http service-unsecure - ... --hostname=${http_host} - Create OC Route ${NAMESPACE} edge route-edge service-unsecure - ... --hostname=${edge_host} - Create OC Route ${NAMESPACE} passthrough route-passth service-secure - ... --hostname=${pass_host} - Create OC Route ${NAMESPACE} reencrypt route-reen service-secure - ... --hostname=${reen_host} - Route Should Be Admitted route-reen + VAR ${HTTP_HOST}= service-unsecure-ocp73152.${BASE_DOMAIN} scope=TEST + VAR ${EDGE_HOST}= route-edge-ocp73152.${BASE_DOMAIN} scope=TEST + VAR ${PASS_HOST}= route-passth-ocp73152.${BASE_DOMAIN} scope=TEST + VAR ${REEN_HOST}= route-reen-ocp73152.${BASE_DOMAIN} scope=TEST - ${lb_ip}= Fetch From Left ${lb_ips} ${SPACE} - - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${http_host} ${http_host}:80:${lb_ip} - ... 200 - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${edge_host} ${edge_host}:443:${lb_ip} - ... 200 -k - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${pass_host} ${pass_host}:443:${lb_ip} - ... 200 -k - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${reen_host} ${reen_host}:443:${lb_ip} - ... 200 -k + Create And Admit Four Route Types ${HTTP_HOST} ${EDGE_HOST} ${PASS_HOST} ${REEN_HOST} + ${lb_ip}= Fetch From Left ${lb_ips} ${SPACE} + Curl All LB Route Types Via IP ${lb_ip} [Teardown] Run Keywords ... Oc Delete route/route-http route/route-edge route/route-passth route/route-reen -n ${NAMESPACE} ... AND Oc Delete -f ${WEB_SERVER_SIGNED_DEPLOY} -n ${NAMESPACE} @@ -210,53 +148,20 @@ Default Listening IPs And Ports ... Deploy Web Server Signed ... AND Deploy Test Client Pod - ${http_port}= Get LB Port http - Should Be Equal As Strings ${http_port} 80 - ${https_port}= Get LB Port https - Should Be Equal As Strings ${https_port} 443 + Verify Default LB IPs And Ports - ${lb_ips}= Get LB IPs - Should Not Be Empty ${lb_ips} - @{host_ips}= Get Host IPs Via SSH - ${sorted_host_ips}= Evaluate " ".join(sorted(${host_ips})) - ${sorted_lb_ips}= Evaluate " ".join(sorted("${lb_ips}".split())) - Should Be Equal As Strings ${sorted_lb_ips} ${sorted_host_ips} + VAR ${HTTP_HOST}= service-unsecure-ocp73202.${BASE_DOMAIN} scope=TEST + VAR ${EDGE_HOST}= route-edge-ocp73202.${BASE_DOMAIN} scope=TEST + VAR ${PASS_HOST}= route-passth-ocp73202.${BASE_DOMAIN} scope=TEST + VAR ${REEN_HOST}= route-reen-ocp73202.${BASE_DOMAIN} scope=TEST - VAR ${http_host}= service-unsecure-ocp73202.${BASE_DOMAIN} - VAR ${edge_host}= route-edge-ocp73202.${BASE_DOMAIN} - VAR ${pass_host}= route-passth-ocp73202.${BASE_DOMAIN} - VAR ${reen_host}= route-reen-ocp73202.${BASE_DOMAIN} - - Create OC Route ${NAMESPACE} http route-http service-unsecure - ... --hostname=${http_host} - Create OC Route ${NAMESPACE} edge route-edge service-unsecure - ... --hostname=${edge_host} - Create OC Route ${NAMESPACE} passthrough route-passth service-secure - ... --hostname=${pass_host} - Create OC Route ${NAMESPACE} reencrypt route-reen service-secure - ... --hostname=${reen_host} - Route Should Be Admitted route-reen + Create And Admit Four Route Types ${HTTP_HOST} ${EDGE_HOST} ${PASS_HOST} ${REEN_HOST} + ${lb_ips}= Get LB IPs @{ips}= Split String ${lb_ips} FOR ${lb_ip} IN @{ips} - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... http://${http_host} ${http_host}:80:${lb_ip} - ... 200 - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${edge_host} ${edge_host}:443:${lb_ip} - ... 200 -k - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${pass_host} ${pass_host}:443:${lb_ip} - ... 200 -k - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} - ... https://${reen_host} ${reen_host}:443:${lb_ip} - ... 200 -k + Curl All LB Route Types Via IP ${lb_ip} END - [Teardown] Run Keywords ... Oc Delete route/route-http route/route-edge route/route-passth route/route-reen -n ${NAMESPACE} ... AND Oc Delete -f ${WEB_SERVER_SIGNED_DEPLOY} -n ${NAMESPACE} @@ -277,10 +182,8 @@ Teardown Reencrypt Ingress Test Setup Two Namespace Test [Documentation] Create two extra namespaces and deploy workloads in each. - VAR ${NS1}= ${NAMESPACE}-ocp72802-1 - VAR ${NS2}= ${NAMESPACE}-ocp72802-2 - VAR ${NS1}= ${NS1} scope=TEST - VAR ${NS2}= ${NS2} scope=TEST + VAR ${NS1}= ${NAMESPACE}-ocp72802-1 scope=TEST + VAR ${NS2}= ${NAMESPACE}-ocp72802-2 scope=TEST Create Namespace ${NS1} Create Namespace ${NS2} Deploy Test Client Pod ${NS1} @@ -292,3 +195,55 @@ Teardown Two Namespace Test [Documentation] Delete the extra namespaces. Remove Namespace ${NS1} Remove Namespace ${NS2} + +Create NS Ownership Routes + [Documentation] Create HTTP, edge, and reencrypt routes in both test namespaces. + Create OC Route ${NS1} http service-unsecure service-unsecure + ... --hostname=${HTTP_HOST} --path=/path + Create OC Route ${NS1} edge route-edge service-unsecure + ... --hostname=${EDGE_HOST} --path=/path + Create OC Route ${NS1} reencrypt route-reen service-secure + ... --hostname=${REEN_HOST} --path=/path + Create OC Route ${NS2} http service-unsecure service-unsecure + ... --hostname=${HTTP_HOST} --path=/test + Create OC Route ${NS2} edge route-edge service-unsecure + ... --hostname=${EDGE_HOST} --path=/test + Create OC Route ${NS2} reencrypt route-reen service-secure + ... --hostname=${REEN_HOST} --path=/test + +All NS Ownership Routes Should Be Admitted + [Documentation] Verify all six routes across both namespaces are admitted. + Route Should Be Admitted service-unsecure ${NS1} + Route Should Be Admitted route-edge ${NS1} + Route Should Be Admitted route-reen ${NS1} + Route Should Be Admitted service-unsecure ${NS2} + Route Should Be Admitted route-edge ${NS2} + Route Should Be Admitted route-reen ${NS2} + +Curl All LB Route Types Via IP + [Documentation] Curl all four route types through a single LB IP. + [Arguments] ${ip} + Wait Until Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} + ... ${NAMESPACE} + ... http://${HTTP_HOST} + ... ${HTTP_HOST}:80:${ip} + Wait Until HTTPS Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} https://${EDGE_HOST} ${EDGE_HOST}:443:${ip} + Wait Until HTTPS Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} https://${PASS_HOST} ${PASS_HOST}:443:${ip} + Wait Until HTTPS Curl Succeeds From Pod + ... ${CLIENT_POD_NAME} ${NAMESPACE} https://${REEN_HOST} ${REEN_HOST}:443:${ip} + +Verify Default LB IPs And Ports + [Documentation] Verify the router-default service LB IPs match all host IPs and ports are 80/443. + ${http_port}= Get LB Port http + Should Be Equal As Strings ${http_port} 80 + ${https_port}= Get LB Port https + Should Be Equal As Strings ${https_port} 443 + ${lb_ips}= Get LB IPs + Should Not Be Empty ${lb_ips} + @{host_ips}= Get Host IPs Via SSH + ${sorted_host_ips}= Evaluate " ".join(sorted(${host_ips})) + ${sorted_lb_ips}= Evaluate " ".join(sorted("${lb_ips}".split())) + Should Be Equal As Strings ${sorted_lb_ips} ${sorted_host_ips} From 28add89347f63f3dc80ee1dbe0a25ff9f0307396 Mon Sep 17 00:00:00 2001 From: Alejandro Gullon Date: Mon, 25 May 2026 17:56:15 +0200 Subject: [PATCH 4/5] USHIFT-6746: fix three bugs found during review - Fix mTLS subject filter (OCP-80518): remove double /CN= prefix from Generate Client Cert File In Dir callers. The keyword already prefixes /CN=, so callers should pass the bare CN value (e.g. example-test.com). The malformed subject /CN=/CN=example-test.com would never match the allowedSubjectPatterns filter, causing usr1 cert to return 403 instead of 200 and inverting the test assertions. - Fix custom error page 503 check (OCP-82004): replace the 503 assertion using Wait Until Curl Succeeds From Pod (which uses curl -sI / HEAD method, headers only) with a direct GET curl via a new Custom 503 Body Should Contain keyword. The HTML error body never appears in HEAD response output, so the assertion would always fail. - Fix tuning timeout normalization (OCP-77349): MicroShift normalizes clientTimeout/serverTimeout "60s" to "1m" before propagating to the deployment env vars and haproxy config. Update expected values from "60s" to "1m" to match actual runtime behavior (confirmed from the original Go source which uses 1m as the expected value). Co-Authored-By: Claude Sonnet 4.6 pre-commit.check-secrets: ENABLED --- test/suites/router/router-config.robot | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/test/suites/router/router-config.robot b/test/suites/router/router-config.robot index 899a2708d1..c58ab59ed6 100644 --- a/test/suites/router/router-config.robot +++ b/test/suites/router/router-config.robot @@ -753,9 +753,9 @@ Verify Custom Router Tuning Env Vars [Documentation] Verify the custom tuning environment variable values after config change. Router Pod Env Should Have Value ROUTER_BUF_SIZE 65536 Router Pod Env Should Have Value ROUTER_MAX_REWRITE_SIZE 16384 - Router Pod Env Should Have Value ROUTER_DEFAULT_CLIENT_TIMEOUT 60s + Router Pod Env Should Have Value ROUTER_DEFAULT_CLIENT_TIMEOUT 1m Router Pod Env Should Have Value ROUTER_CLIENT_FIN_TIMEOUT 2s - Router Pod Env Should Have Value ROUTER_DEFAULT_SERVER_TIMEOUT 60s + Router Pod Env Should Have Value ROUTER_DEFAULT_SERVER_TIMEOUT 1m Router Pod Env Should Have Value ROUTER_DEFAULT_SERVER_FIN_TIMEOUT 2s Router Pod Env Should Have Value ROUTER_DEFAULT_TUNNEL_TIMEOUT 2h Router Pod Env Should Have Value ROUTER_INSPECT_DELAY 10s @@ -767,8 +767,8 @@ Verify Custom Router Tuning Haproxy ${haproxy}= Read Haproxy Config Should Contain ${haproxy} tune.bufsize 65536 Should Contain ${haproxy} tune.maxrewrite 16384 - Should Contain ${haproxy} timeout client 60s - Should Contain ${haproxy} timeout server 60s + Should Contain ${haproxy} timeout client 1m + Should Contain ${haproxy} timeout server 1m Should Contain ${haproxy} timeout tunnel 2h Should Contain ${haproxy} nbthread 8 Should Contain ${haproxy} maxconn 100000 @@ -823,8 +823,8 @@ Prepare Two MTLS Certs For Test VAR ${MTLS2_HOST1}= ${host1} scope=TEST VAR ${MTLS2_HOST2}= ${host2} scope=TEST Generate CA Certificate ${tmpdir}/ca.key ${tmpdir}/ca.crt /CN=MS-Test-Root-CA - Generate Client Cert File In Dir ${tmpdir} ${host1} /CN=example-test.com usr1 - Generate Client Cert File In Dir ${tmpdir} ${host2} /CN=example-test2.com usr2 + Generate Client Cert File In Dir ${tmpdir} ${host1} example-test.com usr1 + Generate Client Cert File In Dir ${tmpdir} ${host2} example-test2.com usr2 Deploy MTLS Test Workloads [Documentation] Deploy workloads and create the mTLS edge route. @@ -912,9 +912,15 @@ Verify Custom Error Pages ... oc exec -n ${NAMESPACE} ${CLIENT_POD_NAME} -- curl http://${noexist_host} -s --resolve ${noexist_host}:80:${router_ip} --connect-timeout 10 Should Contain ${output} Custom:Not Found Scale Deployment ${NAMESPACE} web-server-deploy 0 - Wait Until Curl Succeeds From Pod - ... ${CLIENT_POD_NAME} ${NAMESPACE} http://${routehost} ${routehost}:80:${router_ip} - ... Custom:Application Unavailable + Wait Until Keyword Succeeds 60s 2s + ... Custom 503 Body Should Contain ${routehost} ${router_ip} + +Custom 503 Body Should Contain + [Documentation] Curl a route (GET, full response body) and assert the custom 503 error page body is returned. + [Arguments] ${routehost} ${router_ip} + ${output}= Run With Kubeconfig + ... oc exec -n ${NAMESPACE} ${CLIENT_POD_NAME} -- curl http://${routehost} -s --resolve ${routehost}:80:${router_ip} --connect-timeout 10 + Should Contain ${output} Custom:Application Unavailable Verify Syslog Logging [Documentation] Apply syslog config and verify log delivery, then verify facility change. From 4954eb621941141ef87c6d3f0c6a7f6d0d49dba8 Mon Sep 17 00:00:00 2001 From: Alejandro Gullon Date: Mon, 25 May 2026 18:06:04 +0200 Subject: [PATCH 5/5] USHIFT-6746: apply CodeRabbit suggestions - Fix header capture maxLength assertion (OCP-82003): the truncated hostname is exactly 16 chars ("route-unsec82003"), not 19; waiting for "route-unsec82003.ap" would always time out. Fix the assertion and the accompanying comment. - Assert admission for all four route types in Create And Admit Four Route Types: previously only route-reen was gated; adding checks for route-http, route-edge, and route-passth gives clearer failure messages when a specific route type fails to be admitted. - Check LB IP exclusivity in Verify Custom LB Ports And IP: use Should Be Equal As Strings instead of Should Contain so the test fails if the router-default service exposes additional IPs beyond the configured listenAddress interface. Co-Authored-By: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-Authored-By: Claude Sonnet 4.6 pre-commit.check-secrets: ENABLED --- test/resources/router.resource | 3 +++ test/suites/router/router-config.robot | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/resources/router.resource b/test/resources/router.resource index d65267bdb9..e65a543c03 100644 --- a/test/resources/router.resource +++ b/test/resources/router.resource @@ -95,6 +95,9 @@ Create And Admit Four Route Types Create OC Route ${NAMESPACE} edge route-edge service-unsecure --hostname=${edge_host} Create OC Route ${NAMESPACE} passthrough route-passth service-secure --hostname=${pass_host} Create OC Route ${NAMESPACE} reencrypt route-reen service-secure --hostname=${reen_host} + Route Should Be Admitted route-http + Route Should Be Admitted route-edge + Route Should Be Admitted route-passth Route Should Be Admitted route-reen Curl From Pod diff --git a/test/suites/router/router-config.robot b/test/suites/router/router-config.robot index c58ab59ed6..8992ad9e06 100644 --- a/test/suites/router/router-config.robot +++ b/test/suites/router/router-config.robot @@ -595,8 +595,8 @@ HTTP Capture Headers MaxLength Adherence ${router_ip}= Get Router Pod IP Wait Until Curl Succeeds From Pod ... ${CLIENT_POD_NAME} ${NAMESPACE} http://${routehost}/index.html ${routehost}:80:${router_ip} - # route-unsec82003.apps.e is 16 chars, so the full hostname should not appear - Wait For Router Logs To Contain route-unsec82003.ap + # maxLength is 16, so hostname is truncated to exactly 16 chars: route-unsec82003 + Wait For Router Logs To Contain route-unsec82003 ${logs}= Get Router Access Logs Should Not Contain ${logs} ${routehost} # nginx server version is 5+ chars, so only "nginx" should appear without the version @@ -703,7 +703,7 @@ Verify Custom LB Ports And IP [Documentation] Check the router-default LB has the expected IP and custom port numbers. [Arguments] ${host_ip} ${lb_ips}= Get LB IPs - Should Contain ${lb_ips} ${host_ip} + Should Be Equal As Strings ${lb_ips} ${host_ip} ${http_port}= Get LB Port http Should Be Equal As Strings ${http_port} ${ALT_HTTP_PORT} ${https_port}= Get LB Port https