Skip to content

Commit 64dae88

Browse files
committed
LITE-33682 Ensure certs temp folders are created once
1 parent 42a14e6 commit 64dae88

2 files changed

Lines changed: 164 additions & 23 deletions

File tree

connect/eaas/core/egress_proxy.py

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,15 @@ def __init__(
2727
certificates: EgressProxyCertificates,
2828
):
2929
self.proxy = proxy
30-
self.cert_file = self._create_temp_cert_file(certificates.client_cert)
31-
self.key_file = self._create_temp_cert_file(certificates.client_key)
32-
self.ca_file = self._create_temp_cert_file(certificates.ca_cert)
30+
self.cert_file = self._create_cert_file(
31+
'client_cert.pem', certificates.client_cert,
32+
)
33+
self.key_file = self._create_cert_file(
34+
'client_key.pem', certificates.client_key,
35+
)
36+
self.ca_file = self._create_cert_file(
37+
'ca_cert.pem', certificates.ca_cert,
38+
)
3339

3440
super().__init__(
3541
endpoint=self.proxy.url,
@@ -39,16 +45,24 @@ def __init__(
3945
)
4046

4147
@staticmethod
42-
def _create_temp_cert_file(cert_content):
43-
"""Create a temporary file with certificate content."""
44-
temp_file = tempfile.NamedTemporaryFile(
45-
mode='w',
46-
delete=False,
47-
suffix='.pem',
48-
)
49-
temp_file.write(cert_content)
50-
temp_file.close()
51-
return temp_file.name
48+
def _create_cert_file(filename, cert_content):
49+
"""
50+
Create or reuse a certificate file at a fixed location.
51+
52+
Uses /tmp/<filename> as a stable path. Only writes if the
53+
file doesn't exist or its content has changed.
54+
"""
55+
filepath = os.path.join(tempfile.gettempdir(), filename)
56+
57+
if os.path.exists(filepath):
58+
with open(filepath, 'r') as f:
59+
if f.read() == cert_content:
60+
return filepath
61+
62+
with open(filepath, 'w') as f:
63+
f.write(cert_content)
64+
65+
return filepath
5266

5367
@classmethod
5468
def require_proxy(cls, account_id: str):

tests/connect/eaas/core/test_egress_proxy.py

Lines changed: 137 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -596,18 +596,20 @@ def test_validate_headers_success_with_empty_headers_list(
596596
client._validate_headers(headers)
597597

598598

599-
# Tests for _create_temp_cert_file static method
599+
# Tests for _create_cert_file static method
600600

601601

602-
def test_create_temp_cert_file_creates_file():
603-
"""Test _create_temp_cert_file creates a temporary file."""
602+
def test_create_cert_file_creates_file():
603+
"""Test _create_cert_file creates a file at a fixed location."""
604604
cert_content = (
605605
'-----BEGIN CERTIFICATE-----\n'
606606
'TEST\n'
607607
'-----END CERTIFICATE-----'
608608
)
609609

610-
filepath = EgressProxyClient._create_temp_cert_file(cert_content)
610+
filepath = EgressProxyClient._create_cert_file(
611+
'test_cert.pem', cert_content,
612+
)
611613

612614
try:
613615
assert os.path.exists(filepath)
@@ -620,13 +622,107 @@ def test_create_temp_cert_file_creates_file():
620622
os.unlink(filepath)
621623

622624

623-
def test_create_temp_cert_file_multiple_calls_create_different_files():
624-
"""Test multiple calls create different temp files."""
625-
cert1 = '-----BEGIN CERTIFICATE-----\nCERT1\n-----END CERTIFICATE-----'
626-
cert2 = '-----BEGIN CERTIFICATE-----\nCERT2\n-----END CERTIFICATE-----'
625+
def test_create_cert_file_uses_deterministic_path():
626+
"""Test _create_cert_file returns the same path for same filename."""
627+
cert_content = (
628+
'-----BEGIN CERTIFICATE-----\n'
629+
'CERT\n'
630+
'-----END CERTIFICATE-----'
631+
)
632+
633+
filepath1 = EgressProxyClient._create_cert_file(
634+
'determ_cert.pem', cert_content,
635+
)
636+
filepath2 = EgressProxyClient._create_cert_file(
637+
'determ_cert.pem', cert_content,
638+
)
639+
640+
try:
641+
assert filepath1 == filepath2
642+
finally:
643+
if os.path.exists(filepath1):
644+
os.unlink(filepath1)
645+
646+
647+
def test_create_cert_file_writes_only_once():
648+
"""
649+
Test _create_cert_file writes the file only on first call.
650+
Subsequent calls with same content reuse existing file.
651+
"""
652+
filename = 'write_once_cert.pem'
653+
cert_content = (
654+
'-----BEGIN CERTIFICATE-----\n'
655+
'ONCE\n'
656+
'-----END CERTIFICATE-----'
657+
)
658+
filepath = EgressProxyClient._create_cert_file(
659+
filename, cert_content,
660+
)
661+
662+
try:
663+
mtime_before = os.path.getmtime(filepath)
664+
665+
EgressProxyClient._create_cert_file(
666+
filename, cert_content,
667+
)
668+
669+
mtime_after = os.path.getmtime(filepath)
670+
assert mtime_before == mtime_after
671+
finally:
672+
if os.path.exists(filepath):
673+
os.unlink(filepath)
674+
675+
676+
def test_create_cert_file_rewrites_when_content_changes():
677+
"""
678+
Test _create_cert_file rewrites the file when content changes.
679+
"""
680+
filename = 'rewrite_cert.pem'
681+
old_content = (
682+
'-----BEGIN CERTIFICATE-----\n'
683+
'OLD\n'
684+
'-----END CERTIFICATE-----'
685+
)
686+
new_content = (
687+
'-----BEGIN CERTIFICATE-----\n'
688+
'NEW\n'
689+
'-----END CERTIFICATE-----'
690+
)
691+
filepath = EgressProxyClient._create_cert_file(
692+
filename, old_content,
693+
)
694+
695+
try:
696+
EgressProxyClient._create_cert_file(
697+
filename, new_content,
698+
)
699+
700+
with open(filepath, 'r') as f:
701+
assert f.read() == new_content
702+
finally:
703+
if os.path.exists(filepath):
704+
os.unlink(filepath)
705+
706+
707+
def test_create_cert_file_different_names_create_different_files():
708+
"""Test different filenames create different files."""
709+
cert1 = (
710+
'-----BEGIN CERTIFICATE-----\n'
711+
'CERT1\n'
712+
'-----END CERTIFICATE-----'
713+
)
714+
cert2 = (
715+
'-----BEGIN CERTIFICATE-----\n'
716+
'CERT2\n'
717+
'-----END CERTIFICATE-----'
718+
)
627719

628-
filepath1 = EgressProxyClient._create_temp_cert_file(cert1)
629-
filepath2 = EgressProxyClient._create_temp_cert_file(cert2)
720+
filepath1 = EgressProxyClient._create_cert_file(
721+
'diff_cert1.pem', cert1,
722+
)
723+
filepath2 = EgressProxyClient._create_cert_file(
724+
'diff_cert2.pem', cert2,
725+
)
630726

631727
try:
632728
assert filepath1 != filepath2
@@ -645,6 +741,37 @@ def test_create_temp_cert_file_multiple_calls_create_different_files():
645741
os.unlink(filepath2)
646742

647743

744+
def test_cert_files_created_once_across_multiple_clients(
745+
egress_proxy, certificates, cleanup_client,
746+
):
747+
"""
748+
Test that creating multiple clients reuses existing cert files
749+
without rewriting them.
750+
"""
751+
client1 = cleanup_client(
752+
EgressProxyClient(
753+
proxy=egress_proxy, certificates=certificates,
754+
),
755+
)
756+
757+
mtime_cert = os.path.getmtime(client1.cert_file)
758+
mtime_key = os.path.getmtime(client1.key_file)
759+
mtime_ca = os.path.getmtime(client1.ca_file)
760+
761+
client2 = cleanup_client(
762+
EgressProxyClient(
763+
proxy=egress_proxy, certificates=certificates,
764+
),
765+
)
766+
767+
assert client1.cert_file == client2.cert_file
768+
assert client1.key_file == client2.key_file
769+
assert client1.ca_file == client2.ca_file
770+
assert os.path.getmtime(client2.cert_file) == mtime_cert
771+
assert os.path.getmtime(client2.key_file) == mtime_key
772+
assert os.path.getmtime(client2.ca_file) == mtime_ca
773+
774+
648775
@responses.activate
649776
def test_full_workflow_with_required_headers(
650777
env_vars, proxy_config, cleanup_client,

0 commit comments

Comments
 (0)