From ec2a324a84089571b6e3b1f615cce92045f61b7c Mon Sep 17 00:00:00 2001 From: PedroHMCosme Date: Mon, 13 Jul 2026 19:20:41 -0300 Subject: [PATCH] feat(gateway): cert provider from MinIO+Mongo (sientia-dataops) --- ingestor/connection/certs.py | 29 +++++++++++++++++++++++++++++ tests/unit/connection/test_certs.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 ingestor/connection/certs.py create mode 100644 tests/unit/connection/test_certs.py diff --git a/ingestor/connection/certs.py b/ingestor/connection/certs.py new file mode 100644 index 0000000..71dc762 --- /dev/null +++ b/ingestor/connection/certs.py @@ -0,0 +1,29 @@ +from pathlib import Path + +COLLECTION_NAME = 'platform_certificates' + + +class CertProvider: + """Downloads the platform's client cert + private key (Mongo metadata, + MinIO bytes) into a writable cache dir — pod root FS is read-only (§12), + so `cache_dir` must be an emptyDir/tmpfs mount.""" + + def __init__(self, mongo, minio, cache_dir: str, bucket: str, metadata: dict | None = None): + self.mongo = mongo + self.minio = minio + self.cache_dir = cache_dir + self.bucket = bucket + self.metadata = metadata or {} + + async def fetch(self) -> tuple[str, str]: + doc = await self.mongo.find_one(COLLECTION_NAME, {}, self.metadata) + Path(self.cache_dir).mkdir(parents=True, exist_ok=True) + cert_path = await self._download(doc['client_cert']['minio_object_name']) + key_path = await self._download(doc['private_key']['minio_object_name']) + return cert_path, key_path + + async def _download(self, object_name: str) -> str: + data = await self.minio.download_file(object_name, self.bucket, self.metadata) + local_path = str(Path(self.cache_dir) / Path(object_name).name) + Path(local_path).write_bytes(data) + return local_path diff --git a/tests/unit/connection/test_certs.py b/tests/unit/connection/test_certs.py new file mode 100644 index 0000000..3b66c91 --- /dev/null +++ b/tests/unit/connection/test_certs.py @@ -0,0 +1,28 @@ +from unittest.mock import AsyncMock + +import pytest + +from ingestor.connection.certs import CertProvider + + +@pytest.mark.asyncio +async def test_fetch_returns_local_paths(tmp_path): + mongo = AsyncMock() + mongo.find_one.return_value = { + 'client_cert': {'minio_object_name': 'platform/certificates/client_cert_c.pem'}, + 'private_key': {'minio_object_name': 'platform/certificates/private_key_k.pem'}, + } + minio = AsyncMock() + minio.download_file.side_effect = [b'cert-bytes', b'key-bytes'] + + provider = CertProvider(mongo, minio, cache_dir=str(tmp_path), bucket='sientia-dataops') + cert, key = await provider.fetch() + + assert cert.endswith('c.pem') and key.endswith('k.pem') + assert minio.download_file.await_count == 2 + mongo.find_one.assert_awaited_once_with('platform_certificates', {}, {}) + minio.download_file.assert_any_await( + 'platform/certificates/client_cert_c.pem', 'sientia-dataops', {} + ) + assert (tmp_path / 'client_cert_c.pem').read_bytes() == b'cert-bytes' + assert (tmp_path / 'private_key_k.pem').read_bytes() == b'key-bytes'