Skip to content

Commit 9518b39

Browse files
authored
feat: Sender(..., tls=True) now also uses OS-provided certificate store. (#55)
1 parent 5646700 commit 9518b39

File tree

5 files changed

+40
-17
lines changed

5 files changed

+40
-17
lines changed

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ def ingress_extension():
6161
if PLATFORM == 'darwin':
6262
lib_prefix = 'lib'
6363
lib_suffix = '.a'
64-
extra_link_args.extend(['-framework', 'Security'])
64+
extra_link_args.extend(['-framework', 'Security', '-framework', 'CoreFoundation'])
6565
elif PLATFORM == 'win32':
6666
lib_prefix = ''
6767
lib_suffix = '.lib'
68-
libraries.extend(['wsock32', 'ws2_32', 'ntdll', 'AdvAPI32', 'bcrypt', 'UserEnv'])
68+
libraries.extend(['wsock32', 'ws2_32', 'ntdll', 'AdvAPI32', 'bcrypt', 'UserEnv', 'crypt32', 'Secur32', 'NCrypt'])
6969
elif PLATFORM == 'linux':
7070
lib_prefix = 'lib'
7171
lib_suffix = '.a'

src/questdb/ingress.pyx

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,13 +1288,24 @@ cdef class Sender:
12881288
* ``False``: No TLS encryption (default).
12891289
12901290
* ``True``: TLS encryption, accepting all common certificates as recognized
1291-
by the `webpki-roots <https://crates.io/crates/webpki-roots>`_ Rust crate
1292-
which in turn relies on https://mkcert.org/.
1291+
by either the `webpki-roots <https://crates.io/crates/webpki-roots>`_ Rust
1292+
crate (which in turn relies on https://mkcert.org/), or the OS-provided
1293+
certificate store.
12931294
12941295
* A ``str`` or ``pathlib.Path``: Path to a PEM-encoded certificate authority
12951296
file. This is useful for testing with self-signed certificates.
12961297
1297-
* A special ``'insecure_skip_verify'`` string: Dangerously disable all
1298+
* The special ``'os_roots'`` string: Use the OS-provided certificate store.
1299+
1300+
* The special ``'webpki_roots'`` string: Use the `webpki-roots
1301+
<https://crates.io/crates/webpki-roots>`_ Rust crate to recognize
1302+
certificates.
1303+
1304+
* The special ``'webpki_and_os_roots'`` string: Use both the `webpki-roots
1305+
<https://crates.io/crates/webpki-roots>`_ Rust crate and the OS-provided
1306+
certificate store to recognize certificates. (equivalent to `True`).
1307+
1308+
* The special ``'insecure_skip_verify'`` string: Dangerously disable all
12981309
TLS certificate verification (do *NOT* use in production environments).
12991310
13001311
**Positional constructor arguments for the Sender(..)**
@@ -1433,9 +1444,15 @@ cdef class Sender:
14331444

14341445
if tls:
14351446
if tls is True:
1436-
line_sender_opts_tls(self._opts)
1447+
line_sender_opts_tls_webpki_and_os_roots(self._opts)
14371448
elif isinstance(tls, str):
1438-
if tls == 'insecure_skip_verify':
1449+
if tls == 'webpki_roots':
1450+
line_sender_opts_tls(self._opts)
1451+
elif tls == 'os_roots':
1452+
line_sender_opts_tls_os_roots(self._opts)
1453+
elif tls == 'webpki_and_os_roots':
1454+
line_sender_opts_tls_webpki_and_os_roots(self._opts)
1455+
elif tls == 'insecure_skip_verify':
14391456
line_sender_opts_tls_insecure_skip_verify(self._opts)
14401457
else:
14411458
str_to_utf8(b, <PyObject*>tls, &ca_utf8)

src/questdb/line_sender.pxd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ cdef extern from "questdb/ingress/line_sender.h":
103103

104104
void line_sender_opts_tls(line_sender_opts *opts) noexcept nogil
105105

106+
void line_sender_opts_tls_os_roots(line_sender_opts *opts) noexcept nogil
107+
108+
void line_sender_opts_tls_webpki_and_os_roots(line_sender_opts *opts) noexcept nogil
109+
106110
void line_sender_opts_tls_ca(line_sender_opts *opts, line_sender_utf8 ca_path) noexcept nogil
107111

108112
void line_sender_opts_tls_insecure_skip_verify(line_sender_opts *opts) noexcept nogil

test/test_dataframe.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,8 @@ def test_no_table_name(self):
8181
'Must specify at least one of'):
8282
_dataframe(DF1)
8383

84-
# TODO: Fix me and re-enable me!
85-
def _test_bad_table_name_type(self):
86-
with self.assertRaisesRegex(qi.IngressError, 'Must be str'):
84+
def test_bad_table_name_type(self):
85+
with self.assertRaisesRegex(TypeError, "'table_name' has incorrect type"):
8786
_dataframe(DF1, table_name=1.5)
8887

8988
def test_invalid_table_name(self):
@@ -808,8 +807,7 @@ def test_datetime64_numpy_col(self):
808807
'tbl1 a=1000000t\n' +
809808
'tbl1 a=2000000t\n')
810809

811-
# TODO: Fix me and re-enable me!
812-
def _test_datetime64_tz_arrow_col(self):
810+
def test_datetime64_tz_arrow_col(self):
813811
df = pd.DataFrame({
814812
'a': [
815813
pd.Timestamp(
@@ -879,10 +877,14 @@ def _test_datetime64_tz_arrow_col(self):
879877
year=1900, month=1, day=1,
880878
hour=0, minute=0, second=0, tz=_TZ)],
881879
'b': ['sym1']})
882-
with self.assertRaisesRegex(
883-
qi.IngressError, "Failed.*'a'.*-220897.* is negative."):
884-
_dataframe(df2, table_name='tbl1', symbols=['b'])
885-
return ###############################################################
880+
buf = _dataframe(df2, table_name='tbl1', symbols=['b'])
881+
882+
# Accounting for different datatime library differences.
883+
# Mostly, here assert that negative timestamps are allowed.
884+
self.assertIn(
885+
buf,
886+
['tbl1,b=sym1 a=-2208970800000000t\n',
887+
'tbl1,b=sym1 a=-2208971040000000t\n'])
886888

887889
def test_datetime64_numpy_at(self):
888890
df = pd.DataFrame({

0 commit comments

Comments
 (0)