Skip to content

Commit caaa0c1

Browse files
ea-ruskaizenjincoBao Ngoentelligence-ai-pr-reviews[bot]
authored
Add SSL verification control for ClickHouse handler (continue of #11367) (#11842)
Co-authored-by: Bao Ngo <78314961+kaizenjinco@users.noreply.github.com> Co-authored-by: Bao Ngo <baonn@cbbank.vn> Co-authored-by: entelligence-ai-pr-reviews[bot] <174136889+entelligence-ai-pr-reviews[bot]@users.noreply.github.com>
1 parent 11f6110 commit caaa0c1

2 files changed

Lines changed: 62 additions & 62 deletions

File tree

mindsdb/integrations/handlers/clickhouse_handler/clickhouse_handler.py

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from urllib.parse import quote
1+
from urllib.parse import quote, urlencode
22

33
import pandas as pd
44
from sqlalchemy import create_engine
@@ -12,7 +12,7 @@
1212
from mindsdb.integrations.libs.response import (
1313
HandlerStatusResponse as StatusResponse,
1414
HandlerResponse as Response,
15-
RESPONSE_TYPE
15+
RESPONSE_TYPE,
1616
)
1717

1818
logger = log.getLogger(__name__)
@@ -23,15 +23,15 @@ class ClickHouseHandler(DatabaseHandler):
2323
This handler handles connection and execution of the ClickHouse statements.
2424
"""
2525

26-
name = 'clickhouse'
26+
name = "clickhouse"
2727

2828
def __init__(self, name, connection_data, **kwargs):
2929
super().__init__(name)
30-
self.dialect = 'clickhouse'
30+
self.dialect = "clickhouse"
3131
self.connection_data = connection_data
3232
self.renderer = SqlalchemyRender(ClickHouseDialect)
3333
self.is_connected = False
34-
self.protocol = connection_data.get('protocol', 'native')
34+
self.protocol = connection_data.get("protocol", "native")
3535

3636
def __del__(self):
3737
if self.is_connected is True:
@@ -50,23 +50,31 @@ def connect(self):
5050
if self.is_connected:
5151
return self.connection
5252

53-
protocol = "clickhouse+native" if self.protocol == 'native' else "clickhouse+http"
54-
host = quote(self.connection_data['host'])
55-
port = self.connection_data['port']
56-
user = quote(self.connection_data['user'])
57-
password = quote(self.connection_data['password'])
58-
database = quote(self.connection_data['database'])
59-
url = f'{protocol}://{user}:{password}@{host}:{port}/{database}'
53+
protocol = "clickhouse+native" if self.protocol == "native" else "clickhouse+http"
54+
host = quote(self.connection_data["host"])
55+
port = self.connection_data["port"]
56+
user = quote(self.connection_data["user"])
57+
password = quote(self.connection_data["password"])
58+
database = quote(self.connection_data["database"])
59+
verify = self.connection_data.get("verify", True)
60+
url = f"{protocol}://{user}:{password}@{host}:{port}/{database}"
6061
# This is not redundunt. Check https://clickhouse-sqlalchemy.readthedocs.io/en/latest/connection.html#http
61-
if self.protocol == 'https':
62-
url = url + "?protocol=https"
62+
63+
params = {}
64+
if self.protocol == "https":
65+
params["protocol"] = "https"
66+
if verify is False:
67+
params["verify"] = "false"
68+
if params:
69+
url = f"{url}?{urlencode(params)}"
70+
6371
try:
6472
engine = create_engine(url)
6573
connection = engine.raw_connection()
6674
self.is_connected = True
6775
self.connection = connection
6876
except SQLAlchemyError as e:
69-
logger.error(f'Error connecting to ClickHouse {self.connection_data["database"]}, {e}!')
77+
logger.error(f"Error connecting to ClickHouse {self.connection_data['database']}, {e}!")
7078
self.is_connected = False
7179
raise
7280

@@ -86,12 +94,12 @@ def check_connection(self) -> StatusResponse:
8694
connection = self.connect()
8795
cur = connection.cursor()
8896
try:
89-
cur.execute('select 1;')
97+
cur.execute("select 1;")
9098
finally:
9199
cur.close()
92100
response.success = True
93101
except SQLAlchemyError as e:
94-
logger.error(f'Error connecting to ClickHouse {self.connection_data["database"]}, {e}!')
102+
logger.error(f"Error connecting to ClickHouse {self.connection_data['database']}, {e}!")
95103
response.error_message = str(e)
96104
self.is_connected = False
97105

@@ -117,22 +125,13 @@ def native_query(self, query: str) -> Response:
117125
cur.execute(query)
118126
result = cur.fetchall()
119127
if result:
120-
response = Response(
121-
RESPONSE_TYPE.TABLE,
122-
pd.DataFrame(
123-
result,
124-
columns=[x[0] for x in cur.description]
125-
)
126-
)
128+
response = Response(RESPONSE_TYPE.TABLE, pd.DataFrame(result, columns=[x[0] for x in cur.description]))
127129
else:
128130
response = Response(RESPONSE_TYPE.OK)
129131
connection.commit()
130132
except SQLAlchemyError as e:
131-
logger.error(f'Error running query: {query} on {self.connection_data["database"]}!')
132-
response = Response(
133-
RESPONSE_TYPE.ERROR,
134-
error_message=str(e)
135-
)
133+
logger.error(f"Error running query: {query} on {self.connection_data['database']}!")
134+
response = Response(RESPONSE_TYPE.ERROR, error_message=str(e))
136135
connection.rollback()
137136
finally:
138137
cur.close()
@@ -155,7 +154,7 @@ def get_tables(self) -> Response:
155154
df = result.data_frame
156155

157156
if df is not None:
158-
result.data_frame = df.rename(columns={df.columns[0]: 'table_name'})
157+
result.data_frame = df.rename(columns={df.columns[0]: "table_name"})
159158

160159
return result
161160

mindsdb/integrations/handlers/clickhouse_handler/connection_args.py

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,49 +5,50 @@
55

66
connection_args = OrderedDict(
77
protocol={
8-
'type': ARG_TYPE.STR,
9-
'description': 'The protocol to query clickhouse. Supported: native, http, https. Default: native',
10-
'required': False,
11-
'label': 'Protocol'
8+
"type": ARG_TYPE.STR,
9+
"description": "The protocol to query clickhouse. Supported: native, http, https. Default: native",
10+
"required": False,
11+
"label": "Protocol",
1212
},
1313
user={
14-
'type': ARG_TYPE.STR,
15-
'description': 'The user name used to authenticate with the ClickHouse server.',
16-
'required': True,
17-
'label': 'User'
14+
"type": ARG_TYPE.STR,
15+
"description": "The user name used to authenticate with the ClickHouse server.",
16+
"required": True,
17+
"label": "User",
1818
},
1919
database={
20-
'type': ARG_TYPE.STR,
21-
'description': 'The database name to use when connecting with the ClickHouse server.',
22-
'required': True,
23-
'label': 'Database name'
20+
"type": ARG_TYPE.STR,
21+
"description": "The database name to use when connecting with the ClickHouse server.",
22+
"required": True,
23+
"label": "Database name",
2424
},
2525
host={
26-
'type': ARG_TYPE.STR,
27-
'description': 'The host name or IP address of the ClickHouse server. NOTE: use \'127.0.0.1\' instead of \'localhost\' to connect to local server.',
28-
'required': True,
29-
'label': 'Host'
26+
"type": ARG_TYPE.STR,
27+
"description": "The host name or IP address of the ClickHouse server. NOTE: use '127.0.0.1' instead of 'localhost' to connect to local server.",
28+
"required": True,
29+
"label": "Host",
3030
},
3131
port={
32-
'type': ARG_TYPE.INT,
33-
'description': 'The TCP/IP port of the ClickHouse server. Must be an integer.',
34-
'required': True,
35-
'label': 'Port'
32+
"type": ARG_TYPE.INT,
33+
"description": "The TCP/IP port of the ClickHouse server. Must be an integer.",
34+
"required": True,
35+
"label": "Port",
3636
},
3737
password={
38-
'type': ARG_TYPE.PWD,
39-
'description': 'The password to authenticate the user with the ClickHouse server.',
40-
'required': True,
41-
'label': 'Password',
42-
'secret': True
43-
}
38+
"type": ARG_TYPE.PWD,
39+
"description": "The password to authenticate the user with the ClickHouse server.",
40+
"required": True,
41+
"label": "Password",
42+
"secret": True,
43+
},
44+
verify={
45+
"type": ARG_TYPE.BOOL,
46+
"description": "Controls certificate verification in https protocol. Possible choices: true/false. Default is true.",
47+
"required": False,
48+
"label": "SSL Verification",
49+
},
4450
)
4551

4652
connection_args_example = OrderedDict(
47-
protocol='native',
48-
host='127.0.0.1',
49-
port=9000,
50-
user='root',
51-
password='password',
52-
database='database'
53+
protocol="native", host="127.0.0.1", port=9000, user="root", password="password", database="database", verify=True
5354
)

0 commit comments

Comments
 (0)