Skip to content

Commit 028b4f7

Browse files
committed
Add test for SubjectAccessReview authorization.
Signed-off-by: Martin Hesko <[email protected]>
1 parent 20053cc commit 028b4f7

File tree

7 files changed

+111
-18
lines changed

7 files changed

+111
-18
lines changed

testsuite/kuadrant/policy/authorization/sections.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ def add_external_opa_policy(self, name, endpoint, ttl=0, **common_features):
283283
self.add_item(name, {"opa": {"externalPolicy": {"url": endpoint, "ttl": ttl}}}, **common_features)
284284

285285
@modify
286-
def add_kubernetes(self, name: str, user: ABCValue, resource_attributes: dict, **common_features):
286+
def add_kubernetes(self, name: str, user: ABCValue, resource_attributes: dict = None, **common_features):
287287
"""Adds Kubernetes authorization
288288
289289
:param name: name of kubernetes authorization

testsuite/kubernetes/cluster_role.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""ClusterRole and ClusterRoleBinding objects for Kubernetes"""
22

3-
from typing import Any, Dict, List, Optional
3+
from typing import Any
44
from testsuite.kubernetes import KubernetesObject
55

66

@@ -12,7 +12,7 @@ def create_instance(
1212
cls,
1313
cluster,
1414
name,
15-
rules: Optional[List[Dict[str, Any]]] = None,
15+
rules: list[dict[str, Any]] = None,
1616
labels: dict[str, str] = None,
1717
):
1818
"""Creates a new ClusterRole instance"""
@@ -37,7 +37,7 @@ def create_instance(
3737
cluster,
3838
name,
3939
cluster_role: str,
40-
serviceaccounts: List[str],
40+
serviceaccounts: list[str],
4141
labels: dict[str, str] = None,
4242
):
4343
"""Creates a new ClusterRoleBinding object"""

testsuite/tests/singlecluster/authorino/identity/conftest.py

+15
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@
22

33
import pytest
44

5+
from testsuite.kubernetes.service_account import ServiceAccount
6+
7+
8+
@pytest.fixture(scope="module")
9+
def create_service_account(request, cluster, blame, module_label):
10+
"""Creates and returns service account"""
11+
12+
def _create_service_account(name):
13+
service_account = ServiceAccount.create_instance(cluster, blame(name), labels={"app": module_label})
14+
request.addfinalizer(service_account.delete)
15+
service_account.commit()
16+
return service_account
17+
18+
return _create_service_account
19+
520

621
@pytest.fixture(scope="module")
722
def authorization(authorization):

testsuite/tests/singlecluster/authorino/identity/subject_access_review/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""Conftest for SubjectAccessReview related tests."""
2+
3+
import pytest
4+
5+
from testsuite.httpx.auth import HeaderApiKeyAuth
6+
from testsuite.kubernetes.cluster_role import ClusterRole, ClusterRoleBinding
7+
8+
9+
@pytest.fixture(scope="module")
10+
def cluster_role(request, cluster, blame, module_label):
11+
"""Creates and returns a ClusterRole"""
12+
rules = [{"nonResourceURLs": ["/get"], "verbs": ["get"]}]
13+
cluster_role = ClusterRole.create_instance(cluster, blame("cr"), rules, labels={"app": module_label})
14+
request.addfinalizer(cluster_role.delete)
15+
cluster_role.commit()
16+
return cluster_role
17+
18+
19+
@pytest.fixture(scope="module")
20+
def create_cluster_role_binding(request, cluster, blame, module_label):
21+
"""Creates and returns a ClusterRoleBinding"""
22+
23+
def _create_cluster_role_binding(cluster_role, service_accounts):
24+
cluster_role_binding = ClusterRoleBinding.create_instance(
25+
cluster, blame("crb"), cluster_role, service_accounts, labels={"app": module_label}
26+
)
27+
request.addfinalizer(cluster_role_binding.delete)
28+
cluster_role_binding.commit()
29+
return cluster_role_binding
30+
31+
return _create_cluster_role_binding
32+
33+
34+
@pytest.fixture(scope="module")
35+
def bound_service_account_token(cluster_role, create_service_account, create_cluster_role_binding, audience):
36+
"""Create a ServiceAccount, bind it to a ClusterRole and return its token with a given audience"""
37+
service_account = create_service_account("tkn-auth")
38+
create_cluster_role_binding(cluster_role.model.metadata.name, [service_account.model.metadata.name])
39+
return service_account.get_auth_token(audience)
40+
41+
42+
@pytest.fixture(scope="module")
43+
def auth(bound_service_account_token):
44+
"""Create request auth with service account token as API key"""
45+
return HeaderApiKeyAuth(bound_service_account_token, "Bearer")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""Test kubernetes SubjectAccessReview authorization by verifying only a
2+
ServiceAccount bound to a ClusterRole is authorized to access a resource"""
3+
4+
import pytest
5+
6+
from testsuite.httpx.auth import HeaderApiKeyAuth
7+
from testsuite.kuadrant.policy.authorization import ValueFrom
8+
9+
pytestmark = [pytest.mark.authorino]
10+
11+
12+
@pytest.fixture(scope="module")
13+
def authorization(authorization):
14+
"""Add kubernetes token-review and subject-access-review identity"""
15+
authorization.identity.add_kubernetes("token-review-host")
16+
user = ValueFrom("auth.identity.user.username")
17+
authorization.authorization.add_kubernetes("subject-access-review-host", user)
18+
return authorization
19+
20+
21+
@pytest.fixture(scope="module")
22+
def audience(hostname):
23+
"""Return hostname as only audience for the service account bound token"""
24+
return [hostname.hostname]
25+
26+
27+
@pytest.fixture(scope="module")
28+
def service_account_token(create_service_account, audience):
29+
"""Create a non-authorized service account and request its bound token with the hostname as audience"""
30+
service_account = create_service_account("tkn-non-auth")
31+
return service_account.get_auth_token(audience)
32+
33+
34+
@pytest.fixture(scope="module")
35+
def auth2(service_account_token):
36+
"""Create request auth with service account token as API key"""
37+
return HeaderApiKeyAuth(service_account_token, "Bearer")
38+
39+
40+
def test_host_audience(client, auth, auth2):
41+
"""Test Kubernetes SubjectAccessReview functionality by setting up authentication and authorization for an endpoint
42+
and querying it with non-authorized and authorized ServiceAccount."""
43+
response = client.get("/get", auth=auth2)
44+
assert response.status_code == 403
45+
46+
response = client.get("/get", auth=auth)
47+
assert response.status_code == 200

testsuite/tests/singlecluster/authorino/identity/token_review/conftest.py

-14
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,6 @@
33
import pytest
44

55
from testsuite.httpx.auth import HeaderApiKeyAuth
6-
from testsuite.kubernetes.service_account import ServiceAccount
7-
8-
9-
@pytest.fixture(scope="module")
10-
def create_service_account(request, cluster, blame, module_label):
11-
"""Creates and returns service account"""
12-
13-
def _create_service_account(name):
14-
service_account = ServiceAccount.create_instance(cluster, blame(name), labels={"app": module_label})
15-
request.addfinalizer(service_account.delete)
16-
service_account.commit()
17-
return service_account
18-
19-
return _create_service_account
206

217

228
@pytest.fixture(scope="module")

0 commit comments

Comments
 (0)