Skip to content

Commit 7e9c937

Browse files
authored
#99: Setting correct parameters in a BFS connection object (#100)
* #99 Setting correct parameters in a BFS connection object * #99 Fixed typing issue picked by mypy * #99 Fixed typing issue picked by mypy * #99 Changed the logic of setting the cert. verification in a connection object.
1 parent 40cd8ae commit 7e9c937

File tree

3 files changed

+103
-7
lines changed

3 files changed

+103
-7
lines changed

doc/changes/changes_0.2.9.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ Post-release fixes.
1212
* #89: Connecting a new AI-Lab container to the Docker DB network when the latter container restarts.
1313
* #93: Refactoring the ITDE manager interface.
1414
* #94: Adding an integration test for restart_itde() in a container.
15-
* #95: Adding an integration test for get_itde_status() in a container.
15+
* #95: Adding an integration test for get_itde_status() in a container.
16+
* #99: Setting the correct protocol and TLS certificate verification option when creating a
17+
connection object with BucketFS credentials.

exasol/nb_connector/extension_wrapper_common.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from __future__ import annotations
2+
from typing import Optional
3+
14
from exasol.nb_connector.connections import open_pyexasol_connection
25
from exasol.nb_connector.secret_store import Secrets
36
from exasol.nb_connector.utils import optional_str_to_bool
@@ -40,19 +43,30 @@ def encapsulate_bucketfs_credentials(
4043
Path identifying a location in the bucket.
4144
connection_name:
4245
Name for the connection object to be created.
46+
47+
A note about handling the TLS certificate verification settings.
48+
If the server certificate verification is turned on, either through
49+
reliance of the default https request settings or by setting the cert_vld
50+
configuration parameter to True, this intention will be passed to
51+
the connection object. However, if the user specifies a custom CA list
52+
file or directory, which also implies the certificate verification,
53+
the connection object will instead turn the verification off. This is
54+
because there is no guarantee that the consumer of the connection object,
55+
i.e. a UDF, would have this custom CA list, and even if it would, its location
56+
is unknown.
4357
"""
4458

4559
bfs_host = conf.get(CKey.bfs_host_name, conf.get(CKey.db_host_name))
46-
# For now, just use the http. Once the exasol.bucketfs is capable of using
47-
# the https without validating the server certificate choose between the
48-
# http and https depending on the bfs_encryption setting, like this:
49-
# bfs_protocol = "https" if str_to_bool(conf, CKey.bfs_encryption, True)
50-
# else "http"
51-
bfs_protocol = "http"
60+
bfs_protocol = "https" if str_to_bool(conf, CKey.bfs_encryption, True) else "http"
5261
bfs_dest = (
5362
f"{bfs_protocol}://{bfs_host}:{conf.get(CKey.bfs_port)}/"
5463
f"{conf.get(CKey.bfs_bucket)}/{path_in_bucket};{conf.get(CKey.bfs_service)}"
5564
)
65+
# TLS certificate verification option shall be provided in the fragment field.
66+
verify: Optional[bool] = (False if conf.get(CKey.trusted_ca)
67+
else optional_str_to_bool(conf.get(CKey.cert_vld)))
68+
if verify is not None:
69+
bfs_dest += f'#{verify}'
5670

5771
sql = f"""
5872
CREATE OR REPLACE CONNECTION [{connection_name}]
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import unittest.mock
2+
import pytest
3+
import tempfile
4+
5+
from exasol.nb_connector.secret_store import Secrets
6+
from exasol.nb_connector.ai_lab_config import AILabConfig as CKey
7+
from exasol.nb_connector.extension_wrapper_common import encapsulate_bucketfs_credentials
8+
9+
10+
@pytest.fixture
11+
def filled_secrets(secrets) -> Secrets:
12+
secrets.save(CKey.db_host_name, 'localhost')
13+
secrets.save(CKey.db_port, '8888')
14+
secrets.save(CKey.db_user, 'user')
15+
secrets.save(CKey.db_password, 'password')
16+
secrets.save(CKey.bfs_port, '6666')
17+
secrets.save(CKey.bfs_encryption, 'True')
18+
secrets.save(CKey.bfs_service, 'bfsdefault')
19+
secrets.save(CKey.bfs_bucket, 'default')
20+
secrets.save(CKey.bfs_user, 'user'),
21+
secrets.save(CKey.bfs_password, 'password')
22+
return secrets
23+
24+
25+
@unittest.mock.patch("pyexasol.connect")
26+
def test_bucketfs_credentials_default(mock_connect, filled_secrets):
27+
28+
path_in_bucket = 'location'
29+
30+
mock_connection = unittest.mock.MagicMock()
31+
mock_connection.__enter__.return_value = mock_connection
32+
mock_connect.return_value = mock_connection
33+
34+
encapsulate_bucketfs_credentials(filled_secrets, path_in_bucket=path_in_bucket,
35+
connection_name='whatever')
36+
expected_url = f"https://localhost:6666/default/{path_in_bucket};bfsdefault"
37+
38+
mock_connection.execute.assert_called_once()
39+
query = mock_connection.execute.call_args_list[0].kwargs['query']
40+
assert f"TO '{expected_url}'" in query
41+
42+
43+
@unittest.mock.patch("pyexasol.connect")
44+
def test_bucketfs_credentials_verify(mock_connect, filled_secrets):
45+
46+
path_in_bucket = 'location'
47+
filled_secrets.save(CKey.cert_vld, 'yes')
48+
49+
mock_connection = unittest.mock.MagicMock()
50+
mock_connection.__enter__.return_value = mock_connection
51+
mock_connect.return_value = mock_connection
52+
53+
encapsulate_bucketfs_credentials(filled_secrets, path_in_bucket=path_in_bucket,
54+
connection_name='whatever')
55+
expected_url = f"https://localhost:6666/default/{path_in_bucket};bfsdefault#True"
56+
57+
mock_connection.execute.assert_called_once()
58+
query = mock_connection.execute.call_args_list[0].kwargs['query']
59+
assert f"TO '{expected_url}'" in query
60+
61+
62+
@unittest.mock.patch("pyexasol.connect")
63+
def test_bucketfs_credentials_ca(mock_connect, filled_secrets):
64+
65+
with tempfile.NamedTemporaryFile() as f:
66+
path_in_bucket = 'location'
67+
filled_secrets.save(CKey.trusted_ca, f.name)
68+
filled_secrets.save(CKey.cert_vld, 'yes')
69+
70+
mock_connection = unittest.mock.MagicMock()
71+
mock_connection.__enter__.return_value = mock_connection
72+
mock_connect.return_value = mock_connection
73+
74+
encapsulate_bucketfs_credentials(filled_secrets, path_in_bucket=path_in_bucket,
75+
connection_name='whatever')
76+
expected_url = f"https://localhost:6666/default/{path_in_bucket};bfsdefault#False"
77+
78+
mock_connection.execute.assert_called_once()
79+
query = mock_connection.execute.call_args_list[0].kwargs['query']
80+
assert f"TO '{expected_url}'" in query

0 commit comments

Comments
 (0)