Skip to content

Commit f56444a

Browse files
committed
Add test for SubjectAccessReview authorization
Signed-off-by: averevki <[email protected]>
1 parent 52c5988 commit f56444a

File tree

6 files changed

+106
-15
lines changed

6 files changed

+106
-15
lines changed

testsuite/kuadrant/policy/authorization/sections.py

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

289289
@modify
290-
def add_kubernetes(self, name: str, user: ABCValue, resource_attributes: dict, **common_features):
290+
def add_kubernetes(self, name: str, user: ABCValue, resource_attributes: dict = None, **common_features):
291291
"""Adds Kubernetes authorization
292292
293293
:param name: name of kubernetes authorization

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

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)