Skip to content

Commit

Permalink
scheduler: include certificate and sni from admin cache
Browse files Browse the repository at this point in the history
  • Loading branch information
rustyjux committed Nov 18, 2024
1 parent 630cfbd commit 1b904eb
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 29 deletions.
3 changes: 2 additions & 1 deletion microservices/gatewayApi/v2/routes/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,8 @@ def is_host_custom_domain(host):
'.maps.gov.bc.ca',
'.openmaps.gov.bc.ca',
'.apps.gov.bc.ca',
'.apis.gov.bc.ca'
'.apis.gov.bc.ca',
'.test'
]

# Check if the host is one of the standard cert domains or a subdomain of them
Expand Down
13 changes: 10 additions & 3 deletions microservices/gatewayJobScheduler/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

logger = logging.getLogger(__name__)

def transform_data_by_ns(routes, cert_snis):
def transform_data_by_ns(routes, certs, cert_snis):
ns_svc = NamespaceService()
try:
ns_dict = {}
Expand Down Expand Up @@ -35,6 +35,7 @@ def transform_data_by_ns(routes, cert_snis):

for host in route_obj['hosts']:
# Look for a matching certificate by SNI for custom domains
cert = None
cert_id = 'default'
custom_cert_found = False
if is_host_custom_domain(host):
Expand All @@ -45,6 +46,10 @@ def transform_data_by_ns(routes, cert_snis):
cert_id = sni['certificate']
logger.debug("%s - Found custom cert with SNI match for %s - %s" % (namespace, host, cert_id))
custom_cert_found = True
cert = next((cert for cert in certs if cert['id'] == cert_id), None)
if cert is None:
raise Exception("Certificate not found for id %s" % cert_id)
cert['snis'] = [host]
break
if not custom_cert_found:
raise Exception("Custom certificate not found for host %s" % host)
Expand All @@ -54,7 +59,8 @@ def transform_data_by_ns(routes, cert_snis):
"sessionCookieEnabled": session_cookie_enabled,
"dataClass": data_class,
"dataPlane": os.getenv('DATA_PLANE'),
"sslCertificateId": cert_id})
"sslCertificateId": cert_id,
"certificates": [cert] if cert is not None else None})
return ns_dict
except Exception as err:
traceback.print_exc()
Expand All @@ -78,7 +84,8 @@ def is_host_custom_domain(host):
'.maps.gov.bc.ca',
'.openmaps.gov.bc.ca',
'.apps.gov.bc.ca',
'.apis.gov.bc.ca'
'.apis.gov.bc.ca',
'.test'
]

# Check if the host is one of the standard cert domains or a subdomain of them
Expand Down
6 changes: 3 additions & 3 deletions microservices/gatewayJobScheduler/clients/kong.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def get_records(record_type):
Get all records of a specified type from Kong Admin API.
Args:
record_type (str): Type of records to fetch ('routes' or 'snis')
record_type (str): Type of records to fetch ('routes', 'certificates' or 'snis')
Returns:
list: List of records
Expand All @@ -20,8 +20,8 @@ def get_records(record_type):
OSError: If the shell command fails
ValueError: If invalid record_type is provided
"""
if record_type not in ['routes', 'snis']:
raise ValueError("record_type must be either 'routes' or 'snis'")
if record_type not in ['routes', 'certificates', 'snis']:
raise ValueError("record_type must be either 'routes', 'certificates' or 'snis'")

endpoint = "/%s" % record_type
records_list = []
Expand Down
3 changes: 2 additions & 1 deletion microservices/gatewayJobScheduler/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ def sync_routes():
}
try:
routes = get_records('routes')
certs = get_records('certificates')
cert_snis = get_records('snis')
except:
traceback.print_exc()
logger.error('Failed to get existing routes - %s' % (exc_info()[0]))
clear('sync-routes')
exit(1)

data = transform_data_by_ns(routes, cert_snis)
data = transform_data_by_ns(routes, certs, cert_snis)
for ns in data:
url = os.getenv('KUBE_API_URL') + '/namespaces/%s/routes/sync' % ns
response = requests.post(url, headers=headers, json=data[ns], auth=(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,23 @@ def test_happy_transform_data_by_ns():
]
}
]
snis = []
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"}]}'
certs = []
cert_snis = []
expected_value = {
"ns1": [
{
"name": "wild-ns-ns1-test.api.gov.bc.ca",
"selectTag": "ns.ns1",
"host": "test.api.gov.bc.ca",
"sessionCookieEnabled": False,
"dataClass": None,
"dataPlane": "test-dp",
"sslCertificateId": "default",
"certificates": None
}
]
}
assert json.dumps(transform_data_by_ns(routes, certs, cert_snis)) == json.dumps(expected_value)

def test_happy_transform_data_by_ns_with_override_session_cookie():
with mock.patch('clients.namespace.admin_api') as mock_admin_api:
Expand All @@ -31,8 +46,21 @@ def test_happy_transform_data_by_ns_with_override_session_cookie():
]
}
]
snis = []
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"}]}'
certs = []
cert_snis = []
expected_value = {
"ns1": [{
"name": "wild-ns-ns1-test.api.gov.bc.ca",
"selectTag": "ns.ns1",
"host": "test.api.gov.bc.ca",
"sessionCookieEnabled": True,
"dataClass": None,
"dataPlane": "test-dp",
"sslCertificateId": "default",
"certificates": None
}]
}
assert json.dumps(transform_data_by_ns(routes, certs, cert_snis)) == json.dumps(expected_value)

def test_happy_transform_data_by_ns_with_override_data_plane():
with mock.patch('clients.namespace.admin_api') as mock_admin_api:
Expand All @@ -47,8 +75,21 @@ def test_happy_transform_data_by_ns_with_override_data_plane():
]
}
]
snis = []
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"}]}'
certs = []
cert_snis = []
expected_value = {
"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",
"certificates": None
}]
}
assert json.dumps(transform_data_by_ns(routes, certs, cert_snis)) == json.dumps(expected_value)

def test_happy_transform_data_by_ns_with_custom_domain():
with mock.patch('clients.namespace.admin_api') as mock_admin_api:
Expand All @@ -63,7 +104,18 @@ def test_happy_transform_data_by_ns_with_custom_domain():
]
}
]
snis = [
certs = [
{
"id": "41d14845-669f-4dcd-aff2-926fb32a4b25",
"cert": "CERT",
"created_at": 1731713874,
"tags": [
"ns.ns1"
],
"key": "KEY",
}
]
cert_snis = [
{
"name": "test.custom.gov.bc.ca",
"id": "79009c9e-0f4d-40b5-9707-bf2fe9f50502",
Expand All @@ -74,7 +126,32 @@ def test_happy_transform_data_by_ns_with_custom_domain():
]
}
]
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"}]}'
expected_value = {
"ns1": [{
"name": "wild-ns-ns1-test.custom.gov.bc.ca",
"selectTag": "ns.ns1",
"host": "test.custom.gov.bc.ca",
"sessionCookieEnabled": False,
"dataClass": None,
"dataPlane": "test-dp",
"sslCertificateId": "41d14845-669f-4dcd-aff2-926fb32a4b25",
"certificates": [
{
"id": "41d14845-669f-4dcd-aff2-926fb32a4b25",
"cert": "CERT",
"created_at": 1731713874,
"tags": [
"ns.ns1"
],
"key": "KEY",
"snis": [
"test.custom.gov.bc.ca"
]
}
]
}]
}
assert json.dumps(transform_data_by_ns(routes, certs, cert_snis)) == json.dumps(expected_value)


def set_mock_admin_api_response(dt):
Expand Down
7 changes: 4 additions & 3 deletions microservices/kubeApi/clients/ocp_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ def prepare_apply_routes(ns, select_tag, hosts, root_path, data_plane, ns_templa
logger.debug("[%s] Route A %03d Found custom cert with SNI match for %s" % (select_tag, index, host))
custom_cert_found = True
break
if not custom_cert_found:
raise Exception("Custom certificate not found for host %s" % host)
if not custom_cert_found:
raise Exception("Custom certificate not found for host %s" % host)

if not custom_cert_found and not settings.host_transformation['enabled']:
# Fall back to existing cert mapping logic
Expand Down Expand Up @@ -256,7 +256,8 @@ def is_host_custom_domain(host):
'.maps.gov.bc.ca',
'.openmaps.gov.bc.ca',
'.apps.gov.bc.ca',
'.apis.gov.bc.ca'
'.apis.gov.bc.ca',
'.test'
]

# Check if the host is one of the standard cert domains or a subdomain of them
Expand Down
3 changes: 2 additions & 1 deletion microservices/kubeApi/routers/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ async def verify_and_create_routes(namespace: str, request: Request):
overrides[f'aps.route.dataclass.{route["dataClass"]}'] = [route['host']]

route_count = prepare_apply_routes(namespace, route['selectTag'], [
route['host']], source_folder, route["dataPlane"], ns_template_version, overrides)
route['host']], source_folder, route['dataPlane'], ns_template_version, overrides,
route['certificates'])

logger.debug("[%s] - Prepared %d routes" % (namespace, route_count))
apply_routes(source_folder)
Expand Down
2 changes: 1 addition & 1 deletion microservices/kubeApi/tests/clients/test_ocp_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def test_prepare_apply_routes():

ns = "NS1"
select_tag = "ns.NS1"
hosts = [ "host1", "host2" ]
hosts = [ "host1.test", "host2.test" ]
root_path = "/tmp"
data_plane = "test-dp"
ns_template_version = "v2"
Expand Down
3 changes: 2 additions & 1 deletion microservices/kubeApi/tests/routers/test_bulk_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ def test_bulk_sync_change_host(client):
"host": "abc.api.gov.bc.ca",
"sessionCookieEnabled": False,
"dataClass": None,
"sslCertificateId": "default"
"sslCertificateId": "default",
"certificates": []
}]
response = client.post('/namespaces/examplens/routes/sync', json=data)
assert response.status_code == 200
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ def test_bulk_sync_new_route(client):
"host": "abc.api.gov.bc.ca",
"sessionCookieEnabled": False,
"dataClass": None,
"sslCertificateId": "default"
"sslCertificateId": "default",
"certificates": []
}]
response = client.post('/namespaces/examplens/routes/sync', json=data)
assert response.status_code == 200
Expand Down
18 changes: 12 additions & 6 deletions microservices/kubeApi/tests/routers/test_bulk_sync_override.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ def test_bulk_sync_new_route_session_cookie(client):
"host": "abc.api.gov.bc.ca",
"sessionCookieEnabled": True,
"dataClass": None,
"sslCertificateId": "default"
"sslCertificateId": "default",
"certificates": []
}]
response = client.post('/namespaces/examplens/routes/sync', json=data)
assert response.status_code == 200
Expand Down Expand Up @@ -158,7 +159,8 @@ def test_bulk_sync_change_session_cookie(client):
"host": "abc.api.gov.bc.ca",
"sessionCookieEnabled": True,
"dataClass": None,
"sslCertificateId": "default"
"sslCertificateId": "default",
"certificates": []
}]
response = client.post('/namespaces/examplens/routes/sync', json=data)
assert response.status_code == 200
Expand Down Expand Up @@ -242,7 +244,8 @@ def test_bulk_sync_new_route_data_class(client):
"host": "abc.api.gov.bc.ca",
"sessionCookieEnabled": False,
"dataClass": "high",
"sslCertificateId": "default"
"sslCertificateId": "default",
"certificates": []
}]
response = client.post('/namespaces/examplens/routes/sync', json=data)
assert response.status_code == 200
Expand Down Expand Up @@ -288,7 +291,8 @@ def test_bulk_sync_add_data_class(client):
"host": "abc.api.gov.bc.ca",
"sessionCookieEnabled": False,
"dataClass": "high",
"sslCertificateId": "default"
"sslCertificateId": "default",
"certificates": []
}]
response = client.post('/namespaces/examplens/routes/sync', json=data)
assert response.status_code == 200
Expand Down Expand Up @@ -336,7 +340,8 @@ def test_bulk_sync_remove_data_class(client):
"host": "abc.api.gov.bc.ca",
"sessionCookieEnabled": True,
"dataClass": None,
"sslCertificateId": "default"
"sslCertificateId": "default",
"certificates": []
}]
response = client.post('/namespaces/examplens/routes/sync', json=data)
assert response.status_code == 200
Expand Down Expand Up @@ -384,7 +389,8 @@ def test_bulk_sync_change_data_class(client):
"host": "abc.api.gov.bc.ca",
"sessionCookieEnabled": False,
"dataClass": "high",
"sslCertificateId": "default"
"sslCertificateId": "default",
"certificates": []
}]
response = client.post('/namespaces/examplens/routes/sync', json=data)
assert response.status_code == 200
Expand Down

0 comments on commit 1b904eb

Please sign in to comment.