Skip to content

Commit 3e1c42e

Browse files
authored
Merge pull request #589 from azgabur/small_fix
Make gateway secret name unique
2 parents 7fe7f52 + 77661b9 commit 3e1c42e

File tree

8 files changed

+52
-21
lines changed

8 files changed

+52
-21
lines changed

testsuite/gateway/__init__.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ def wait_for_ready(self, timeout: int = 90):
135135
"""Waits until the gateway is ready"""
136136

137137
@abstractmethod
138-
def get_tls_cert(self) -> Optional[Certificate]:
138+
def get_tls_cert(self, hostname: str) -> Optional[Certificate]:
139139
"""Returns TLS cert bound to this Gateway, if the Gateway does not use TLS, returns None"""
140140

141141

@@ -211,7 +211,10 @@ def asdict(self):
211211
"port": self.port,
212212
"protocol": self.protocol,
213213
"allowedRoutes": self.allowedRoutes,
214-
"tls": {"mode": self.mode, "certificateRefs": [{"name": f"{self.gateway_name}-tls", "kind": "Secret"}]},
214+
"tls": {
215+
"mode": self.mode,
216+
"certificateRefs": [{"name": f"{self.gateway_name}-{self.name}-tls", "kind": "Secret"}],
217+
},
215218
}
216219

217220

testsuite/gateway/envoy/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def commit(self):
9999
)
100100
self.service.commit()
101101

102-
def get_tls_cert(self) -> Optional[Certificate]:
102+
def get_tls_cert(self, _) -> Optional[Certificate]:
103103
return None
104104

105105
def delete(self):

testsuite/gateway/exposers.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ class LoadBalancerServiceExposer(Exposer):
6767
"""Exposer using Load Balancer service for Gateway"""
6868

6969
def expose_hostname(self, name, gateway: Gateway) -> Hostname:
70+
hostname = f"{name}.{self.base_domain}"
7071
return StaticLocalHostname(
71-
f"{name}.{self.base_domain}", gateway.external_ip, gateway.get_tls_cert(), force_https=self.passthrough
72+
hostname, gateway.external_ip, gateway.get_tls_cert(hostname), force_https=self.passthrough
7273
)
7374

7475
@property

testsuite/gateway/gateway_api/gateway.py

+18-10
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from testsuite.kubernetes.client import KubernetesClient
1010
from testsuite.kubernetes import KubernetesObject, modify
1111
from testsuite.kuadrant.policy import Policy
12-
from testsuite.utils import check_condition, asdict
12+
from testsuite.utils import check_condition, asdict, domain_match
1313

1414

1515
class KuadrantGateway(KubernetesObject, Gateway):
@@ -84,11 +84,15 @@ def is_affected_by(self, policy: Policy) -> bool:
8484
return True
8585
return False
8686

87-
def get_tls_cert(self):
88-
if "tls" not in self.model.spec.listeners[0]:
87+
def get_tls_cert(self, hostname):
88+
tls_cert_secret_name = None
89+
for listener in self.all_tls_listeners():
90+
if domain_match(hostname, listener.hostname):
91+
tls_cert_secret_name = listener.tls.certificateRefs[0].name
92+
93+
if tls_cert_secret_name is None:
8994
return None
9095

91-
tls_cert_secret_name = self.cert_secret_name
9296
try:
9397
tls_cert_secret = self.cluster.get_secret(tls_cert_secret_name)
9498
except oc.OpenShiftPythonException as e:
@@ -102,20 +106,24 @@ def get_tls_cert(self):
102106
)
103107
return tls_cert
104108

109+
def all_tls_listeners(self):
110+
"""Yields all listeners in gateway that support 'tls'"""
111+
for listener in self.model.spec.listeners:
112+
if "tls" in listener:
113+
yield listener
114+
105115
def delete(self, ignore_not_found=True, cmd_args=None):
106116
res = super().delete(ignore_not_found, cmd_args)
107117
with self.cluster.context:
108118
# TLSPolicy does not delete certificates it creates
109-
oc.selector(f"secret/{self.cert_secret_name}").delete(ignore_not_found=True)
119+
for secret in oc.selector("secret").objects():
120+
if "tls" in secret.name() and self.name() in secret.name():
121+
secret.delete()
122+
110123
# Istio does not delete ServiceAccount
111124
oc.selector(f"sa/{self.service_name}").delete(ignore_not_found=True)
112125
return res
113126

114-
@property
115-
def cert_secret_name(self):
116-
"""Returns name of the secret with generated TLS certificate"""
117-
return self.model.spec.listeners[0].tls.certificateRefs[0].name
118-
119127
@property
120128
def reference(self):
121129
return {

testsuite/gateway/gateway_api/hostname.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
class StaticHostname(Hostname):
1616
"""Already exposed hostname object"""
1717

18-
def __init__(self, hostname, tls_cert_getter: Callable[[], Certificate | bool] = None):
18+
def __init__(self, hostname, tls_cert_getter: Callable[[str], Certificate | bool] = None):
1919
"""
2020
:param hostname: Hostname that is exposed
2121
:param tls_cert_getter: Function that will gather TLS certificate when called,
@@ -27,9 +27,11 @@ def __init__(self, hostname, tls_cert_getter: Callable[[], Certificate | bool] =
2727

2828
def client(self, **kwargs) -> KuadrantClient:
2929
protocol = "http"
30-
if self.tls_cert_getter is not None and self.tls_cert_getter() is not None:
31-
protocol = "https"
32-
kwargs.setdefault("verify", self.tls_cert_getter())
30+
if self.tls_cert_getter is not None:
31+
cert = self.tls_cert_getter(self.hostname)
32+
if cert is not None:
33+
protocol = "https"
34+
kwargs.setdefault("verify", self.tls_cert_getter(self.hostname))
3335
return KuadrantClient(base_url=f"{protocol}://{self.hostname}", **kwargs)
3436

3537
@property

testsuite/tests/singlecluster/gateway/test_external_ca.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def cluster_issuer(testconfig, cluster):
6060
def client(hostname, gateway):
6161
"""Returns httpx client to be used for requests, it also commits AuthConfig"""
6262
root_cert = resources.files("testsuite.resources").joinpath("letsencrypt-stg-root-x1.pem").read_text()
63-
old_cert = gateway.get_tls_cert()
63+
old_cert = gateway.get_tls_cert(hostname.hostname)
6464
cert = dataclasses.replace(old_cert, chain=old_cert.certificate + root_cert)
6565
client = hostname.client(verify=cert)
6666
yield client

testsuite/tests/singlecluster/gateway/tlspolicy/test_cert_parameters.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ def tls_policy(tls_policy):
2929

3030

3131
@pytest.fixture(scope="module")
32-
def tls_cert(gateway): # pylint: disable=unused-argument
32+
def tls_cert(gateway, wildcard_domain): # pylint: disable=unused-argument
3333
"""Return certificate generated by TLSPolicy"""
34-
return gateway.get_tls_cert()
34+
return gateway.get_tls_cert(wildcard_domain)
3535

3636

3737
def test_tls_cert_common_name(tls_cert):

testsuite/utils.py

+17
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,20 @@ def sleep_ttl(hostname: str):
209209
return
210210

211211
sleep(dns.resolver.resolve(hostname).rrset.ttl) # type: ignore
212+
213+
214+
def domain_match(first: str, second: str):
215+
"""Returns true if domains are the same, considering left-most wildcard"""
216+
# strip last '.'
217+
if first[-1] == ".":
218+
first = first[:-1]
219+
if second[-1] == ".":
220+
second = second[:-1]
221+
222+
if first == second:
223+
return True
224+
if first[0] == "*":
225+
return first[2:] == ".".join(second.split(".")[1:])
226+
if second[0] == "*":
227+
return second[2:] == ".".join(first.split(".")[1:])
228+
return False

0 commit comments

Comments
 (0)