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'Ignored by VirtualServer {text_vs}: spec.subroutes: Invalid value: "subroutes": ' \ f'must have only one subroute if regex match or exact match are being used' vsr_event_text = f'VirtualServerRoute {text_vsr_s} is invalid and was rejected: ' \ 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_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_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_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, v_s_route_setup.namespace, v_s_route_setup.vs_name, ic_pod_name, ingress_controller_prerequisites.namespace) vsr_src = f"{TEST_DATA}/virtual-server-route-error-pages/route-multiple-invalid-openapi.yaml" try: patch_v_s_route_from_yaml(kube_apis.custom_objects, v_s_route_setup.route_m.name, vsr_src, v_s_route_setup.route_m.namespace) except ApiException as ex: assert ex.status == 422 \ and "spec.subroutes.errorPages.codes: Invalid value" in ex.body \ and "spec.subroutes.errorPages.redirect.code: Invalid value" in ex.body \ and "spec.subroutes.errorPages.redirect.url: Invalid value" in ex.body \ and "spec.subroutes.errorPages.return.code: Invalid value" in ex.body \ and "spec.subroutes.errorPages.return.type: Invalid value" in ex.body \ and "spec.subroutes.errorPages.return.body: Invalid value" in ex.body \ and "spec.subroutes.errorPages.return.headers.name: Invalid value" in ex.body \ and "spec.subroutes.errorPages.return.headers.value: Invalid value" 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, v_s_route_setup.namespace, v_s_route_setup.vs_name, ic_pod_name, ingress_controller_prerequisites.namespace) assert config_old == config_new, "Expected: config doesn't change"
def test_flow_with_complex_conditions(self, kube_apis, crd_ingress_controller, vsr_adv_routing_setup): patch_v_s_route_from_yaml( kube_apis.custom_objects, vsr_adv_routing_setup.route.name, f"{TEST_DATA}/virtual-server-route-advanced-routing/virtual-server-route-complex.yaml", vsr_adv_routing_setup.namespace) wait_before_test(1) resp_1 = requests.get(vsr_adv_routing_setup.backends_url + "?arg1=v1", headers={ "host": vsr_adv_routing_setup.vs_host, "x-version": "future" }, cookies={"user": "******"}) resp_2 = requests.post(vsr_adv_routing_setup.backends_url + "?arg1=v2", headers={ "host": vsr_adv_routing_setup.vs_host, "x-version": "deprecated" }, cookies={"user": "******"}) resp_3 = requests.get(vsr_adv_routing_setup.backends_url + "?arg1=v2", headers={ "host": vsr_adv_routing_setup.vs_host, "x-version": "deprecated" }, cookies={"user": "******"}) execute_assertions(resp_1, resp_2, resp_3)
def test_make_existing_vsr_invalid(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup, route_yaml): ic_pod_name = get_first_pod_name( kube_apis.v1, ingress_controller_prerequisites.namespace) patch_v_s_route_from_yaml(kube_apis.custom_objects, v_s_route_setup.route_s.name, route_yaml, v_s_route_setup.route_s.namespace) wait_before_test(1) new_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) new_vs_events = get_events(kube_apis.v1, v_s_route_setup.namespace) new_vsr_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) assert_locations_not_in_config(new_config, v_s_route_setup.route_s.paths) text = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" assert_event_and_count( f"Configuration for {v_s_route_setup.namespace}/{v_s_route_setup.vs_name} was added or updated with warning(s)", 1, new_vs_events) if route_yaml == f"{TEST_DATA}/virtual-server-route/route-single-invalid-host.yaml": assert_event_and_count( f"VirtualServer is invalid or doesn't exist", 1, new_vsr_events) else: assert_event_and_count( f"VirtualServerRoute {text} was rejected with error", 1, new_vsr_events)
def test_regex_rewrite(self, kube_apis, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup): """ Test VirtualServerRoute URI rewrite using regex """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" patch_src_m = f"{TEST_DATA}/virtual-server-route-rewrites/route-multiple-prefix-regex.yaml" patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, patch_src_m, v_s_route_setup.route_m.namespace, ) wait_before_test() resp1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", headers={"host": v_s_route_setup.vs_host}) resp2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}/", headers={"host": v_s_route_setup.vs_host}) resp3 = requests.get( f"{req_url}{v_s_route_setup.route_m.paths[1]}/abc", headers={"host": v_s_route_setup.vs_host}) self.patch_standard_vsr(kube_apis, v_s_route_setup) assert ("URI: /\nRequest" in resp1.text and "URI: /\nRequest" in resp2.text and "URI: /abc\nRequest" in resp3.text)
def test_rl_policy_invalid_vsr( self, kube_apis, crd_ingress_controller, v_s_route_app_setup, v_s_route_setup, test_namespace, src, ): """ Test if using an invalid policy in vsr:subroute results in 500 """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" print(f"Create rl policy") pol_name = create_policy_from_yaml(kube_apis.custom_objects, rl_pol_invalid_src, v_s_route_setup.route_m.namespace) print(f"Patch vsr with policy: {src}") patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, src, v_s_route_setup.route_m.namespace, ) wait_before_test() resp = requests.get( f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}, ) print(resp.status_code) delete_policy(kube_apis.custom_objects, pol_name, v_s_route_setup.route_m.namespace) self.restore_default_vsr(kube_apis, v_s_route_setup) assert resp.status_code == 500
def test_update(self, kube_apis, crd_ingress_controller, v_s_route_setup): req_host = f"{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" req_url_1 = f"http://{req_host}{v_s_route_setup.route_m.paths[0]}" req_url_2 = f"http://{req_host}{v_s_route_setup.route_m.paths[1]}" wait_before_test(1) vs_name = f"{v_s_route_setup.namespace}/{v_s_route_setup.vs_name}" vsr_name = f"{v_s_route_setup.namespace}/{v_s_route_setup.route_m.name}" vsr_event_text = f"Configuration for {vsr_name} was added or updated" vs_event_text = f"Configuration for {vs_name} was added or updated" events_ns = get_events(kube_apis.v1, v_s_route_setup.namespace) initial_count_vs = assert_event_and_get_count(vs_event_text, events_ns) initial_count_vsr = assert_event_and_get_count(vsr_event_text, events_ns) vsr_src = f"{TEST_DATA}/virtual-server-route-canned-responses/route-multiple-updated.yaml" patch_v_s_route_from_yaml(kube_apis.custom_objects, v_s_route_setup.route_m.name, vsr_src, v_s_route_setup.namespace) wait_and_assert_status_code(501, req_url_1, v_s_route_setup.vs_host) resp = requests.get(req_url_1, headers={"host": v_s_route_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, req_url_2, v_s_route_setup.vs_host) resp = requests.get(req_url_2, headers={"host": v_s_route_setup.vs_host}) resp_content = resp.content.decode('utf-8') assert resp.headers['content-type'] == 'user-type' and resp_content == "line1\nline2" new_events_ns = get_events(kube_apis.v1, v_s_route_setup.namespace) assert_event_count_increased(vs_event_text, initial_count_vs, new_events_ns) assert_event_count_increased(vsr_event_text, initial_count_vsr, new_events_ns)
def test_jwt_policy_override( self, kube_apis, crd_ingress_controller, v_s_route_app_setup, v_s_route_setup, test_namespace, ): """ Test if first reference to a policy in the same context(subroute) takes precedence, i.e. in this case, policy without $httptoken over policy with $httptoken. """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" secret, pol_name_1, pol_name_2, headers = self.setup_multiple_policies( kube_apis, v_s_route_setup.route_m.namespace, valid_token, jwk_sec_valid_src, jwt_pol_valid_src, jwt_pol_multi_src, v_s_route_setup.vs_host, ) print(f"Patch vsr with policies: {jwt_pol_valid_src}") patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, jwt_vsr_override_src, v_s_route_setup.route_m.namespace, ) wait_before_test() resp = requests.get( f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers, ) print(resp.status_code) crd_info = read_crd( kube_apis.custom_objects, v_s_route_setup.route_m.namespace, "virtualserverroutes", v_s_route_setup.route_m.name, ) delete_policy(kube_apis.custom_objects, pol_name_1, v_s_route_setup.route_m.namespace) delete_policy(kube_apis.custom_objects, pol_name_2, v_s_route_setup.route_m.namespace) delete_secret(kube_apis.v1, secret, v_s_route_setup.route_m.namespace) 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, ) assert resp.status_code == 401 assert f"Authorization Required" in resp.text assert (f"Multiple jwt policies in the same context is not valid." in crd_info["status"]["message"])
def test_make_existing_vsr_invalid(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup, route_yaml): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) patch_v_s_route_from_yaml(kube_apis.custom_objects, v_s_route_setup.route_s.name, route_yaml, v_s_route_setup.route_s.namespace) wait_before_test(1) new_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) new_vs_events = get_events(kube_apis.v1, v_s_route_setup.namespace) new_vsr_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) assert_locations_not_in_config(new_config, v_s_route_setup.route_s.paths) text = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" assert_event_and_count(f"Ignored VirtualServerRoute {text}", 1, new_vs_events) assert_event_and_count(f"Ignored by VirtualServer {v_s_route_setup.namespace}/{v_s_route_setup.vs_name}", 1, new_vsr_events)
def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_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, v_s_route_setup.namespace, v_s_route_setup.vs_name, ic_pod_name, ingress_controller_prerequisites.namespace) route_yaml = f"{TEST_DATA}/virtual-server-route/route-single-invalid-openapi.yaml" try: patch_v_s_route_from_yaml(kube_apis.custom_objects, v_s_route_setup.route_s.name, route_yaml, v_s_route_setup.route_s.namespace) except ApiException as ex: assert ex.status == 422 and "spec.subroutes.action.pass" 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, v_s_route_setup.namespace, v_s_route_setup.vs_name, ic_pod_name, ingress_controller_prerequisites.namespace) assert config_old == config_new, "Expected: config doesn't change"
def test_virtual_server_after_update(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup): req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, f"{TEST_DATA}/virtual-server-route-error-pages/route-multiple-updated.yaml", v_s_route_setup.route_m.namespace) wait_and_assert_status_code( 301, f"{req_url}{v_s_route_setup.route_m.paths[0]}", v_s_route_setup.vs_host, allow_redirects=False) resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={ "host": v_s_route_setup.vs_host, "x-forwarded-proto": "http" }, allow_redirects=False) assert f'http://{v_s_route_setup.vs_host}/error_http.html' in resp.next.url wait_and_assert_status_code( 502, f"{req_url}{v_s_route_setup.route_m.paths[1]}", v_s_route_setup.vs_host, allow_redirects=False) resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", headers={"host": v_s_route_setup.vs_host}) resp_content = resp.content.decode('utf-8') assert resp_content == 'Hello World!\n'
def test_deny_policy_vsr( self, kube_apis, crd_ingress_controller, v_s_route_app_setup, test_namespace, config_setup, v_s_route_setup, ): """ Test if ip (10.0.0.1) block-listing is working (policy specified in vsr subroute): default(no policy) -> deny """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" 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}") assert resp.status_code == 200 print(f"Create deny policy") pol_name = create_policy_from_yaml(kube_apis.custom_objects, deny_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, deny_vsr_src, v_s_route_setup.route_m.namespace, ) wait_before_test() print(f"\nUse IP listed in deny block: 10.0.0.1") resp1 = 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: {resp1.status_code}\n{resp1.text}") print(f"\nUse IP not listed in deny block: 10.0.0.2") resp2 = 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.2" }, ) print(f"Response: {resp2.status_code}\n{resp2.text}") delete_policy(kube_apis.custom_objects, pol_name, v_s_route_setup.route_m.namespace) self.restore_default_vsr(kube_apis, v_s_route_setup) assert (resp1.status_code == 403 and "403 Forbidden" in resp1.text and resp2.status_code == 200 and "Server address:" in resp2.text)
def test_invalid_value_rejection(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup, v_s_route_secure_app_setup): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) initial_events_ns_m = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) initial_events_ns_s = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) patch_v_s_route_from_yaml(kube_apis.custom_objects, v_s_route_setup.route_s.name, f"{TEST_DATA}/virtual-server-route-upstream-tls/route-single-invalid.yaml", v_s_route_setup.route_s.namespace) wait_before_test(1) 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) req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) new_events_ns_m = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) new_events_ns_s = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) vs_line = f"vs_{v_s_route_setup.namespace}_{v_s_route_setup.vs_name}" proxy_host_s = f"{vs_line}_vsr_{v_s_route_setup.route_s.namespace}_{v_s_route_setup.route_s.name}" proxy_host_m = f"{vs_line}_vsr_{v_s_route_setup.route_m.namespace}_{v_s_route_setup.route_m.name}" assert f'proxy_pass https://{proxy_host_m}' not in config assert f'proxy_pass https://{proxy_host_s}' in config assert_response_codes(resp_1, resp_2) assert_no_new_events(initial_events_ns_m, new_events_ns_m) assert_no_new_events(initial_events_ns_s, new_events_ns_s)
def test_event_message_and_config(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup): invalid_fields_s = [ "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" ] invalid_fields_m = [ "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_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" vsr_s_event_text = f"VirtualServerRoute {text_s} is invalid and was rejected: " vsr_m_event_text = f"VirtualServerRoute {text_m} is invalid and was rejected: " patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_s.name, f"{TEST_DATA}/virtual-server-route-upstream-options/route-single-invalid-keys.yaml", v_s_route_setup.route_s.namespace) patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple-invalid-keys.yaml", v_s_route_setup.route_m.namespace) wait_before_test(2) ic_pod_name = get_first_pod_name( kube_apis.v1, ingress_controller_prerequisites.namespace) 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) vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) assert_event_starts_with_text_and_contains_errors( vsr_s_event_text, vsr_s_events, invalid_fields_s) assert_event_starts_with_text_and_contains_errors( vsr_m_event_text, vsr_m_events, invalid_fields_m) assert "upstream" not in config
def test_jwt_policy_delete_policy( self, kube_apis, crd_ingress_controller, v_s_route_app_setup, v_s_route_setup, test_namespace, ): """ Test if requests result in 500 when policy is deleted """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" secret, pol_name, headers = self.setup_single_policy( kube_apis, v_s_route_setup.route_m.namespace, valid_token, jwk_sec_valid_src, jwt_pol_valid_src, v_s_route_setup.vs_host, ) print(f"Patch vsr with policy: {jwt_pol_valid_src}") patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, jwt_vsr_valid_src, v_s_route_setup.route_m.namespace, ) wait_before_test() resp1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) print(resp1.status_code) delete_policy(kube_apis.custom_objects, pol_name, v_s_route_setup.route_m.namespace) resp2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) print(resp2.status_code) crd_info = read_crd( kube_apis.custom_objects, v_s_route_setup.route_m.namespace, "virtualserverroutes", v_s_route_setup.route_m.name, ) delete_secret(kube_apis.v1, secret, v_s_route_setup.route_m.namespace) 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, ) assert resp1.status_code == 200 assert f"Request ID:" in resp1.text assert crd_info["status"]["state"] == "Warning" assert ( f"{v_s_route_setup.route_m.namespace}/{pol_name} is missing" in crd_info["status"]["message"] ) assert resp2.status_code == 500 assert f"Internal Server Error" in resp2.text
def test_jwt_policy_token( self, kube_apis, crd_ingress_controller, v_s_route_app_setup, v_s_route_setup, test_namespace, token, ): """ Test jwt-policy with no token, valid token and invalid token """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" secret, pol_name, headers = self.setup_single_policy( kube_apis, v_s_route_setup.route_m.namespace, token, jwk_sec_valid_src, jwt_pol_valid_src, v_s_route_setup.vs_host, ) print(f"Patch vsr with policy: {jwt_vsr_valid_src}") patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, jwt_vsr_valid_src, v_s_route_setup.route_m.namespace, ) wait_before_test() resp1 = requests.get( f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}, ) print(resp1.status_code) resp2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers) print(resp2.status_code) delete_policy(kube_apis.custom_objects, pol_name, v_s_route_setup.route_m.namespace) delete_secret(kube_apis.v1, secret, v_s_route_setup.route_m.namespace) 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, ) assert resp1.status_code == 401 assert f"401 Authorization Required" in resp1.text if token == valid_token: assert resp2.status_code == 200 assert f"Request ID:" in resp2.text else: assert resp2.status_code == 401 assert f"Authorization Required" in resp2.text
def test_jwt_policy_override_vs_vsr( self, kube_apis, crd_ingress_controller, v_s_route_app_setup, v_s_route_setup, test_namespace, vs_src, ): """ Test if policy specified in vsr:subroute (policy without $httptoken) takes preference over policy specified in: 1. vs:spec (policy with $httptoken) 2. vs:route (policy with $httptoken) """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" secret, pol_name_1, pol_name_2, headers = self.setup_multiple_policies( kube_apis, v_s_route_setup.route_m.namespace, valid_token, jwk_sec_valid_src, jwt_pol_valid_src, jwt_pol_multi_src, v_s_route_setup.vs_host, ) print(f"Patch vsr with policies: {jwt_pol_valid_src}") patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, jwt_vsr_valid_multi_src, v_s_route_setup.route_m.namespace, ) patch_virtual_server_from_yaml( kube_apis.custom_objects, v_s_route_setup.vs_name, vs_src, v_s_route_setup.namespace, ) wait_before_test() resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) print(resp.status_code) delete_policy(kube_apis.custom_objects, pol_name_1, v_s_route_setup.route_m.namespace) delete_policy(kube_apis.custom_objects, pol_name_2, v_s_route_setup.route_m.namespace) delete_secret(kube_apis.v1, secret, v_s_route_setup.route_m.namespace) 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_src, v_s_route_setup.namespace ) assert resp.status_code == 401 assert f"Authorization Required" in resp.text
def test_invalid_policy_vsr( self, kube_apis, crd_ingress_controller, v_s_route_app_setup, test_namespace, config_setup, v_s_route_setup, ): """ Test if applying invalid-policy results in 500. """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" 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}") assert resp.status_code == 200 print(f"Create invalid policy") pol_name = create_policy_from_yaml(kube_apis.custom_objects, invalid_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, invalid_vsr_src, v_s_route_setup.route_m.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}") vsr_info = read_crd( kube_apis.custom_objects, v_s_route_setup.route_m.namespace, "virtualserverroutes", v_s_route_setup.route_m.name, ) delete_policy(kube_apis.custom_objects, pol_name, v_s_route_setup.route_m.namespace) self.restore_default_vsr(kube_apis, v_s_route_setup) assert resp.status_code == 500 and "500 Internal Server Error" in resp.text assert (vsr_info["status"]["state"] == "Warning" and vsr_info["status"]["reason"] == "AddedOrUpdatedWithWarning")
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_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_flow_with_variable(self, kube_apis, crd_ingress_controller, vsr_adv_routing_setup): patch_v_s_route_from_yaml(kube_apis.custom_objects, vsr_adv_routing_setup.route.name, f"{TEST_DATA}/virtual-server-route-advanced-routing/virtual-server-route-variable.yaml", vsr_adv_routing_setup.namespace) wait_before_test(1) resp_1 = requests.get(vsr_adv_routing_setup.backends_url, headers={"host": vsr_adv_routing_setup.vs_host}) resp_2 = requests.post(vsr_adv_routing_setup.backends_url, headers={"host": vsr_adv_routing_setup.vs_host}) resp_3 = requests.put(vsr_adv_routing_setup.backends_url, headers={"host": vsr_adv_routing_setup.vs_host}) execute_assertions(resp_1, resp_2, resp_3)
def test_ap_waf_policy_block( self, kube_apis, crd_ingress_controller_with_ap, v_s_route_setup, appprotect_setup, test_namespace, ap_enable, ): """ Test if WAF policy is working with VSR deployments """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" print(f"Create waf policy") create_ap_waf_policy_from_yaml( kube_apis.custom_objects, waf_pol_dataguard_src, v_s_route_setup.route_m.namespace, test_namespace, ap_enable, ap_enable, ap_pol_name, log_name, "syslog:server=127.0.0.1:514", ) wait_before_test() print(f"Patch vsr with policy: {waf_subroute_vsr_src}") patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, waf_subroute_vsr_src, v_s_route_setup.route_m.namespace, ) wait_before_test() ap_crd_info = read_ap_custom_resource(kube_apis.custom_objects, test_namespace, "appolicies", ap_policy_uds) assert_ap_crd_info(ap_crd_info, ap_policy_uds) wait_before_test(120) response = requests.get( f"{req_url}{v_s_route_setup.route_m.paths[0]}+'</script>'", headers={"host": v_s_route_setup.vs_host}, ) print(response.text) delete_policy(kube_apis.custom_objects, "waf-policy", v_s_route_setup.route_m.namespace) self.restore_default_vsr(kube_apis, v_s_route_setup) if ap_enable == True: assert_invalid_responses(response) elif ap_enable == False: assert_valid_responses(response) else: pytest.fail(f"Invalid arguments")
def test_splits_and_matches(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup, v_s_r_data): req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" patch_v_s_route_from_yaml(kube_apis.custom_objects, v_s_route_setup.route_m.name, f"{TEST_DATA}/virtual-server-route-error-pages/{v_s_r_data['src']}", v_s_route_setup.route_m.namespace) wait_and_assert_status_code(v_s_r_data["expected_code"], f"{req_url}{v_s_route_setup.route_m.paths[0]}", v_s_route_setup.vs_host, allow_redirects=False) resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}, allow_redirects=False) assert f'http://{v_s_route_setup.vs_host}/error.html' in resp.next.url
def restore_default_vsr(self, kube_apis, v_s_route_setup) -> None: """ Function to revert vsr deployments to valid state """ patch_src_m = f"{TEST_DATA}/virtual-server-route/route-multiple.yaml" patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, patch_src_m, v_s_route_setup.route_m.namespace, ) wait_before_test()
def test_rl_policy_1rs_vsr( self, kube_apis, crd_ingress_controller, v_s_route_app_setup, v_s_route_setup, test_namespace, src, ): """ Test if rate-limiting policy is working with ~1 rps in vsr:subroute """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" print(f"Create rl policy") pol_name = create_policy_from_yaml( kube_apis.custom_objects, rl_pol_pri_src, v_s_route_setup.route_m.namespace ) print(f"Patch vsr with policy: {src}") patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, src, v_s_route_setup.route_m.namespace, ) wait_before_test() policy_info = read_crd( kube_apis.custom_objects, v_s_route_setup.route_m.namespace, "policies", pol_name ) occur = [] t_end = time.perf_counter() + 1 resp = requests.get( f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}, ) print(resp.status_code) assert resp.status_code == 200 while time.perf_counter() < t_end: resp = requests.get( f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}, ) occur.append(resp.status_code) delete_policy(kube_apis.custom_objects, pol_name, v_s_route_setup.route_m.namespace) self.restore_default_vsr(kube_apis, v_s_route_setup) assert ( policy_info["status"] and policy_info["status"]["reason"] == "AddedOrUpdated" and policy_info["status"]["state"] == "Valid" ) assert occur.count(200) <= 1
def test_validation_flow(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup): invalid_fields_s = [ "upstreams[0].healthCheck.path", "upstreams[0].healthCheck.interval", "upstreams[0].healthCheck.jitter", "upstreams[0].healthCheck.fails", "upstreams[0].healthCheck.passes", "upstreams[0].healthCheck.connect-timeout", "upstreams[0].healthCheck.read-timeout", "upstreams[0].healthCheck.send-timeout", "upstreams[0].healthCheck.headers[0].name", "upstreams[0].healthCheck.headers[0].value", "upstreams[0].healthCheck.statusMatch", "upstreams[0].slow-start" ] invalid_fields_m = [ "upstreams[0].healthCheck.path", "upstreams[0].healthCheck.interval", "upstreams[0].healthCheck.jitter", "upstreams[0].healthCheck.fails", "upstreams[0].healthCheck.passes", "upstreams[0].healthCheck.connect-timeout", "upstreams[0].healthCheck.read-timeout", "upstreams[0].healthCheck.send-timeout", "upstreams[0].healthCheck.headers[0].name", "upstreams[0].healthCheck.headers[0].value", "upstreams[0].healthCheck.statusMatch", "upstreams[0].slow-start", "upstreams[1].healthCheck.path", "upstreams[1].healthCheck.interval", "upstreams[1].healthCheck.jitter", "upstreams[1].healthCheck.fails", "upstreams[1].healthCheck.passes", "upstreams[1].healthCheck.connect-timeout", "upstreams[1].healthCheck.read-timeout", "upstreams[1].healthCheck.send-timeout", "upstreams[1].healthCheck.headers[0].name", "upstreams[0].healthCheck.headers[0].value", "upstreams[1].healthCheck.statusMatch", "upstreams[1].slow-start" ] text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" vsr_s_event_text = f"VirtualServerRoute {text_s} is invalid and was rejected: " vsr_m_event_text = f"VirtualServerRoute {text_m} is invalid and was rejected: " patch_v_s_route_from_yaml(kube_apis.custom_objects, v_s_route_setup.route_s.name, f"{TEST_DATA}/virtual-server-route-upstream-options/plus-route-s-invalid-keys.yaml", v_s_route_setup.route_s.namespace) patch_v_s_route_from_yaml(kube_apis.custom_objects, v_s_route_setup.route_m.name, f"{TEST_DATA}/virtual-server-route-upstream-options/plus-route-m-invalid-keys.yaml", v_s_route_setup.route_m.namespace) wait_before_test(2) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) 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) vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) assert_event_starts_with_text_and_contains_errors(vsr_s_event_text, vsr_s_events, invalid_fields_s) assert_event_starts_with_text_and_contains_errors(vsr_m_event_text, vsr_m_events, invalid_fields_m) assert "upstream" not in config
def test_status_invalid_prefix( self, kube_apis, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup ): """ Test VirtualServerRoute status with a invalid path /prefix in vsr yaml i.e. referring to non-existing path """ patch_src_m = f"{TEST_DATA}/virtual-server-route-status/route-multiple-invalid-prefixed-path.yaml" patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, patch_src_m, v_s_route_setup.route_m.namespace, ) wait_before_test() patch_src_s = f"{TEST_DATA}/virtual-server-route-status/route-single-invalid-prefixed-path.yaml" patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_s.name, patch_src_s, v_s_route_setup.route_s.namespace, ) wait_before_test() response_m = read_crd( kube_apis.custom_objects, v_s_route_setup.route_m.namespace, "virtualserverroutes", v_s_route_setup.route_m.name, ) response_s = read_crd( kube_apis.custom_objects, v_s_route_setup.route_s.namespace, "virtualserverroutes", v_s_route_setup.route_s.name, ) self.patch_valid_vsr(kube_apis, v_s_route_setup) assert ( response_m["status"] and response_m["status"]["reason"] == "AddedOrUpdated" and response_m["status"]["referencedBy"] and response_m["status"]["state"] == "Valid" ) assert ( response_s["status"] and response_s["status"]["reason"] == "Ignored" and not response_s["status"]["referencedBy"] and response_s["status"]["state"] == "Warning" )
def test_rl_policy_override_vsr( self, kube_apis, crd_ingress_controller, v_s_route_app_setup, v_s_route_setup, test_namespace, src, ): """ Test if rate-limiting policy with lower rps is used when multiple policies are listed in vsr:subroute And test if the order of policies in vsr:subroute has no effect """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" print(f"Create rl policy: 1rps") pol_name_pri = create_policy_from_yaml( kube_apis.custom_objects, rl_pol_pri_src, v_s_route_setup.route_m.namespace) print(f"Create rl policy: 10rps") pol_name_sec = create_policy_from_yaml( kube_apis.custom_objects, rl_pol_sec_src, v_s_route_setup.route_m.namespace) print(f"Patch vsr with policy: {src}") patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, src, v_s_route_setup.route_m.namespace, ) wait_before_test() occur = [] t_end = time.perf_counter() + 1 resp = requests.get( f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}, ) print(resp.status_code) assert resp.status_code == 200 while time.perf_counter() < t_end: resp = requests.get( f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}, ) occur.append(resp.status_code) delete_policy(kube_apis.custom_objects, pol_name_pri, v_s_route_setup.route_m.namespace) delete_policy(kube_apis.custom_objects, pol_name_sec, v_s_route_setup.route_m.namespace) self.restore_default_vsr(kube_apis, v_s_route_setup) assert occur.count(200) <= 1
def test_validation_flow(self, kube_apis, crd_ingress_controller, v_s_route_setup): req_host = f"{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" req_url = f"http://{req_host}{v_s_route_setup.route_s.paths[0]}" text = f"{v_s_route_setup.namespace}/{v_s_route_setup.route_m.name}" event_text = f"VirtualServerRoute {text} is invalid and was rejected: " \ f"spec.subroutes[0].action.return.body: Required value" vsr_src = f"{TEST_DATA}/virtual-server-route-canned-responses/route-multiple-invalid.yaml" patch_v_s_route_from_yaml(kube_apis.custom_objects, v_s_route_setup.route_m.name, vsr_src, v_s_route_setup.namespace) wait_before_test(1) wait_and_assert_status_code(404, req_url, v_s_route_setup.vs_host) events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) assert_event(event_text, events)