From a3aae50676235beecb1a8a8097016a59622c1253 Mon Sep 17 00:00:00 2001 From: averevki Date: Tue, 18 Feb 2025 19:44:22 +0100 Subject: [PATCH] D&O section target tests Signed-off-by: averevki --- .../policy/authorization/auth_policy.py | 3 + testsuite/kuadrant/policy/rate_limit.py | 13 ++++- .../defaults/test_section_targeting.py | 57 +++++++++++++++++++ .../overrides/test_multiple_rate_limit.py | 51 +++++++++++++++++ .../overrides/test_section_targeting.py | 57 +++++++++++++++++++ 5 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/singlecluster/defaults/test_section_targeting.py create mode 100644 testsuite/tests/singlecluster/overrides/test_multiple_rate_limit.py create mode 100644 testsuite/tests/singlecluster/overrides/test_section_targeting.py diff --git a/testsuite/kuadrant/policy/authorization/auth_policy.py b/testsuite/kuadrant/policy/authorization/auth_policy.py index 4c77bfe4..62d2292f 100644 --- a/testsuite/kuadrant/policy/authorization/auth_policy.py +++ b/testsuite/kuadrant/policy/authorization/auth_policy.py @@ -27,6 +27,7 @@ def create_instance( name, target: Referencable, labels: Dict[str, str] = None, + section_name: str = None, ): """Creates base instance""" model: Dict = { @@ -37,6 +38,8 @@ def create_instance( "targetRef": target.reference, }, } + if section_name: + model["spec"]["targetRef"]["sectionName"] = section_name return cls(model, context=cluster.context) diff --git a/testsuite/kuadrant/policy/rate_limit.py b/testsuite/kuadrant/policy/rate_limit.py index a46ee1ea..7332f751 100644 --- a/testsuite/kuadrant/policy/rate_limit.py +++ b/testsuite/kuadrant/policy/rate_limit.py @@ -27,9 +27,16 @@ def __init__(self, *args, **kwargs): self.spec_section = None @classmethod - def create_instance(cls, cluster: KubernetesClient, name, target: Referencable, labels: dict[str, str] = None): + def create_instance( + cls, + cluster: KubernetesClient, + name, + target: Referencable, + section_name: str = None, + labels: dict[str, str] = None, + ): """Creates new instance of RateLimitPolicy""" - model = { + model: dict = { "apiVersion": "kuadrant.io/v1", "kind": "RateLimitPolicy", "metadata": {"name": name, "labels": labels}, @@ -37,6 +44,8 @@ def create_instance(cls, cluster: KubernetesClient, name, target: Referencable, "targetRef": target.reference, }, } + if section_name: + model["spec"]["targetRef"]["sectionName"] = section_name return cls(model, context=cluster.context) diff --git a/testsuite/tests/singlecluster/defaults/test_section_targeting.py b/testsuite/tests/singlecluster/defaults/test_section_targeting.py new file mode 100644 index 00000000..b6c0e190 --- /dev/null +++ b/testsuite/tests/singlecluster/defaults/test_section_targeting.py @@ -0,0 +1,57 @@ +"""Test enforcement of policies with defaults targeting a specifics gateway/route section""" + +import pytest + +from testsuite.httpx.auth import HttpxOidcClientAuth +from testsuite.kuadrant.policy.authorization.auth_policy import AuthPolicy +from testsuite.kuadrant.policy.rate_limit import RateLimitPolicy, Limit + +pytestmark = [pytest.mark.kuadrant_only, pytest.mark.limitador] + +LIMIT = Limit(5, "10s") + + +@pytest.fixture(scope="module") +def target(request): + """Returns the test target(gateway or route) and the target section name""" + return request.getfixturevalue(request.param[0]), request.param[1] + + +@pytest.fixture(scope="module") +def auth(oidc_provider): + """Returns Authentication object for HTTPX""" + return HttpxOidcClientAuth(oidc_provider.get_token, "authorization") + + +@pytest.fixture(scope="module") +def authorization(cluster, target, route, oidc_provider, module_label, blame): # pylint: disable=unused-argument + """Add oidc identity to defaults block of AuthPolicy""" + authorization = AuthPolicy.create_instance( + cluster, blame("authz"), target[0], labels={"testRun": module_label}, section_name=target[1] + ) + authorization.defaults.identity.add_oidc("default", oidc_provider.well_known["issuer"]) + return authorization + + +@pytest.fixture(scope="module") +def rate_limit(cluster, target, route, module_label, blame): # pylint: disable=unused-argument + """Add a RateLimitPolicy targeting specific section""" + rate_limit = RateLimitPolicy.create_instance( + cluster, blame("limit"), target[0], target[1], labels={"testRun": module_label} + ) + rate_limit.defaults.add_limit("basic", [LIMIT]) + return rate_limit + + +@pytest.mark.parametrize( + "target", + [pytest.param(("gateway", "api"), id="gateway"), pytest.param(("route", "rule-1"), id="route")], + indirect=True, +) +def test_basic_listener(client, auth): + """Test the defaults policies are correctly applied to the target section""" + assert client.get("/get").status_code == 401 + + responses = client.get_many("/get", LIMIT.limit - 1, auth=auth) + responses.assert_all(status_code=200) + assert client.get("/get", auth=auth).status_code == 429 diff --git a/testsuite/tests/singlecluster/overrides/test_multiple_rate_limit.py b/testsuite/tests/singlecluster/overrides/test_multiple_rate_limit.py new file mode 100644 index 00000000..f2da4840 --- /dev/null +++ b/testsuite/tests/singlecluster/overrides/test_multiple_rate_limit.py @@ -0,0 +1,51 @@ +"""Test override overriding another policy aimed at the same gateway/route""" + +import pytest + +from testsuite.kuadrant.policy.rate_limit import RateLimitPolicy, Limit + +pytestmark = [pytest.mark.kuadrant_only, pytest.mark.limitador] + +LIMIT = Limit(10, "10s") +OVERRIDE_LIMIT = Limit(5, "10s") + + +@pytest.fixture(scope="module") +def target(request): + """Returns the test target(gateway or route)""" + return request.getfixturevalue(request.param) + + +@pytest.fixture(scope="module") +def rate_limit(cluster, blame, module_label, target): + """Add a RateLimitPolicy with a default limit targeting the gateway/route""" + rate_limit = RateLimitPolicy.create_instance(cluster, blame("limit"), target, labels={"testRun": module_label}) + rate_limit.defaults.add_limit("basic", [LIMIT]) + return rate_limit + + +@pytest.fixture(scope="module") +def override_rate_limit(cluster, blame, module_label, target): + """Add a RateLimitPolicy with an overrride targeting the gateway/route""" + override_rate_limit = RateLimitPolicy.create_instance( + cluster, blame("limit"), target, labels={"testRun": module_label} + ) + override_rate_limit.overrides.add_limit("override", [OVERRIDE_LIMIT]) + return override_rate_limit + + +@pytest.fixture(scope="module", autouse=True) +def commit(request, route, rate_limit, override_rate_limit): # pylint: disable=unused-argument + """Commits RateLimitPolicies after the HTTPRoute is created and checks correct status""" + for policy in [rate_limit, override_rate_limit]: + request.addfinalizer(policy.delete) + policy.commit() + policy.wait_for_ready() + + +@pytest.mark.parametrize("target", ["gateway", "route"], indirect=True) +def test_multiple_policies_gateway_override(client): + """Test RateLimitPolicy with an override overriding a default policy targeting the same gateway/route""" + responses = client.get_many("/get", OVERRIDE_LIMIT.limit) + responses.assert_all(status_code=200) + assert client.get("/get").status_code == 429 diff --git a/testsuite/tests/singlecluster/overrides/test_section_targeting.py b/testsuite/tests/singlecluster/overrides/test_section_targeting.py new file mode 100644 index 00000000..770ec4f4 --- /dev/null +++ b/testsuite/tests/singlecluster/overrides/test_section_targeting.py @@ -0,0 +1,57 @@ +"""Test override overriding another policy aimed at the same gateway/route section""" + +import pytest + +from testsuite.kuadrant.policy.rate_limit import RateLimitPolicy, Limit + +pytestmark = [pytest.mark.kuadrant_only, pytest.mark.limitador] + +LIMIT = Limit(8, "5s") +OVERRIDE_LIMIT = Limit(3, "5s") + + +@pytest.fixture(scope="module") +def target(request): + """Returns the test target(gateway or route) and the target section name""" + return request.getfixturevalue(request.param[0]), request.param[1] + + +@pytest.fixture(scope="module") +def rate_limit(cluster, blame, module_label, target): + """Add a RateLimitPolicy targeting the specific section of gateway/route""" + rate_limit = RateLimitPolicy.create_instance( + cluster, blame("limit"), target[0], section_name=target[1], labels={"testRun": module_label} + ) + rate_limit.defaults.add_limit("basic", [LIMIT]) + return rate_limit + + +@pytest.fixture(scope="module") +def override_rate_limit(cluster, blame, module_label, target): + """Add a RateLimitPolicy targeting the specific section of gateway/route""" + override_rate_limit = RateLimitPolicy.create_instance( + cluster, blame("limit"), target[0], section_name=target[1], labels={"testRun": module_label} + ) + override_rate_limit.overrides.add_limit("override", [OVERRIDE_LIMIT]) + return override_rate_limit + + +@pytest.fixture(scope="module", autouse=True) +def commit(request, route, rate_limit, override_rate_limit): # pylint: disable=unused-argument + """Commits RateLimitPolicy after the HTTPRoute is created""" + for policy in [rate_limit, override_rate_limit]: + request.addfinalizer(policy.delete) + policy.commit() + policy.wait_for_ready() + + +@pytest.mark.parametrize( + "target", + [pytest.param(("gateway", "api"), id="gateway"), pytest.param(("route", "rule-1"), id="route")], + indirect=True, +) +def test_multiple_policies_listener_override(client): + """Test RateLimitPolicy with an override overriding a default policy targeting the same gateway/route section""" + responses = client.get_many("/get", OVERRIDE_LIMIT.limit) + responses.assert_all(status_code=200) + assert client.get("/get").status_code == 429