def test_event_message_and_config(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup): invalid_fields = [ "upstreams[0].lb-method", "upstreams[0].fail-timeout", "upstreams[0].max-fails", "upstreams[0].connect-timeout", "upstreams[0].read-timeout", "upstreams[0].send-timeout", "upstreams[0].keepalive", "upstreams[0].max-conns", "upstreams[0].next-upstream", "upstreams[0].next-upstream-timeout", "upstreams[0].next-upstream-tries", "upstreams[0].client-max-body-size", "upstreams[0].buffers.number", "upstreams[0].buffers.size", "upstreams[0].buffer-size", "upstreams[1].lb-method", "upstreams[1].fail-timeout", "upstreams[1].max-fails", "upstreams[1].connect-timeout", "upstreams[1].read-timeout", "upstreams[1].send-timeout", "upstreams[1].keepalive", "upstreams[1].max-conns", "upstreams[1].next-upstream", "upstreams[1].next-upstream-timeout", "upstreams[1].next-upstream-tries", "upstreams[1].client-max-body-size", "upstreams[1].buffers.number", "upstreams[1].buffers.size", "upstreams[1].buffer-size" ] text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"VirtualServer {text} was rejected with error:" vs_file = f"{TEST_DATA}/virtual-server-upstream-options/virtual-server-with-invalid-keys.yaml" patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_file, virtual_server_setup.namespace) wait_before_test(2) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event_starts_with_text_and_contains_errors(vs_event_text, vs_events, invalid_fields) assert_vs_conf_not_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, virtual_server_setup)
def test_policy_non_matching_ingress_class( self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, src, ): """ Test if non matching policy gets caught by vc validation """ print(f"Create rl policy") pol_name = create_policy_from_yaml(kube_apis.custom_objects, policy_other_ingress_class_src, test_namespace) wait_before_test() policy_info = read_custom_resource(kube_apis.custom_objects, test_namespace, "policies", pol_name) assert "status" not in policy_info, "the policy is not managed by the IC, therefore the status is not updated" print(f"Patch vs with policy: {src}") patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, src, virtual_server_setup.namespace, ) wait_before_test() vs_info = read_custom_resource(kube_apis.custom_objects, virtual_server_setup.namespace, "virtualservers", virtual_server_setup.vs_name) assert ( vs_info["status"] and "rate-limit-primary is missing or invalid" in vs_info["status"]["message"] and vs_info["status"]["reason"] == "AddedOrUpdatedWithWarning" and vs_info["status"]["state"] == "Warning" ) delete_policy(kube_apis.custom_objects, pol_name, test_namespace) self.restore_default_vs(kube_apis, virtual_server_setup)
def test_virtual_server_no_cm(self, kube_apis, crd_ingress_controller, create_certmanager, virtual_server_setup): vs_src = f"{TEST_DATA}/virtual-server-certmanager/virtual-server-no-tls.yaml" patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, virtual_server_setup.namespace) print("\nStep 1: verify connectivity with no TLS block") resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 print( "\nStep 2: verify connectivity with TLS block but no cert-manager") vs_src = f"{TEST_DATA}/virtual-server-certmanager/virtual-server-no-cm.yaml" secret_src = f"{TEST_DATA}/virtual-server-certmanager/tls-secret.yaml" create_secret_from_yaml(kube_apis.v1, virtual_server_setup.namespace, secret_src) patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, virtual_server_setup.namespace) resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200
def test_responses_after_setup(self, kube_apis, crd_ingress_controller, create_certmanager, virtual_server_setup): vs_src = f"{TEST_DATA}/virtual-server-certmanager/virtual-server-updated.yaml" print("\nStep 1: Verify no secret exists with bad issuer name") secret_name = get_secret_name_from_vs_yaml( f"{TEST_DATA}/virtual-server-certmanager/standard/virtual-server.yaml" ) sec = is_secret_present(kube_apis.v1, secret_name, virtual_server_setup.namespace) assert sec is False patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, virtual_server_setup.namespace) print("\nStep 2: Verify secret exists with updated issuer name") secret_name = get_secret_name_from_vs_yaml( f"{TEST_DATA}/virtual-server-certmanager/virtual-server-updated.yaml" ) sec = is_secret_present(kube_apis.v1, secret_name, virtual_server_setup.namespace) retry = 0 while not sec and retry <= 30: sec = is_secret_present(kube_apis.v1, secret_name, virtual_server_setup.namespace) retry += 1 wait_before_test(5) print(f"Secret not found yet, retrying... #{retry}") print("\nStep 3: verify connectivity") resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200
def test_grpc_healthcheck_validation(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, backend_setup, virtual_server_setup): invalid_fields = [ "upstreams[0].healthCheck.path", "upstreams[0].healthCheck.statusMatch", "upstreams[0].healthCheck.grpcStatus", "upstreams[0].healthCheck.grpcService" ] text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"VirtualServer {text} was rejected with error:" patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, f"{TEST_DATA}/virtual-server-grpc/virtual-server-healthcheck-invalid.yaml", virtual_server_setup.namespace) wait_before_test(2) ic_pod_name = get_first_pod_name( kube_apis.v1, ingress_controller_prerequisites.namespace) vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) print(vs_events) assert_event_starts_with_text_and_contains_errors( vs_event_text, vs_events, invalid_fields) assert_vs_conf_not_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, virtual_server_setup)
def test_policy_matching_ingress_class( self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, src, ): """ Test if policy with matching ingress class is applied to vs """ print(f"Create rl policy") pol_name = create_policy_from_yaml(kube_apis.custom_objects, policy_ingress_class_src, test_namespace) wait_before_test() policy_info = read_custom_resource(kube_apis.custom_objects, test_namespace, "policies", pol_name) assert ( policy_info["status"] and policy_info["status"]["reason"] == "AddedOrUpdated" and policy_info["status"]["state"] == "Valid" ) print(f"Patch vs with policy: {src}") patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, src, virtual_server_setup.namespace, ) wait_before_test() vs_info = read_custom_resource(kube_apis.custom_objects, virtual_server_setup.namespace, "virtualservers", virtual_server_setup.vs_name) assert ( vs_info["status"] and vs_info["status"]["reason"] == "AddedOrUpdated" and vs_info["status"]["state"] == "Valid" ) delete_policy(kube_apis.custom_objects, pol_name, test_namespace) self.restore_default_vs(kube_apis, virtual_server_setup)
def test_regex_rewrite( self, kube_apis, crd_ingress_controller, virtual_server_setup, ): """ Test VirtualServer URI rewrite using regex """ patch_src = f"{TEST_DATA}/virtual-server-rewrites/virtual-server-rewrite-regex.yaml" patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, patch_src, virtual_server_setup.namespace, ) wait_before_test() resp1 = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) resp2 = requests.get(virtual_server_setup.backend_1_url + "/", headers={"host": virtual_server_setup.vs_host}) resp3 = requests.get(virtual_server_setup.backend_2_url + "/abc", headers={"host": virtual_server_setup.vs_host}) self.patch_standard_vs(kube_apis, virtual_server_setup) assert ("URI: /\nRequest" in resp1.text and "URI: /\nRequest" in resp2.text and "URI: /abc\nRequest" in resp3.text)
def test_response_for_regex_location(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup, test_data): req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" vs_src_yaml = f"{TEST_DATA}" \ f"/virtual-server-route-regexp-location/standard/virtual-server-{test_data['regex_type']}.yaml" vsr_src_yaml = f"{TEST_DATA}/virtual-server-route-regexp-location/route-single-{test_data['regex_type']}.yaml" patch_virtual_server_from_yaml(kube_apis.custom_objects, v_s_route_setup.vs_name, vs_src_yaml, v_s_route_setup.namespace) patch_v_s_route_from_yaml(kube_apis.custom_objects, v_s_route_setup.route_s.name, vsr_src_yaml, v_s_route_setup.route_s.namespace) wait_before_test(1) for item in test_data['expected_results']: uri = item expected_code = test_data['expected_results'][uri] ensure_response_from_backend(f"{req_url}{uri}", v_s_route_setup.vs_host) resp = requests.get(f"{req_url}{uri}", headers={"host": v_s_route_setup.vs_host}) if expected_code == 200: assert resp.status_code == expected_code and "Server name: backend2-" in resp.text else: assert resp.status_code == expected_code, "Expected 404 for URI that doesn't match"
def test_virtual_server_after_update(self, kube_apis, crd_ingress_controller, virtual_server_setup): patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, f"{TEST_DATA}/virtual-server-error-pages/virtual-server-updated.yaml", virtual_server_setup.namespace) wait_and_assert_status_code(301, virtual_server_setup.backend_1_url, virtual_server_setup.vs_host, allow_redirects=False) resp = requests.get(virtual_server_setup.backend_1_url, headers={ "host": virtual_server_setup.vs_host, "x-forwarded-proto": "http" }, allow_redirects=False) assert f'http://{virtual_server_setup.vs_host}/error_http.html' in resp.next.url wait_and_assert_status_code(502, virtual_server_setup.backend_2_url, virtual_server_setup.vs_host) resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) resp_content = resp.content.decode('utf-8') assert resp_content == 'Hello World!\n'
def test_responses_and_config_after_disable_tls( self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup): ic_pod_name = get_first_pod_name( kube_apis.v1, ingress_controller_prerequisites.namespace) text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"Configuration for {text} was added or updated" initial_events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace) initial_count = assert_event_and_get_count(vs_event_text, initial_events_vs) patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, f"{TEST_DATA}/virtual-server-upstream-tls/virtual-server-disable-tls.yaml", virtual_server_setup.namespace) wait_before_test(1) config = get_vs_nginx_template_conf( kube_apis.v1, virtual_server_setup.namespace, virtual_server_setup.vs_name, ic_pod_name, ingress_controller_prerequisites.namespace) resp_1 = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) resp_2 = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) new_events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace) assert 'proxy_pass https://' not in config assert_response_codes(resp_1, resp_2, 200, 400) assert_event_count_increased(vs_event_text, initial_count, new_events_vs)
def test_update(self, kube_apis, crd_ingress_controller, virtual_server_setup): wait_before_test(1) text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"Configuration for {text} was added or updated" events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace) initial_count = assert_event_and_get_count(vs_event_text, events_vs) vs_src = f"{TEST_DATA}/virtual-server-redirects/virtual-server-updated.yaml" patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, virtual_server_setup.namespace) wait_and_assert_status_code(301, virtual_server_setup.backend_1_url, virtual_server_setup.vs_host, allow_redirects=False) resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False) assert resp.headers['location'] == "http://demo.nginx.com" wait_and_assert_status_code(302, virtual_server_setup.backend_2_url, virtual_server_setup.vs_host, allow_redirects=False) resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False) assert resp.headers['location'] == "http://demo.nginx.com" vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event_count_increased(vs_event_text, initial_count, vs_events)
def test_flow_for_invalid_vsr(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup): ic_pod_name = get_first_pod_name( kube_apis.v1, ingress_controller_prerequisites.namespace) text_vs = f"{v_s_route_setup.namespace}/{v_s_route_setup.vs_name}" text_vsr_s = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" vs_event_text = f'Configuration for {text_vs} was added or updated with warning(s)' vsr_event_text = f'VirtualServerRoute {text_vsr_s} was rejected with error: ' \ f'spec.subroutes[1].path: Duplicate value: "=/backends/exact-match$request"' vs_src_yaml = f"{TEST_DATA}" \ f"/virtual-server-route-regexp-location/standard/virtual-server-exact.yaml" patch_virtual_server_from_yaml(kube_apis.custom_objects, v_s_route_setup.vs_name, vs_src_yaml, v_s_route_setup.namespace) vsr_src_yaml = f"{TEST_DATA}" \ f"/virtual-server-route-regexp-location/route-multiple-invalid-multiple-regexp-subroutes.yaml" patch_v_s_route_from_yaml(kube_apis.custom_objects, v_s_route_setup.route_m.name, vsr_src_yaml, v_s_route_setup.route_m.namespace) wait_before_test(2) config = get_vs_nginx_template_conf( kube_apis.v1, v_s_route_setup.namespace, v_s_route_setup.vs_name, ic_pod_name, ingress_controller_prerequisites.namespace) ns_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) assert_event(vsr_event_text, ns_events) and assert_event( vs_event_text, ns_events) assert "location =/backends/exact-match$request {" not in config
def test_status_warning( self, kube_apis, crd_ingress_controller, virtual_server_setup, ): """ Test VirtualServer status with conflicting Upstream fields Only for N+ since Slow-start isn """ patch_src = f"{TEST_DATA}/virtual-server-status/warning-state.yaml" patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, patch_src, virtual_server_setup.namespace, ) wait_before_test() response = read_custom_resource( kube_apis.custom_objects, virtual_server_setup.namespace, "virtualservers", virtual_server_setup.vs_name, ) self.patch_valid_vs(kube_apis, virtual_server_setup) assert (response["status"] and response["status"]["reason"] == "AddedOrUpdatedWithWarning" and response["status"]["state"] == "Warning")
def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup): ic_pod_name = get_first_pod_name( kube_apis.v1, ingress_controller_prerequisites.namespace) config_old = get_vs_nginx_template_conf( kube_apis.v1, virtual_server_setup.namespace, virtual_server_setup.vs_name, ic_pod_name, ingress_controller_prerequisites.namespace) vs_src = f"{TEST_DATA}/virtual-server-redirects/virtual-server-invalid-openapi.yaml" try: patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, virtual_server_setup.namespace) except ApiException as ex: assert ex.status == 422 \ and "spec.routes.action.redirect.url" in ex.body \ and "spec.routes.action.redirect.code" in ex.body except Exception as ex: pytest.fail(f"An unexpected exception is raised: {ex}") else: pytest.fail("Expected an exception but there was none") wait_before_test(1) config_new = get_vs_nginx_template_conf( kube_apis.v1, virtual_server_setup.namespace, virtual_server_setup.vs_name, ic_pod_name, ingress_controller_prerequisites.namespace) assert config_old == config_new, "Expected: config doesn't change"
def test_update(self, kube_apis, crd_ingress_controller, virtual_server_setup): wait_before_test(1) text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"Configuration for {text} was added or updated" events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace) initial_count = assert_event_and_get_count(vs_event_text, events_vs) vs_src = f"{TEST_DATA}/virtual-server-canned-responses/virtual-server-updated.yaml" patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, virtual_server_setup.namespace) wait_and_assert_status_code(501, virtual_server_setup.backend_1_url, virtual_server_setup.vs_host) resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) resp_content = resp.content.decode('utf-8') assert resp.headers[ 'content-type'] == 'some/type' and resp_content == "{}" wait_and_assert_status_code(201, virtual_server_setup.backend_2_url, virtual_server_setup.vs_host) resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) resp_content = resp.content.decode('utf-8') assert resp.headers[ 'content-type'] == 'user-type' and resp_content == "line1\nline2" vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event_count_increased(vs_event_text, initial_count, vs_events)
def test_status_invalid( self, kube_apis, crd_ingress_controller, virtual_server_setup, ): """ Test VirtualServer status with a invalid path pattern """ patch_src = f"{TEST_DATA}/virtual-server-status/invalid-state.yaml" patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, patch_src, virtual_server_setup.namespace, ) wait_before_test() response = read_custom_resource( kube_apis.custom_objects, virtual_server_setup.namespace, "virtualservers", virtual_server_setup.vs_name, ) self.patch_valid_vs(kube_apis, virtual_server_setup) assert (response["status"] and response["status"]["reason"] == "Rejected" and response["status"]["state"] == "Invalid")
def test_validation_event_flow(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup): invalid_fields = [ "spec.routes[0].errorPages[0].redirect.url: Invalid value", "spec.routes[0].errorPages[0].redirect.code: Invalid value: 101", "spec.routes[1].errorPages[0].return.body: Invalid value: \"status\"", "spec.routes[1].errorPages[0].return.code: Invalid value: 100", "spec.routes[1].errorPages[0].return.headers[0].value: Invalid value: \"schema\"" ] text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"VirtualServer {text} was rejected with error:" vs_file = f"{TEST_DATA}/virtual-server-error-pages/virtual-server-invalid.yaml" patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_file, virtual_server_setup.namespace) wait_before_test(2) ic_pod_name = get_first_pod_name( kube_apis.v1, ingress_controller_prerequisites.namespace) vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event_starts_with_text_and_contains_errors( vs_event_text, vs_events, invalid_fields) assert_vs_conf_not_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, virtual_server_setup)
def test_tls_redirect_based_on_scheme(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup): patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, f"{TEST_DATA}/virtual-server-tls-redirect/virtual-server-scheme-redirect.yaml", virtual_server_setup.namespace) wait_before_test(1) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) config = get_vs_nginx_template_conf(kube_apis.v1, virtual_server_setup.namespace, virtual_server_setup.vs_name, ic_pod_name, ingress_controller_prerequisites.namespace) assert "proxy_set_header X-Forwarded-Proto $scheme;" in config resp_1 = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False) resp_2 = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False) assert resp_1.status_code == 302, "Expected: a redirect for scheme=http" assert resp_2.status_code == 302, "Expected: a redirect for scheme=http" resp_3 = requests.get(virtual_server_setup.backend_1_url_ssl, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False, verify=False) resp_4 = requests.get(virtual_server_setup.backend_2_url_ssl, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False, verify=False) assert resp_3.status_code == 200, "Expected: no redirect for scheme=https" assert resp_4.status_code == 200, "Expected: no redirect for scheme=https"
def test_when_option_in_config_map_only(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup, restore_configmap, config_map_file, expected_strings, unexpected_strings): text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"Configuration for {text} was added or updated" print(f"Case 3: key specified in ConfigMap, no option in VS") patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, f"{TEST_DATA}/virtual-server-upstream-options/standard/virtual-server.yaml", virtual_server_setup.namespace) config_map_name = ingress_controller_prerequisites.config_map["metadata"]["name"] replace_configmap_from_yaml(kube_apis.v1, config_map_name, ingress_controller_prerequisites.namespace, config_map_file) wait_before_test(1) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) config = get_vs_nginx_template_conf(kube_apis.v1, virtual_server_setup.namespace, virtual_server_setup.vs_name, ic_pod_name, ingress_controller_prerequisites.namespace) resp_1 = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) resp_2 = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event(vs_event_text, vs_events) for _ in expected_strings: assert _ in config for _ in unexpected_strings: assert _ not in config assert_response_codes(resp_1, resp_2)
def test_validation_flow(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup): ic_pod_name = get_first_pod_name( kube_apis.v1, ingress_controller_prerequisites.namespace) initial_events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace) try: patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, f"{TEST_DATA}/virtual-server-upstream-tls/virtual-server-invalid.yaml", virtual_server_setup.namespace) except ApiException as ex: assert ex.status == 422 and "spec.upstreams.tls.enable" in ex.body except Exception as ex: pytest.fail(f"An unexpected exception is raised: {ex}") else: pytest.fail("Expected an exception but there was none") wait_before_test(1) config = get_vs_nginx_template_conf( kube_apis.v1, virtual_server_setup.namespace, virtual_server_setup.vs_name, ic_pod_name, ingress_controller_prerequisites.namespace) resp_1 = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) resp_2 = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) new_events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace) proxy_host = f"vs_{virtual_server_setup.namespace}_{virtual_server_setup.vs_name}" assert f'proxy_pass https://{proxy_host}_backend1' not in config assert f'proxy_pass https://{proxy_host}_backend2' in config assert_response_codes(resp_1, resp_2) assert_no_new_events(initial_events_vs, new_events_vs)
def test_ingress_mtls_policy_cert( self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, certificate, expected_code, expected_text, exception, ): """ Test ingress-mtls with valid and invalid policy """ session = create_sni_session() mtls_secret, tls_secret, pol_name = setup_policy( kube_apis, test_namespace, mtls_sec_valid_src, tls_sec_valid_src, mtls_pol_valid_src, ) print(f"Patch vs with policy: {mtls_pol_valid_src}") patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, mtls_vs_spec_src, virtual_server_setup.namespace, ) wait_before_test() ssl_exception = "" resp = "" try: resp = session.get( virtual_server_setup.backend_1_url_ssl, cert=certificate, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False, verify=False, ) except requests.exceptions.SSLError as e: print(f"SSL certificate exception: {e}") ssl_exception = str(e) resp = mock.Mock() resp.status_code = "None" resp.text = "None" teardown_policy(kube_apis, test_namespace, tls_secret, pol_name, mtls_secret) patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, std_vs_src, virtual_server_setup.namespace, ) assert (resp.status_code == expected_code and expected_text in resp.text and exception in ssl_exception)
def test_ingress_mtls_policy_vsr( self, kube_apis, crd_ingress_controller, v_s_route_app_setup, v_s_route_setup, test_namespace, ): """ Test ingress-mtls in vsr subroute context. """ mtls_secret, tls_secret, pol_name = setup_policy( kube_apis, v_s_route_setup.route_m.namespace, mtls_sec_valid_src, tls_sec_valid_src, mtls_pol_valid_src, ) print( f"Patch vsr with policy: {mtls_vsr_subroute_src} and vs with tls secret: {tls_secret}" ) patch_virtual_server_from_yaml( kube_apis.custom_objects, v_s_route_setup.vs_name, mtls_vs_vsr_src, v_s_route_setup.namespace, ) patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, mtls_vsr_subroute_src, v_s_route_setup.route_m.namespace, ) wait_before_test() vsr_res = read_vsr( kube_apis.custom_objects, v_s_route_setup.route_m.namespace, v_s_route_setup.route_m.name, ) teardown_policy( kube_apis, v_s_route_setup.route_m.namespace, tls_secret, pol_name, mtls_secret ) patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, std_vsr_src, v_s_route_setup.route_m.namespace, ) patch_virtual_server_from_yaml( kube_apis.custom_objects, v_s_route_setup.vs_name, std_vs_vsr_src, v_s_route_setup.namespace, ) assert ( vsr_res["status"]["state"] == "Warning" and f"{pol_name} is not allowed in the subroute context" in vsr_res["status"]["message"] )
def test_overide_vs_vsr( self, kube_apis, crd_ingress_controller, v_s_route_app_setup, test_namespace, config_setup, v_s_route_setup, src, ): """ Test if vsr subroute policy overrides vs spec policy and vsr subroute policy overrides vs route policy """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" print(f"Create deny policy") deny_pol_name = create_policy_from_yaml( kube_apis.custom_objects, deny_pol_src, v_s_route_setup.route_m.namespace) print(f"Create allow policy") allow_pol_name = create_policy_from_yaml( kube_apis.custom_objects, allow_pol_src, v_s_route_setup.route_m.namespace) patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, allow_vsr_src, v_s_route_setup.route_m.namespace, ) # patch vs with blocking policy patch_virtual_server_from_yaml(kube_apis.custom_objects, v_s_route_setup.vs_name, src, v_s_route_setup.namespace) wait_before_test() print(f"\nUse IP listed in deny block: 10.0.0.1") resp = requests.get( f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={ "host": v_s_route_setup.vs_host, "X-Real-IP": "10.0.0.1" }, ) print(f"Response: {resp.status_code}\n{resp.text}") delete_policy(kube_apis.custom_objects, deny_pol_name, v_s_route_setup.route_m.namespace) delete_policy(kube_apis.custom_objects, allow_pol_name, v_s_route_setup.route_m.namespace) self.restore_default_vsr(kube_apis, v_s_route_setup) patch_virtual_server_from_yaml(kube_apis.custom_objects, v_s_route_setup.vs_name, std_vs_src, v_s_route_setup.namespace) wait_before_test() assert resp.status_code == 200 and "Server address:" in resp.text
def test_ingress_mtls_policy( self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, policy_src, vs_src, expected_code, expected_text, vs_message, vs_state, ): """ Test ingress-mtls with valid and invalid policy in vs spec and route contexts. """ session = create_sni_session() mtls_secret, tls_secret, pol_name = setup_policy( kube_apis, test_namespace, mtls_sec_valid_src, tls_sec_valid_src, policy_src, ) print(f"Patch vs with policy: {policy_src}") patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, virtual_server_setup.namespace, ) wait_before_test() resp = session.get( virtual_server_setup.backend_1_url_ssl, cert=(crt, key), headers={"host": virtual_server_setup.vs_host}, allow_redirects=False, verify=False, ) vs_res = read_vs(kube_apis.custom_objects, test_namespace, virtual_server_setup.vs_name) teardown_policy(kube_apis, test_namespace, tls_secret, pol_name, mtls_secret) patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, std_vs_src, virtual_server_setup.namespace, ) assert (resp.status_code == expected_code and expected_text in resp.text and vs_message in vs_res["status"]["message"] and vs_res["status"]["state"] == vs_state)
def patch_valid_vs(self, kube_apis, virtual_server_setup) -> None: """ Function to revert vs deployment to valid state """ patch_src = f"{TEST_DATA}/virtual-server-status/standard/virtual-server.yaml" patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, patch_src, virtual_server_setup.namespace, )
def patch_standard_vs(self, kube_apis, virtual_server_setup) -> None: """ Deploy standard virtual-server """ patch_src = f"{TEST_DATA}/virtual-server-rewrites/standard/virtual-server.yaml" patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, patch_src, virtual_server_setup.namespace, )
def test_flow_with_variable(self, kube_apis, crd_ingress_controller, virtual_server_setup): patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, f"{TEST_DATA}/virtual-server-advanced-routing/virtual-server-variable.yaml", virtual_server_setup.namespace) wait_before_test(1) resp_1 = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) resp_2 = requests.post(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) resp_3 = requests.put(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) execute_assertions(resp_1, resp_2, resp_3)
def test_tls_redirect_without_tls_termination(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup): source_yaml = f"{TEST_DATA}/virtual-server-tls-redirect/virtual-server-no-tls-termination-redirect.yaml" patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, source_yaml, virtual_server_setup.namespace) wait_before_test(1) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) config = get_vs_nginx_template_conf(kube_apis.v1, virtual_server_setup.namespace, virtual_server_setup.vs_name, ic_pod_name, ingress_controller_prerequisites.namespace) assert "proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;" in config resp_1 = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, allow_redirects=False) resp_2 = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, allow_redirects=False) assert resp_1.status_code == 308, "Expected: a redirect for x-forwarded-proto=http" assert resp_2.status_code == 308, "Expected: a redirect for x-forwarded-proto=http" resp_3 = requests.get(virtual_server_setup.backend_1_url_ssl, headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, allow_redirects=False, verify=False) resp_4 = requests.get(virtual_server_setup.backend_2_url_ssl, headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, allow_redirects=False, verify=False) assert resp_3.status_code == 404, "Expected: 404 for x-forwarded-proto=http and scheme=https" assert resp_4.status_code == 404, "Expected: 404 for x-forwarded-proto=http and scheme=https" resp_5 = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, allow_redirects=False) resp_6 = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, allow_redirects=False) assert resp_5.status_code == 200, "Expected: no redirect for x-forwarded-proto=https" assert resp_6.status_code == 200, "Expected: no redirect for x-forwarded-proto=https" resp_7 = requests.get(virtual_server_setup.backend_1_url_ssl, headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, allow_redirects=False, verify=False) resp_8 = requests.get(virtual_server_setup.backend_2_url_ssl, headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, allow_redirects=False, verify=False) assert resp_7.status_code == 404, "Expected: no redirect for x-forwarded-proto=https and scheme=https" assert resp_8.status_code == 404, "Expected: no redirect for x-forwarded-proto=https and scheme=https"
def test_config_error_page_warning(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, backend_setup, virtual_server_setup): text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_warning_text = f"Configuration for {text} was added or updated ; with warning(s): " patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, f"{TEST_DATA}/virtual-server-grpc/virtual-server-error-page.yaml", virtual_server_setup.namespace) wait_before_test(5) events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event(vs_event_warning_text, events) self.patch_valid_vs(kube_apis, virtual_server_setup) wait_before_test()
def test_route_override_spec( self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, config_setup, ): """ Test allow policy specified under routes overrides block in spec """ resp = requests.get( virtual_server_setup.backend_1_url, headers={ "host": virtual_server_setup.vs_host, "X-Real-IP": "10.0.0.1" }, ) print(f"Response: {resp.status_code}\n{resp.text}") assert resp.status_code == 200 print(f"Create deny policy") deny_pol_name = create_policy_from_yaml(kube_apis.custom_objects, deny_pol_src, test_namespace) print(f"Create allow policy") allow_pol_name = create_policy_from_yaml(kube_apis.custom_objects, allow_pol_src, test_namespace) patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, override_vs_spec_route_src, virtual_server_setup.namespace, ) wait_before_test() print(f"Use IP listed in both deny and allow policies: 10.0.0.1") resp = requests.get( virtual_server_setup.backend_1_url, headers={ "host": virtual_server_setup.vs_host, "X-Real-IP": "10.0.0.1" }, ) print(f"Response: {resp.status_code}\n{resp.text}") self.restore_default_vs(kube_apis, virtual_server_setup) delete_policy(kube_apis.custom_objects, deny_pol_name, test_namespace) delete_policy(kube_apis.custom_objects, allow_pol_name, test_namespace) assert resp.status_code == 200 and "Server address:" in resp.text