may-day / olap

Python package to access OLAP data sources.
63 stars 47 forks source link

Connecting to MS SAAS #24

Open ghomem opened 3 years ago

ghomem commented 3 years ago

Hi,

I am trying to connect from Ubuntu 20.04 to a 3rd party MS SAAS service on the Internet. This is the current code:

import olap.xmla.xmla as xmla
from requests import Session
from requests_ntlm import HttpNtlmAuth

# for debugging the authentication
from zeep import Client
from zeep.transports import Transport

MYUSER='THEDOMAIN\\THEUSER'
MYPASS='THEPASSWORD'
MYURL='https://THEINTERNETDOMAIN/olap/msmdpump.dll'

session = Session()
session.auth = HttpNtlmAuth(MYUSER, MYPASS)

# first we test it we can actually authenticate with user + pass
# this is done directly with Zeep and depends on the IP being whitelisted
try:
    client = Client( MYURL , transport=Transport(session=session))
except Exception as e:
    # 500 means auth is OK, 401 means authentication problem
    #print('Connection result was ' + str(e)

    if "500 Server Error" in str(e):
        print('Authentication was sucessful')
    else:
        print('Authentication problem - check your credentials and source IP')

# then we try to work with the XMLA connection provider, which uses Zeep underneath
p = xmla.XMLAProvider()

# the connection REALLY needs to be NTLM
c = p.connect(location=MYURL, session=session, Log=True, sslverify=False )

# in order to debug this change to the logger to debug level
# at the top of "olap/xmla/connection.py"
#
# logging.basicConfig(level=logging.DEBUG)

# getting info about provided data
print(c.getDatasources())

The connection seems to succeed but the XML response, visible with logging.DEBUG, brings the following error:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault xmlns="http://schemas.xmlsoap.org/soap/envelope/"><faultcode>XMLAnalysisError.0xc10d0009</faultcode><faultstring>An error was encountered in the transport layer.</faultstring><detail><Error ErrorCode="3238854665" Description="An error was encountered in the transport layer." Source="Unknown" HelpFile=""/></detail></soap:Fault></soap:Body></soap:Envelope>
Traceback (most recent call last):
  File "/home/gustavo/cubetest/xyz/olap/xmla/olap/xmla/connection.py", line 154, in Discover
    doc=self.service.Discover(RequestType=what, Restrictions=rl, Properties=pl, _soapheaders=self._soapheaders)
  File "/home/gustavo/cubetest/xyz/lib/python3.8/site-packages/zeep-4.0.0-py3.8.egg/zeep/proxy.py", line 46, in __call__
    return self._proxy._binding.send(
  File "/home/gustavo/cubetest/xyz/lib/python3.8/site-packages/zeep-4.0.0-py3.8.egg/zeep/wsdl/bindings/soap.py", line 135, in send
    return self.process_reply(client, operation_obj, response)
  File "/home/gustavo/cubetest/xyz/lib/python3.8/site-packages/zeep-4.0.0-py3.8.egg/zeep/wsdl/bindings/soap.py", line 229, in process_reply
    return self.process_error(doc, operation)
  File "/home/gustavo/cubetest/xyz/lib/python3.8/site-packages/zeep-4.0.0-py3.8.egg/zeep/wsdl/bindings/soap.py", line 329, in process_error
    raise Fault(
zeep.exceptions.Fault: None

Googling for "An error was encountered in the transport layer." we found many occurrences of this error on different environments but it isn't clear how a solution could be applied here. Any ideas on how to overcome this?

ghomem commented 3 years ago

For some reason, the code above started to work. It could be because I was under some rate-limiting constraint after many failed attempts or it could be because I logged in with Saiku in parallel. Or there was a temporary problem on the server. So, the code above can be used to connect to a SAAS service with NTLM authentication.

ghomem commented 3 years ago

Errata:

The code above would work intermittently - it required a connection from Saiku to warm up the user.

Here is the code that works all the time to connect Ubuntu 20.04 to an MS OLAP service:

import olap.xmla.xmla as xmla
from requests import Session
from requests.auth import HTTPBasicAuth

# for debugging the authentication
from zeep import Client
from zeep.transports import Transport

MYUSER='THEDOMAIN\\THEUSER'
MYPASS='THEPASSWORD'
MYURL='https://THEINTERNETDOMAIN/olap/msmdpump.dll'

session = Session()
session.auth = HTTPBasicAuth(MYUSER, MYPASS)

# first we test it we can actually authenticate with user + pass
# this is done directly with Zeep and (in my case) depends on the IP being whitelisted
try:
    client = Client( MYURL , transport=Transport(session=session))
except Exception as e:
    # 500 means auth is OK, 401 means authentication problem
    #print('Connection result was ' + str(e)

    if "500 Server Error" in str(e):
        print('Authentication was sucessful')
    else:
        print('Authentication problem - check your credentials and source IP')
        exit()

# then we try to work with the XMLA connection provider, which uses Zeep underneath
p = xmla.XMLAProvider()

c = p.connect(location=MYURL, session=session, Log=True, sslverify=False )

# in order to debug this change to the logger to debug level
# at the top of "olap/xmla/connection.py"
#
# logging.basicConfig(level=logging.DEBUG)

# getting info about provided data
print(c.getDatasources())
print(c.getDBSchemaCatalogs())
ghomem commented 3 years ago

How the system was setup:

# base
sudo apt install python3-venv python3-pip pipenv gcc python-dev libkrb5-dev

# virtualenv
python3 -m venv xyz
cd xyz
source bin/activate
pip install pipenv==2018.11.26
pipenv install -dev
git clone https://github.com/may-day/olap
cd olap/xmla
python setup.py develop