Open AndreyKadysh opened 1 day ago
I am seeing the same issue from Python 3.12 and 3.9 works fine.
I can't reproduce this issue.
I included the tlsCipherList
in the tm1s.cfg
and run below script with the latest release of python 3.12 and TM1py.
Am I missing something?
from TM1py import TM1Service
tm1_params = {
"address": "localhost",
"port": 12354,
"user": "admin",
"password": "apple",
"ssl": True,
}
with TM1Service(**tm1_params) as tm1:
print(tm1.server.get_product_version())
print(tm1.server.get_server_name())
@AndreyKadysh, @macsir
can you try to manipulate the ssl_context
directly in your local TM1py RestService
? Possibly somewhere around here, I guess?
https://github.com/cubewise-code/tm1py/blob/59a93a8ff9b2e5053cbe60274a67969e42c77e28/TM1py/Services/RestService.py#L462
If this works, we could do an enhancement to allow users to pass a custom ssl_context
in the TM1Service
constructor
Hi Marius! Thank you for reply!
Have you done also changes to admin server parameter called "Supported Cipher Suites" in Cognos Configuration? It can be a reason why you can't reproduce issue.
Our detailed traceback:
Traceback (most recent call last):
File "C:\Users\akadysh\PycharmProjects\ibm_connections\ssl_test_2.py", line 11, in <module>
with (TM1Service(address=address, port=port, ssl=True, user=user, password=password, namespace=namespace )) as tm1:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\akadysh\PycharmProjects\ibm_connections\.venv\Lib\site-packages\TM1py\Services\TM1Service.py", line 64, in __init__
self._tm1_rest = RestService(**kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\akadysh\PycharmProjects\ibm_connections\.venv\Lib\site-packages\TM1py\Services\RestService.py", line 183, in __init__
self.connect()
File "C:\Users\akadysh\PycharmProjects\ibm_connections\.venv\Lib\site-packages\TM1py\Services\RestService.py", line 332, in connect
self._start_session(
File "C:\Users\akadysh\PycharmProjects\ibm_connections\.venv\Lib\site-packages\TM1py\Services\RestService.py", line 745, in _start_session
response = self._s.get(
^^^^^^^^^^^^
File "C:\Users\akadysh\PycharmProjects\ibm_connections\.venv\Lib\site-packages\requests\sessions.py", line 602, in get
return self.request("GET", url, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\akadysh\PycharmProjects\ibm_connections\.venv\Lib\site-packages\requests\sessions.py", line 589, in request
resp = self.send(prep, **send_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\akadysh\PycharmProjects\ibm_connections\.venv\Lib\site-packages\requests\sessions.py", line 703, in send
r = adapter.send(request, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\akadysh\PycharmProjects\ibm_connections\.venv\Lib\site-packages\requests\adapters.py", line 698, in send
raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='0.0.0.0', port=0000): Max retries exceeded with url: /api/v1/Configuration/ProductVersion/$value (Caused by SSLError(SSLError(1, '[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1000)')))
So the error appears in RestService method _start_session() here: https://github.com/cubewise-code/tm1py/blob/59a93a8ff9b2e5053cbe60274a67969e42c77e28/TM1py/Services/RestService.py#L763
Tried to tweak http adapter this way, but it doen't help (maybe did something wrong)
def _manage_http_adapter(self):
# Create a custom SSL context
ssl_context = ssl.create_default_context()
# Disable SSLv3
ssl_context.options |= ssl.OP_NO_SSLv3
adapter = HTTPAdapterWithSocketOptions(
pool_connections=int(self._connection_pool_size or self.DEFAULT_CONNECTION_POOL_SIZE),
pool_maxsize=int(self._connection_pool_size),
ssl_context=ssl_context # Pass the custom SSL context here
)
self._s.mount(self._base_url, adapter)
I met this issue before. in my case, the SSL is using TLSv1 (not familiar with it... just look at the result of openssl...). please make sure your SSL configuration with openssl or other tools
then, may check the following changes what I made within TM1py source code
BUT!!!!! some of the changes is not a MUST... because TM1 version is v10.xxx
# in TM1py.Services.Utils.Utils
import ssl
class HTTPAdapterWithSocketOptions(HTTPAdapter):
def __init__(self, *args, **kwargs):
self.socket_options = kwargs.pop("socket_options", None)
++++++ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
++++++ context.options &= ~ssl.OP_NO_SSLv3
++++++ ciphers = ":".join(['@SECLEVEL=0', 'ALL'])
++++++ context.set_ciphers(ciphers)
++++++ self.ssl_context = context
super(HTTPAdapterWithSocketOptions, self).__init__(*args, **kwargs)
def init_poolmanager(self, *args, **kwargs):
# must use hasattr here, as socket_options may be not-set in case TM1Service was created with restore_from_file
if hasattr(self, "socket_options"):
kwargs["socket_options"] = self.socket_options
++++++ kwargs['ssl_context'] = self.ssl_context
super(HTTPAdapterWithSocketOptions, self).init_poolmanager(*args, **kwargs)
Since the TM1 version is v10, TM1py may face compatibility issues in communication between the client and server.
def _manage_http_adapter(self):
adapter = HTTPAdapterWithSocketOptions(
pool_connections=int(self._connection_pool_size or self.DEFAULT_CONNECTION_POOL_SIZE),
pool_maxsize=int(self._connection_pool_size))
+++ self._s.mount('https://', adpater)
self._s.mount(self._base_url, adapter)
During
TM1Service.__init__
, therequests.session
may perform a health check for the connection without any adapter mounted, which may lead to SSL errors.*
class RestService():
def __init__():
...
self._version = None
self._headers = self.HEADERS.copy()
if "session_context" in kwargs:
self._headers["TM1-SessionContext"] = kwargs["session_context"]
self.disable_http_warnings()
self._s = Session()
+++ self._manage_http_adapter()
if self._proxies:
self._s.proxies = self._proxies
# First contact with TM1
self.connect()
if not self._version:
self.set_version()
--- self._manage_http_adapter()
def logout(self, timeout: float = None, **kwargs):
""" End TM1 Session and HTTP session
"""
try:
----- self.POST('/ActiveSession/tm1.Close', '', headers={"Connection": "close"}, timeout=timeout,
async_requests_mode=False, **kwargs)
+++++ self._s.post('https://localhost:8000/api/logout', '', headers={"Connection": "close"}, timeout=timeout,
async_requests_mode=False, verify=False, **kwargs)
finally:
self._s.close()
@MariusWirtz What value do you use in tlsCipherList
?
at least adding these values doesn't work for me. Still same error.
tlsCipherList=TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
And looks like it always came from this Delete operation and Post is fine.
File "/Users/.local/lib/python3.12/site-packages/TM1py/Services/RestService.py", line 594, in cancel_async_operation
response = self._s.delete(url, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/.local/lib/python3.12/site-packages/requests/sessions.py", line 671, in delete
return self.request("DELETE", url, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Hi!
During an internal security audit at our company, we faced false-positive security scan results for our IBM PA model ports. To fix this, we followed the IBM tech note https://www.ibm.com/docs/en/planning-analytics/2.0.0?topic=pa2f82-disable-des-3des-ciphers-in-planning-analytics-mitigate-false-positive-security-scans And added a list of cipher suites to the Admin Server parameter and to the model .cfg file.
After that sslv3 handshake errors began to appear in our python scripts:
Although, аll the other services (PAW, Arc, PAX, http-calls via postman) work well.
We tried changing different sets of cipher suites but it didn't help at all. Also found that there is a way to change default ssl-context in requests lib. But we use TM1Service() for auth. And requests lib is wrapped around deeply into TM1Py library.
Environmental details: TM1 2.0.9.19 on premise , auth mode 5 Python 3.12.3 TM1Py 2.0.4 urllib3 2.2.3 requests 2.32.3
Sample python code for tests:
P.S. We accidentally figured out that it works well with python 3.9.7 But we cannot go back to the previous version of python for a number of reasons.
Any help would be appreciated! Andre