From aa6e36e414d7d7926763e387f31712530334d935 Mon Sep 17 00:00:00 2001 From: Venktesh Shivam Patel <64591391+vepatel@users.noreply.github.com> Date: Wed, 19 Aug 2020 16:37:10 +0100 Subject: [PATCH] Add tests for access-control using policies in vs and vsr (#1101) * update policy tests with scenarios for routes and sub-routes for vs and vsr respectively --- .../access-control-policy-allow.yaml | 0 .../access-control-policy-deny.yaml | 0 .../access-control-policy-invalid.yaml | 0 .../virtual-server-allow-route.yaml | 22 ++ .../virtual-server-deny-route.yaml | 22 ++ .../virtual-server-invalid-route.yaml | 22 ++ .../virtual-server-override-route.yaml | 23 ++ .../virtual-server-override-spec-route.yaml | 24 ++ .../virtual-server-route-allow-subroute.yaml | 22 ++ .../virtual-server-route-deny-subroute.yaml | 22 ++ ...virtual-server-route-invalid-subroute.yaml | 22 ++ ...irtual-server-route-override-subroute.yaml | 23 ++ .../virtual-server-vsr-route-override.yaml | 13 + .../virtual-server-vsr-spec-override.yaml | 13 + .../{ => spec}/virtual-server-allow.yaml | 0 .../{ => spec}/virtual-server-deny.yaml | 0 .../{ => spec}/virtual-server-invalid.yaml | 0 .../{ => spec}/virtual-server-override.yaml | 0 tests/suite/test_ac_policies.py | 142 +++++-- tests/suite/test_ac_policies_vsr.py | 369 ++++++++++++++++++ 20 files changed, 711 insertions(+), 28 deletions(-) rename tests/data/access-control/{ => policies}/access-control-policy-allow.yaml (100%) rename tests/data/access-control/{ => policies}/access-control-policy-deny.yaml (100%) rename tests/data/access-control/{ => policies}/access-control-policy-invalid.yaml (100%) create mode 100644 tests/data/access-control/route-subroute/virtual-server-allow-route.yaml create mode 100644 tests/data/access-control/route-subroute/virtual-server-deny-route.yaml create mode 100644 tests/data/access-control/route-subroute/virtual-server-invalid-route.yaml create mode 100644 tests/data/access-control/route-subroute/virtual-server-override-route.yaml create mode 100644 tests/data/access-control/route-subroute/virtual-server-override-spec-route.yaml create mode 100644 tests/data/access-control/route-subroute/virtual-server-route-allow-subroute.yaml create mode 100644 tests/data/access-control/route-subroute/virtual-server-route-deny-subroute.yaml create mode 100644 tests/data/access-control/route-subroute/virtual-server-route-invalid-subroute.yaml create mode 100644 tests/data/access-control/route-subroute/virtual-server-route-override-subroute.yaml create mode 100644 tests/data/access-control/route-subroute/virtual-server-vsr-route-override.yaml create mode 100644 tests/data/access-control/route-subroute/virtual-server-vsr-spec-override.yaml rename tests/data/access-control/{ => spec}/virtual-server-allow.yaml (100%) rename tests/data/access-control/{ => spec}/virtual-server-deny.yaml (100%) rename tests/data/access-control/{ => spec}/virtual-server-invalid.yaml (100%) rename tests/data/access-control/{ => spec}/virtual-server-override.yaml (100%) create mode 100644 tests/suite/test_ac_policies_vsr.py diff --git a/tests/data/access-control/access-control-policy-allow.yaml b/tests/data/access-control/policies/access-control-policy-allow.yaml similarity index 100% rename from tests/data/access-control/access-control-policy-allow.yaml rename to tests/data/access-control/policies/access-control-policy-allow.yaml diff --git a/tests/data/access-control/access-control-policy-deny.yaml b/tests/data/access-control/policies/access-control-policy-deny.yaml similarity index 100% rename from tests/data/access-control/access-control-policy-deny.yaml rename to tests/data/access-control/policies/access-control-policy-deny.yaml diff --git a/tests/data/access-control/access-control-policy-invalid.yaml b/tests/data/access-control/policies/access-control-policy-invalid.yaml similarity index 100% rename from tests/data/access-control/access-control-policy-invalid.yaml rename to tests/data/access-control/policies/access-control-policy-invalid.yaml diff --git a/tests/data/access-control/route-subroute/virtual-server-allow-route.yaml b/tests/data/access-control/route-subroute/virtual-server-allow-route.yaml new file mode 100644 index 0000000000..1442a1bc98 --- /dev/null +++ b/tests/data/access-control/route-subroute/virtual-server-allow-route.yaml @@ -0,0 +1,22 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServer +metadata: + name: virtual-server +spec: + host: virtual-server.example.com + upstreams: + - name: backend2 + service: backend2-svc + port: 80 + - name: backend1 + service: backend1-svc + port: 80 + routes: + - path: "/backend1" + policies: + - name: allow-policy + action: + pass: backend1 + - path: "/backend2" + action: + pass: backend2 \ No newline at end of file diff --git a/tests/data/access-control/route-subroute/virtual-server-deny-route.yaml b/tests/data/access-control/route-subroute/virtual-server-deny-route.yaml new file mode 100644 index 0000000000..f1594c32e6 --- /dev/null +++ b/tests/data/access-control/route-subroute/virtual-server-deny-route.yaml @@ -0,0 +1,22 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServer +metadata: + name: virtual-server +spec: + host: virtual-server.example.com + upstreams: + - name: backend2 + service: backend2-svc + port: 80 + - name: backend1 + service: backend1-svc + port: 80 + routes: + - path: "/backend1" + policies: + - name: deny-policy + action: + pass: backend1 + - path: "/backend2" + action: + pass: backend2 \ No newline at end of file diff --git a/tests/data/access-control/route-subroute/virtual-server-invalid-route.yaml b/tests/data/access-control/route-subroute/virtual-server-invalid-route.yaml new file mode 100644 index 0000000000..2cd584e4cc --- /dev/null +++ b/tests/data/access-control/route-subroute/virtual-server-invalid-route.yaml @@ -0,0 +1,22 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServer +metadata: + name: virtual-server +spec: + host: virtual-server.example.com + upstreams: + - name: backend2 + service: backend2-svc + port: 80 + - name: backend1 + service: backend1-svc + port: 80 + routes: + - path: "/backend1" + policies: + - name: invalid-policy + action: + pass: backend1 + - path: "/backend2" + action: + pass: backend2 \ No newline at end of file diff --git a/tests/data/access-control/route-subroute/virtual-server-override-route.yaml b/tests/data/access-control/route-subroute/virtual-server-override-route.yaml new file mode 100644 index 0000000000..491f209bf2 --- /dev/null +++ b/tests/data/access-control/route-subroute/virtual-server-override-route.yaml @@ -0,0 +1,23 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServer +metadata: + name: virtual-server +spec: + host: virtual-server.example.com + upstreams: + - name: backend2 + service: backend2-svc + port: 80 + - name: backend1 + service: backend1-svc + port: 80 + routes: + - path: "/backend1" + policies: + - name: allow-policy + - name: deny-policy + action: + pass: backend1 + - path: "/backend2" + action: + pass: backend2 \ No newline at end of file diff --git a/tests/data/access-control/route-subroute/virtual-server-override-spec-route.yaml b/tests/data/access-control/route-subroute/virtual-server-override-spec-route.yaml new file mode 100644 index 0000000000..d6cc158f7d --- /dev/null +++ b/tests/data/access-control/route-subroute/virtual-server-override-spec-route.yaml @@ -0,0 +1,24 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServer +metadata: + name: virtual-server +spec: + host: virtual-server.example.com + policies: + - name: deny-policy + upstreams: + - name: backend2 + service: backend2-svc + port: 80 + - name: backend1 + service: backend1-svc + port: 80 + routes: + - path: "/backend1" + policies: + - name: allow-policy + action: + pass: backend1 + - path: "/backend2" + action: + pass: backend2 \ No newline at end of file diff --git a/tests/data/access-control/route-subroute/virtual-server-route-allow-subroute.yaml b/tests/data/access-control/route-subroute/virtual-server-route-allow-subroute.yaml new file mode 100644 index 0000000000..37188f6a83 --- /dev/null +++ b/tests/data/access-control/route-subroute/virtual-server-route-allow-subroute.yaml @@ -0,0 +1,22 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServerRoute +metadata: + name: backends +spec: + host: virtual-server-route.example.com + upstreams: + - name: backend1 + service: backend1-svc + port: 80 + - name: backend3 + service: backend3-svc + port: 80 + subroutes: + - path: "/backends/backend1" + policies: + - name: allow-policy + action: + pass: backend1 + - path: "/backends/backend3" + action: + pass: backend3 \ No newline at end of file diff --git a/tests/data/access-control/route-subroute/virtual-server-route-deny-subroute.yaml b/tests/data/access-control/route-subroute/virtual-server-route-deny-subroute.yaml new file mode 100644 index 0000000000..6b51d1d22c --- /dev/null +++ b/tests/data/access-control/route-subroute/virtual-server-route-deny-subroute.yaml @@ -0,0 +1,22 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServerRoute +metadata: + name: backends +spec: + host: virtual-server-route.example.com + upstreams: + - name: backend1 + service: backend1-svc + port: 80 + - name: backend3 + service: backend3-svc + port: 80 + subroutes: + - path: "/backends/backend1" + policies: + - name: deny-policy + action: + pass: backend1 + - path: "/backends/backend3" + action: + pass: backend3 \ No newline at end of file diff --git a/tests/data/access-control/route-subroute/virtual-server-route-invalid-subroute.yaml b/tests/data/access-control/route-subroute/virtual-server-route-invalid-subroute.yaml new file mode 100644 index 0000000000..61d77912f2 --- /dev/null +++ b/tests/data/access-control/route-subroute/virtual-server-route-invalid-subroute.yaml @@ -0,0 +1,22 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServerRoute +metadata: + name: backends +spec: + host: virtual-server-route.example.com + upstreams: + - name: backend1 + service: backend1-svc + port: 80 + - name: backend3 + service: backend3-svc + port: 80 + subroutes: + - path: "/backends/backend1" + policies: + - name: invalid-policy + action: + pass: backend1 + - path: "/backends/backend3" + action: + pass: backend3 \ No newline at end of file diff --git a/tests/data/access-control/route-subroute/virtual-server-route-override-subroute.yaml b/tests/data/access-control/route-subroute/virtual-server-route-override-subroute.yaml new file mode 100644 index 0000000000..ad26821612 --- /dev/null +++ b/tests/data/access-control/route-subroute/virtual-server-route-override-subroute.yaml @@ -0,0 +1,23 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServerRoute +metadata: + name: backends +spec: + host: virtual-server-route.example.com + upstreams: + - name: backend1 + service: backend1-svc + port: 80 + - name: backend3 + service: backend3-svc + port: 80 + subroutes: + - path: "/backends/backend1" + policies: + - name: deny-policy + - name: allow-policy + action: + pass: backend1 + - path: "/backends/backend3" + action: + pass: backend3 \ No newline at end of file diff --git a/tests/data/access-control/route-subroute/virtual-server-vsr-route-override.yaml b/tests/data/access-control/route-subroute/virtual-server-vsr-route-override.yaml new file mode 100644 index 0000000000..ac261605a4 --- /dev/null +++ b/tests/data/access-control/route-subroute/virtual-server-vsr-route-override.yaml @@ -0,0 +1,13 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServer +metadata: + name: virtual-server-route +spec: + host: virtual-server-route.example.com + routes: + - path: "/backends" + policies: + - name: deny-policy + route: backends + - path: "/backend2" + route: backend2-namespace/backend2 \ No newline at end of file diff --git a/tests/data/access-control/route-subroute/virtual-server-vsr-spec-override.yaml b/tests/data/access-control/route-subroute/virtual-server-vsr-spec-override.yaml new file mode 100644 index 0000000000..352c73e212 --- /dev/null +++ b/tests/data/access-control/route-subroute/virtual-server-vsr-spec-override.yaml @@ -0,0 +1,13 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServer +metadata: + name: virtual-server-route +spec: + host: virtual-server-route.example.com + policies: + - name: deny-policy + routes: + - path: "/backends" + route: backends + - path: "/backend2" + route: backend2-namespace/backend2 \ No newline at end of file diff --git a/tests/data/access-control/virtual-server-allow.yaml b/tests/data/access-control/spec/virtual-server-allow.yaml similarity index 100% rename from tests/data/access-control/virtual-server-allow.yaml rename to tests/data/access-control/spec/virtual-server-allow.yaml diff --git a/tests/data/access-control/virtual-server-deny.yaml b/tests/data/access-control/spec/virtual-server-deny.yaml similarity index 100% rename from tests/data/access-control/virtual-server-deny.yaml rename to tests/data/access-control/spec/virtual-server-deny.yaml diff --git a/tests/data/access-control/virtual-server-invalid.yaml b/tests/data/access-control/spec/virtual-server-invalid.yaml similarity index 100% rename from tests/data/access-control/virtual-server-invalid.yaml rename to tests/data/access-control/spec/virtual-server-invalid.yaml diff --git a/tests/data/access-control/virtual-server-override.yaml b/tests/data/access-control/spec/virtual-server-override.yaml similarity index 100% rename from tests/data/access-control/virtual-server-override.yaml rename to tests/data/access-control/spec/virtual-server-override.yaml diff --git a/tests/suite/test_ac_policies.py b/tests/suite/test_ac_policies.py index 6e4385bdaa..bd5385e5e6 100644 --- a/tests/suite/test_ac_policies.py +++ b/tests/suite/test_ac_policies.py @@ -15,14 +15,22 @@ std_cm_src = f"{DEPLOYMENTS}/common/nginx-config.yaml" test_cm_src = f"{TEST_DATA}/access-control/configmap/nginx-config.yaml" std_vs_src = f"{TEST_DATA}/access-control/standard/virtual-server.yaml" -deny_pol_src = f"{TEST_DATA}/access-control/access-control-policy-deny.yaml" -deny_vs_src = f"{TEST_DATA}/access-control/virtual-server-deny.yaml" -allow_pol_src = f"{TEST_DATA}/access-control/access-control-policy-allow.yaml" -allow_vs_src = f"{TEST_DATA}/access-control/virtual-server-allow.yaml" -override_vs_src = f"{TEST_DATA}/access-control/virtual-server-override.yaml" -invalid_pol_src = f"{TEST_DATA}/access-control/access-control-policy-invalid.yaml" -invalid_vs_src = f"{TEST_DATA}/access-control/virtual-server-invalid.yaml" - +deny_pol_src = f"{TEST_DATA}/access-control/policies/access-control-policy-deny.yaml" +deny_vs_src = f"{TEST_DATA}/access-control/spec/virtual-server-deny.yaml" +allow_pol_src = f"{TEST_DATA}/access-control/policies/access-control-policy-allow.yaml" +allow_vs_src = f"{TEST_DATA}/access-control/spec/virtual-server-allow.yaml" +override_vs_src = f"{TEST_DATA}/access-control/spec/virtual-server-override.yaml" +invalid_pol_src = f"{TEST_DATA}/access-control/policies/access-control-policy-invalid.yaml" +invalid_vs_src = f"{TEST_DATA}/access-control/spec/virtual-server-invalid.yaml" +allow_vs_src_route = f"{TEST_DATA}/access-control/route-subroute/virtual-server-allow-route.yaml" +deny_vs_src_route = f"{TEST_DATA}/access-control/route-subroute/virtual-server-deny-route.yaml" +invalid_vs_src_route = ( + f"{TEST_DATA}/access-control/route-subroute/virtual-server-invalid-route.yaml" +) +override_vs_src_route = ( + f"{TEST_DATA}/access-control/route-subroute/virtual-server-override-route.yaml" +) +override_vs_spec_route_src = f"{TEST_DATA}/access-control/route-subroute/virtual-server-override-spec-route.yaml" @pytest.fixture(scope="class") def config_setup(request, kube_apis, ingress_controller_prerequisites) -> None: @@ -43,11 +51,11 @@ def config_setup(request, kube_apis, ingress_controller_prerequisites) -> None: def fin(): print(f"------------- Restore ConfigMap --------------") replace_configmap_from_yaml( - kube_apis.v1, - ingress_controller_prerequisites.config_map["metadata"]["name"], - ingress_controller_prerequisites.namespace, - std_cm_src, - ) + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + std_cm_src, + ) request.addfinalizer(fin) @@ -65,7 +73,7 @@ def fin(): ], indirect=True, ) -class TestAccessControlPolicies: +class TestAccessControlPoliciesVs: def restore_default_vs(self, kube_apis, virtual_server_setup) -> None: """ Restore VirtualServer without policy spec @@ -78,9 +86,16 @@ def restore_default_vs(self, kube_apis, virtual_server_setup) -> None: ) wait_before_test() + @pytest.mark.parametrize("src", [deny_vs_src, deny_vs_src_route]) @pytest.mark.smoke def test_deny_policy( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, config_setup + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + config_setup, + src, ): """ Test if ip (10.0.0.1) block-listing is working: default(no policy) -> deny @@ -94,10 +109,11 @@ def test_deny_policy( print(f"Create deny policy") pol_name = create_policy_from_yaml(kube_apis.custom_objects, deny_pol_src, test_namespace) + print(f"Patch vs with policy: {src}") patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, - deny_vs_src, + src, virtual_server_setup.namespace, ) wait_before_test() @@ -125,9 +141,16 @@ def test_deny_policy( and "Server address:" in resp2.text ) + @pytest.mark.parametrize("src", [allow_vs_src, allow_vs_src_route]) @pytest.mark.smoke def test_allow_policy( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, config_setup + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + config_setup, + src, ): """ Test if ip (10.0.0.1) allow-listing is working: default(no policy) -> allow @@ -144,7 +167,7 @@ def test_allow_policy( patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, - allow_vs_src, + src, virtual_server_setup.namespace, ) wait_before_test() @@ -172,8 +195,15 @@ def test_allow_policy( and "403 Forbidden" in resp2.text ) + @pytest.mark.parametrize("src", [override_vs_src, override_vs_src_route]) def test_override_policy( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, config_setup + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + config_setup, + src, ): """ Test if ip allow-listing overrides block-listing: default(no policy) -> deny and allow @@ -196,7 +226,7 @@ def test_override_policy( patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, - override_vs_src, + src, virtual_server_setup.namespace, ) wait_before_test() @@ -214,8 +244,15 @@ def test_override_policy( assert resp.status_code == 200 and "Server address:" in resp.text + @pytest.mark.parametrize("src", [invalid_vs_src, invalid_vs_src_route]) def test_invalid_policy( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, config_setup + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + config_setup, + src, ): """ Test if invalid policy is applied then response is 500 @@ -234,7 +271,7 @@ def test_invalid_policy( patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, - invalid_vs_src, + src, virtual_server_setup.namespace, ) @@ -260,8 +297,15 @@ def test_invalid_policy( and vs_info["status"]["reason"] == "AddedOrUpdatedWithWarning" ) + @pytest.mark.parametrize("src", [deny_vs_src, deny_vs_src_route]) def test_deleted_policy( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, config_setup + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + config_setup, + src, ): """ Test if valid policy is deleted then response is 500 @@ -274,16 +318,14 @@ def test_deleted_policy( assert resp.status_code == 200 print(f"Create deny policy") - + pol_name = create_policy_from_yaml(kube_apis.custom_objects, deny_pol_src, test_namespace) patch_virtual_server_from_yaml( kube_apis.custom_objects, virtual_server_setup.vs_name, - deny_vs_src, + src, virtual_server_setup.namespace, ) - pol_name = create_policy_from_yaml( - kube_apis.custom_objects, deny_pol_src, test_namespace - ) + wait_before_test() vs_info = read_crd( kube_apis.custom_objects, @@ -314,3 +356,47 @@ def test_deleted_policy( vs_info["status"]["state"] == "Warning" and vs_info["status"]["reason"] == "UpdatedWithWarning" ) + + 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 \ No newline at end of file diff --git a/tests/suite/test_ac_policies_vsr.py b/tests/suite/test_ac_policies_vsr.py new file mode 100644 index 0000000000..fb8b813dda --- /dev/null +++ b/tests/suite/test_ac_policies_vsr.py @@ -0,0 +1,369 @@ +import pytest, requests +from kubernetes.client.rest import ApiException +from suite.resources_utils import wait_before_test, replace_configmap_from_yaml +from suite.custom_resources_utils import ( + read_crd, + delete_virtual_server, + create_virtual_server_from_yaml, + patch_virtual_server_from_yaml, + patch_v_s_route_from_yaml, + create_policy_from_yaml, + delete_policy, +) +from settings import TEST_DATA, DEPLOYMENTS + +std_cm_src = f"{DEPLOYMENTS}/common/nginx-config.yaml" +test_cm_src = f"{TEST_DATA}/access-control/configmap/nginx-config.yaml" +std_vs_src = f"{TEST_DATA}/virtual-server-route/standard/virtual-server.yaml" +deny_pol_src = f"{TEST_DATA}/access-control/policies/access-control-policy-deny.yaml" +allow_pol_src = f"{TEST_DATA}/access-control/policies/access-control-policy-allow.yaml" +invalid_pol_src = f"{TEST_DATA}/access-control/policies/access-control-policy-invalid.yaml" +deny_vsr_src = f"{TEST_DATA}/access-control/route-subroute/virtual-server-route-deny-subroute.yaml" +allow_vsr_src = ( + f"{TEST_DATA}/access-control/route-subroute/virtual-server-route-allow-subroute.yaml" +) +override_vsr_src = ( + f"{TEST_DATA}/access-control/route-subroute/virtual-server-route-override-subroute.yaml" +) +invalid_vsr_src = ( + f"{TEST_DATA}/access-control/route-subroute/virtual-server-route-invalid-subroute.yaml" +) +vs_spec_vsr_override_src = ( + f"{TEST_DATA}/access-control/route-subroute/virtual-server-vsr-spec-override.yaml" +) +vs_route_vsr_override_src = ( + f"{TEST_DATA}/access-control/route-subroute/virtual-server-vsr-route-override.yaml" +) + +@pytest.fixture(scope="class") +def config_setup(request, kube_apis, ingress_controller_prerequisites) -> None: + """ + Replace configmap to add "set-real-ip-from" + :param request: pytest fixture + :param kube_apis: client apis + :param ingress_controller_prerequisites: IC pre-requisites + """ + print(f"------------- Replace ConfigMap --------------") + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + test_cm_src, + ) + + def fin(): + print(f"------------- Restore ConfigMap --------------") + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + std_cm_src, + ) + + request.addfinalizer(fin) + +@pytest.mark.policies +@pytest.mark.parametrize( + "crd_ingress_controller, v_s_route_setup", + [ + ( + { + "type": "complete", + "extra_args": [f"-enable-custom-resources", f"-enable-leader-election=false"], + }, + {"example": "virtual-server-route"}, + ) + ], + indirect=True, +) +class TestAccessControlPoliciesVsr: + 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_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_allow_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 allow policy") + 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, + ) + 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 ( + resp2.status_code == 403 + and "403 Forbidden" in resp2.text + and resp1.status_code == 200 + and "Server address:" in resp1.text + ) + + def test_override_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) allow-listing overrides block-listing (policy specified in vsr subroute) + """ + 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") + 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, + override_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, 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) + assert ( + resp2.status_code == 403 + and "403 Forbidden" in resp2.text + and resp1.status_code == 200 + and "Server address:" in resp1.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" + ) + + @pytest.mark.parametrize("src", [vs_spec_vsr_override_src, vs_route_vsr_override_src]) + 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