Skip to content

Commit 1b904eb

Browse files
committed
scheduler: include certificate and sni from admin cache
1 parent 630cfbd commit 1b904eb

File tree

11 files changed

+125
-29
lines changed

11 files changed

+125
-29
lines changed

microservices/gatewayApi/v2/routes/gateway.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,8 @@ def is_host_custom_domain(host):
502502
'.maps.gov.bc.ca',
503503
'.openmaps.gov.bc.ca',
504504
'.apps.gov.bc.ca',
505-
'.apis.gov.bc.ca'
505+
'.apis.gov.bc.ca',
506+
'.test'
506507
]
507508

508509
# Check if the host is one of the standard cert domains or a subdomain of them

microservices/gatewayJobScheduler/app.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
logger = logging.getLogger(__name__)
88

9-
def transform_data_by_ns(routes, cert_snis):
9+
def transform_data_by_ns(routes, certs, cert_snis):
1010
ns_svc = NamespaceService()
1111
try:
1212
ns_dict = {}
@@ -35,6 +35,7 @@ def transform_data_by_ns(routes, cert_snis):
3535

3636
for host in route_obj['hosts']:
3737
# Look for a matching certificate by SNI for custom domains
38+
cert = None
3839
cert_id = 'default'
3940
custom_cert_found = False
4041
if is_host_custom_domain(host):
@@ -45,6 +46,10 @@ def transform_data_by_ns(routes, cert_snis):
4546
cert_id = sni['certificate']
4647
logger.debug("%s - Found custom cert with SNI match for %s - %s" % (namespace, host, cert_id))
4748
custom_cert_found = True
49+
cert = next((cert for cert in certs if cert['id'] == cert_id), None)
50+
if cert is None:
51+
raise Exception("Certificate not found for id %s" % cert_id)
52+
cert['snis'] = [host]
4853
break
4954
if not custom_cert_found:
5055
raise Exception("Custom certificate not found for host %s" % host)
@@ -54,7 +59,8 @@ def transform_data_by_ns(routes, cert_snis):
5459
"sessionCookieEnabled": session_cookie_enabled,
5560
"dataClass": data_class,
5661
"dataPlane": os.getenv('DATA_PLANE'),
57-
"sslCertificateId": cert_id})
62+
"sslCertificateId": cert_id,
63+
"certificates": [cert] if cert is not None else None})
5864
return ns_dict
5965
except Exception as err:
6066
traceback.print_exc()
@@ -78,7 +84,8 @@ def is_host_custom_domain(host):
7884
'.maps.gov.bc.ca',
7985
'.openmaps.gov.bc.ca',
8086
'.apps.gov.bc.ca',
81-
'.apis.gov.bc.ca'
87+
'.apis.gov.bc.ca',
88+
'.test'
8289
]
8390

8491
# Check if the host is one of the standard cert domains or a subdomain of them

microservices/gatewayJobScheduler/clients/kong.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def get_records(record_type):
1111
Get all records of a specified type from Kong Admin API.
1212
1313
Args:
14-
record_type (str): Type of records to fetch ('routes' or 'snis')
14+
record_type (str): Type of records to fetch ('routes', 'certificates' or 'snis')
1515
1616
Returns:
1717
list: List of records
@@ -20,8 +20,8 @@ def get_records(record_type):
2020
OSError: If the shell command fails
2121
ValueError: If invalid record_type is provided
2222
"""
23-
if record_type not in ['routes', 'snis']:
24-
raise ValueError("record_type must be either 'routes' or 'snis'")
23+
if record_type not in ['routes', 'certificates', 'snis']:
24+
raise ValueError("record_type must be either 'routes', 'certificates' or 'snis'")
2525

2626
endpoint = "/%s" % record_type
2727
records_list = []

microservices/gatewayJobScheduler/main.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,15 @@ def sync_routes():
2525
}
2626
try:
2727
routes = get_records('routes')
28+
certs = get_records('certificates')
2829
cert_snis = get_records('snis')
2930
except:
3031
traceback.print_exc()
3132
logger.error('Failed to get existing routes - %s' % (exc_info()[0]))
3233
clear('sync-routes')
3334
exit(1)
3435

35-
data = transform_data_by_ns(routes, cert_snis)
36+
data = transform_data_by_ns(routes, certs, cert_snis)
3637
for ns in data:
3738
url = os.getenv('KUBE_API_URL') + '/namespaces/%s/routes/sync' % ns
3839
response = requests.post(url, headers=headers, json=data[ns], auth=(

microservices/gatewayJobScheduler/tests/test_transform_data_by_ns.py

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,23 @@ def test_happy_transform_data_by_ns():
1515
]
1616
}
1717
]
18-
snis = []
19-
assert json.dumps(transform_data_by_ns(routes, snis)) == '{"ns1": [{"name": "wild-ns-ns1-test.api.gov.bc.ca", "selectTag": "ns.ns1", "host": "test.api.gov.bc.ca", "sessionCookieEnabled": false, "dataClass": null, "dataPlane": "test-dp", "sslCertificateId": "default"}]}'
18+
certs = []
19+
cert_snis = []
20+
expected_value = {
21+
"ns1": [
22+
{
23+
"name": "wild-ns-ns1-test.api.gov.bc.ca",
24+
"selectTag": "ns.ns1",
25+
"host": "test.api.gov.bc.ca",
26+
"sessionCookieEnabled": False,
27+
"dataClass": None,
28+
"dataPlane": "test-dp",
29+
"sslCertificateId": "default",
30+
"certificates": None
31+
}
32+
]
33+
}
34+
assert json.dumps(transform_data_by_ns(routes, certs, cert_snis)) == json.dumps(expected_value)
2035

2136
def test_happy_transform_data_by_ns_with_override_session_cookie():
2237
with mock.patch('clients.namespace.admin_api') as mock_admin_api:
@@ -31,8 +46,21 @@ def test_happy_transform_data_by_ns_with_override_session_cookie():
3146
]
3247
}
3348
]
34-
snis = []
35-
assert json.dumps(transform_data_by_ns(routes, snis)) == '{"ns1": [{"name": "wild-ns-ns1-test.api.gov.bc.ca", "selectTag": "ns.ns1", "host": "test.api.gov.bc.ca", "sessionCookieEnabled": true, "dataClass": null, "dataPlane": "test-dp", "sslCertificateId": "default"}]}'
49+
certs = []
50+
cert_snis = []
51+
expected_value = {
52+
"ns1": [{
53+
"name": "wild-ns-ns1-test.api.gov.bc.ca",
54+
"selectTag": "ns.ns1",
55+
"host": "test.api.gov.bc.ca",
56+
"sessionCookieEnabled": True,
57+
"dataClass": None,
58+
"dataPlane": "test-dp",
59+
"sslCertificateId": "default",
60+
"certificates": None
61+
}]
62+
}
63+
assert json.dumps(transform_data_by_ns(routes, certs, cert_snis)) == json.dumps(expected_value)
3664

3765
def test_happy_transform_data_by_ns_with_override_data_plane():
3866
with mock.patch('clients.namespace.admin_api') as mock_admin_api:
@@ -47,8 +75,21 @@ def test_happy_transform_data_by_ns_with_override_data_plane():
4775
]
4876
}
4977
]
50-
snis = []
51-
assert json.dumps(transform_data_by_ns(routes, snis)) == '{"ns1": [{"name": "wild-ns-ns1-test.api.gov.bc.ca", "selectTag": "ns.ns1", "host": "test.api.gov.bc.ca", "sessionCookieEnabled": false, "dataClass": "high", "dataPlane": "test-dp", "sslCertificateId": "default"}]}'
78+
certs = []
79+
cert_snis = []
80+
expected_value = {
81+
"ns1": [{
82+
"name": "wild-ns-ns1-test.api.gov.bc.ca",
83+
"selectTag": "ns.ns1",
84+
"host": "test.api.gov.bc.ca",
85+
"sessionCookieEnabled": False,
86+
"dataClass": "high",
87+
"dataPlane": "test-dp",
88+
"sslCertificateId": "default",
89+
"certificates": None
90+
}]
91+
}
92+
assert json.dumps(transform_data_by_ns(routes, certs, cert_snis)) == json.dumps(expected_value)
5293

5394
def test_happy_transform_data_by_ns_with_custom_domain():
5495
with mock.patch('clients.namespace.admin_api') as mock_admin_api:
@@ -63,7 +104,18 @@ def test_happy_transform_data_by_ns_with_custom_domain():
63104
]
64105
}
65106
]
66-
snis = [
107+
certs = [
108+
{
109+
"id": "41d14845-669f-4dcd-aff2-926fb32a4b25",
110+
"cert": "CERT",
111+
"created_at": 1731713874,
112+
"tags": [
113+
"ns.ns1"
114+
],
115+
"key": "KEY",
116+
}
117+
]
118+
cert_snis = [
67119
{
68120
"name": "test.custom.gov.bc.ca",
69121
"id": "79009c9e-0f4d-40b5-9707-bf2fe9f50502",
@@ -74,7 +126,32 @@ def test_happy_transform_data_by_ns_with_custom_domain():
74126
]
75127
}
76128
]
77-
assert json.dumps(transform_data_by_ns(routes, snis)) == '{"ns1": [{"name": "wild-ns-ns1-test.custom.gov.bc.ca", "selectTag": "ns.ns1", "host": "test.custom.gov.bc.ca", "sessionCookieEnabled": false, "dataClass": null, "dataPlane": "test-dp", "sslCertificateId": "41d14845-669f-4dcd-aff2-926fb32a4b25"}]}'
129+
expected_value = {
130+
"ns1": [{
131+
"name": "wild-ns-ns1-test.custom.gov.bc.ca",
132+
"selectTag": "ns.ns1",
133+
"host": "test.custom.gov.bc.ca",
134+
"sessionCookieEnabled": False,
135+
"dataClass": None,
136+
"dataPlane": "test-dp",
137+
"sslCertificateId": "41d14845-669f-4dcd-aff2-926fb32a4b25",
138+
"certificates": [
139+
{
140+
"id": "41d14845-669f-4dcd-aff2-926fb32a4b25",
141+
"cert": "CERT",
142+
"created_at": 1731713874,
143+
"tags": [
144+
"ns.ns1"
145+
],
146+
"key": "KEY",
147+
"snis": [
148+
"test.custom.gov.bc.ca"
149+
]
150+
}
151+
]
152+
}]
153+
}
154+
assert json.dumps(transform_data_by_ns(routes, certs, cert_snis)) == json.dumps(expected_value)
78155

79156

80157
def set_mock_admin_api_response(dt):

microservices/kubeApi/clients/ocp_routes.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,8 @@ def prepare_apply_routes(ns, select_tag, hosts, root_path, data_plane, ns_templa
198198
logger.debug("[%s] Route A %03d Found custom cert with SNI match for %s" % (select_tag, index, host))
199199
custom_cert_found = True
200200
break
201-
if not custom_cert_found:
202-
raise Exception("Custom certificate not found for host %s" % host)
201+
if not custom_cert_found:
202+
raise Exception("Custom certificate not found for host %s" % host)
203203

204204
if not custom_cert_found and not settings.host_transformation['enabled']:
205205
# Fall back to existing cert mapping logic
@@ -256,7 +256,8 @@ def is_host_custom_domain(host):
256256
'.maps.gov.bc.ca',
257257
'.openmaps.gov.bc.ca',
258258
'.apps.gov.bc.ca',
259-
'.apis.gov.bc.ca'
259+
'.apis.gov.bc.ca',
260+
'.test'
260261
]
261262

262263
# Check if the host is one of the standard cert domains or a subdomain of them

microservices/kubeApi/routers/routes.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,8 @@ async def verify_and_create_routes(namespace: str, request: Request):
212212
overrides[f'aps.route.dataclass.{route["dataClass"]}'] = [route['host']]
213213

214214
route_count = prepare_apply_routes(namespace, route['selectTag'], [
215-
route['host']], source_folder, route["dataPlane"], ns_template_version, overrides)
215+
route['host']], source_folder, route['dataPlane'], ns_template_version, overrides,
216+
route['certificates'])
216217

217218
logger.debug("[%s] - Prepared %d routes" % (namespace, route_count))
218219
apply_routes(source_folder)

microservices/kubeApi/tests/clients/test_ocp_routes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def test_prepare_apply_routes():
112112

113113
ns = "NS1"
114114
select_tag = "ns.NS1"
115-
hosts = [ "host1", "host2" ]
115+
hosts = [ "host1.test", "host2.test" ]
116116
root_path = "/tmp"
117117
data_plane = "test-dp"
118118
ns_template_version = "v2"

microservices/kubeApi/tests/routers/test_bulk_sync.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ def test_bulk_sync_change_host(client):
8282
"host": "abc.api.gov.bc.ca",
8383
"sessionCookieEnabled": False,
8484
"dataClass": None,
85-
"sslCertificateId": "default"
85+
"sslCertificateId": "default",
86+
"certificates": []
8687
}]
8788
response = client.post('/namespaces/examplens/routes/sync', json=data)
8889
assert response.status_code == 200

microservices/kubeApi/tests/routers/test_bulk_sync_new_route.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ def test_bulk_sync_new_route(client):
7777
"host": "abc.api.gov.bc.ca",
7878
"sessionCookieEnabled": False,
7979
"dataClass": None,
80-
"sslCertificateId": "default"
80+
"sslCertificateId": "default",
81+
"certificates": []
8182
}]
8283
response = client.post('/namespaces/examplens/routes/sync', json=data)
8384
assert response.status_code == 200

0 commit comments

Comments
 (0)