Skip to content

Commit

Permalink
#99: Setting correct parameters in a BFS connection object (#100)
Browse files Browse the repository at this point in the history
* #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.
  • Loading branch information
ahsimb authored May 3, 2024
1 parent 40cd8ae commit 7e9c937
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 7 deletions.
4 changes: 3 additions & 1 deletion doc/changes/changes_0.2.9.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ Post-release fixes.
* #89: Connecting a new AI-Lab container to the Docker DB network when the latter container restarts.
* #93: Refactoring the ITDE manager interface.
* #94: Adding an integration test for restart_itde() in a container.
* #95: Adding an integration test for get_itde_status() in a container.
* #95: Adding an integration test for get_itde_status() in a container.
* #99: Setting the correct protocol and TLS certificate verification option when creating a
connection object with BucketFS credentials.
26 changes: 20 additions & 6 deletions exasol/nb_connector/extension_wrapper_common.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from __future__ import annotations
from typing import Optional

from exasol.nb_connector.connections import open_pyexasol_connection
from exasol.nb_connector.secret_store import Secrets
from exasol.nb_connector.utils import optional_str_to_bool
Expand Down Expand Up @@ -40,19 +43,30 @@ def encapsulate_bucketfs_credentials(
Path identifying a location in the bucket.
connection_name:
Name for the connection object to be created.
A note about handling the TLS certificate verification settings.
If the server certificate verification is turned on, either through
reliance of the default https request settings or by setting the cert_vld
configuration parameter to True, this intention will be passed to
the connection object. However, if the user specifies a custom CA list
file or directory, which also implies the certificate verification,
the connection object will instead turn the verification off. This is
because there is no guarantee that the consumer of the connection object,
i.e. a UDF, would have this custom CA list, and even if it would, its location
is unknown.
"""

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

sql = f"""
CREATE OR REPLACE CONNECTION [{connection_name}]
Expand Down
80 changes: 80 additions & 0 deletions test/unit/test_extension_wrapper_common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import unittest.mock
import pytest
import tempfile

from exasol.nb_connector.secret_store import Secrets
from exasol.nb_connector.ai_lab_config import AILabConfig as CKey
from exasol.nb_connector.extension_wrapper_common import encapsulate_bucketfs_credentials


@pytest.fixture
def filled_secrets(secrets) -> Secrets:
secrets.save(CKey.db_host_name, 'localhost')
secrets.save(CKey.db_port, '8888')
secrets.save(CKey.db_user, 'user')
secrets.save(CKey.db_password, 'password')
secrets.save(CKey.bfs_port, '6666')
secrets.save(CKey.bfs_encryption, 'True')
secrets.save(CKey.bfs_service, 'bfsdefault')
secrets.save(CKey.bfs_bucket, 'default')
secrets.save(CKey.bfs_user, 'user'),
secrets.save(CKey.bfs_password, 'password')
return secrets


@unittest.mock.patch("pyexasol.connect")
def test_bucketfs_credentials_default(mock_connect, filled_secrets):

path_in_bucket = 'location'

mock_connection = unittest.mock.MagicMock()
mock_connection.__enter__.return_value = mock_connection
mock_connect.return_value = mock_connection

encapsulate_bucketfs_credentials(filled_secrets, path_in_bucket=path_in_bucket,
connection_name='whatever')
expected_url = f"https://localhost:6666/default/{path_in_bucket};bfsdefault"

mock_connection.execute.assert_called_once()
query = mock_connection.execute.call_args_list[0].kwargs['query']
assert f"TO '{expected_url}'" in query


@unittest.mock.patch("pyexasol.connect")
def test_bucketfs_credentials_verify(mock_connect, filled_secrets):

path_in_bucket = 'location'
filled_secrets.save(CKey.cert_vld, 'yes')

mock_connection = unittest.mock.MagicMock()
mock_connection.__enter__.return_value = mock_connection
mock_connect.return_value = mock_connection

encapsulate_bucketfs_credentials(filled_secrets, path_in_bucket=path_in_bucket,
connection_name='whatever')
expected_url = f"https://localhost:6666/default/{path_in_bucket};bfsdefault#True"

mock_connection.execute.assert_called_once()
query = mock_connection.execute.call_args_list[0].kwargs['query']
assert f"TO '{expected_url}'" in query


@unittest.mock.patch("pyexasol.connect")
def test_bucketfs_credentials_ca(mock_connect, filled_secrets):

with tempfile.NamedTemporaryFile() as f:
path_in_bucket = 'location'
filled_secrets.save(CKey.trusted_ca, f.name)
filled_secrets.save(CKey.cert_vld, 'yes')

mock_connection = unittest.mock.MagicMock()
mock_connection.__enter__.return_value = mock_connection
mock_connect.return_value = mock_connection

encapsulate_bucketfs_credentials(filled_secrets, path_in_bucket=path_in_bucket,
connection_name='whatever')
expected_url = f"https://localhost:6666/default/{path_in_bucket};bfsdefault#False"

mock_connection.execute.assert_called_once()
query = mock_connection.execute.call_args_list[0].kwargs['query']
assert f"TO '{expected_url}'" in query

0 comments on commit 7e9c937

Please sign in to comment.