Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 
l_robin
Contributor
Contributor

Engine API - Using websocket.create_connection with Python

Hello,

I'm using the following Python script to connect to a Qlik Sense Enterprise Server (aka myserver) :

import websocket, json, ssl
ssl.match_hostname = lambda cert, hostname: True
websocket.enableTrace(True)
ws = websocket.create_connection('wss://myserver/app/', sslopt={"cert_reqs": ssl.CERT_NONE}, header={"X-Qlik-User": "UserDirectory=INTERNAL; UserId=sa_engine"})

Result of the trace :

--- request header ---
GET /app/ HTTP/1.1
Upgrade: websocket
Host: myserver
Origin: https://myserver
Sec-WebSocket-Key: zn7kGce6liKC/nO9Xib3Xw==
Sec-WebSocket-Version: 13
Connection: Upgrade
X-Qlik-User: UserDirectory=RATP; UserId=X2027531


-----------------------
--- response header ---
HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Accept: QkiegGxJWQshniYccw2ibjuLpJM=

 

Then I'm trying to get list of apps using the following Python instructions : 

params='''{
"handle": -1,
"method": "GetDocList",
"params": [],
"outKey": -1,
"id": 1
}'''
ws.send(params)
print ("Sent")
print ("Receiving...")
result = ws.recv()
print ("Received GetDocList '%s'" % result)

 

I am expecting the list of apps but I always get the same answer from the server :

{"jsonrpc":"2.0","method":"OnAuthenticationInformation","params":{"loginUri":"https://myserver:443/internal_forms_authentication/?targetId=444d4b95-afd1-41b0-88ba-ee2014ecee3e","mustAuthenticate":true}}

Thanks in advance for your help.

Regards,

Laurent

Labels (1)
  • API

5 Replies
Øystein_Kolsrud
Employee
Employee

Qlik Sense will sometimes send push notifications. When you connect to the engine through the Proxy, the first messages you get on the websocket is typically the one you are referring to. It is a push method that indicates your authentication status. The property "mustAuthenticate" is set to "true" in your case which indicates that you have not yet been correctly authenticated.

The use of the user INTERNAL\sa_engine requires you to do a direct connection to the engine using certificates. Have you attached the Qlik client certificate to your request? And also, you'll need to connect directly to the engine port (typically 4747) in this case.

l_robin
Contributor
Contributor
Author

Hello Yko,

Thanks for your prompt answer.

Using the certificates exported with the QMC, I have tried the below script, where privatekeypath is the folder where the certificates are stored :

privateKeyPath='c:\\tmp\\'
url = 'wss://myserver:4747/app/'
certs = ({"ca_certs": privateKeyPath + "root.pem", "certfile": privateKeyPath + "client.pem", "keyfile": privateKeyPath + "client_key.pem", "cert_reqs": ssl.CERT_REQUIRED, "server_side": False})
ws = websocket.create_connection(url, sslopt=certs, header={"X-Qlik-User": "UserDirectory=INTERNAL; UserId=sa_engine"})

Unfortunately, there is a problem with the certificates and I get the following error :

ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: invalid CA certificate (_ssl.c:997)

 

Thanks in advance for your help.

Regards,

Laurent

Øystein_Kolsrud
Employee
Employee

I have never use Python for communicating with Qlik Sense before, so I'm probably not the best person to continue helping you on this, but did you disable the certificate validation in this second scenario? I saw you added the line "ssl.match_hostname" in your first post, but not your second (but perhaps you just excluded that part). I'm asking because error message you get indicates that you are running into exactly the type of validation error that the "match_hostname" property disables. Also this page indicates that the "match_hostname" is the solution for this:
https://stackoverflow.com/questions/49257450/ssl-sslerror-ssl-certificate-verify-failed-certificate-...

l_robin
Contributor
Contributor
Author

Yes,  I forgot to add it to my previous post but the following line is in my Python script :

ssl.match_hostname = lambda cert, hostname: True

But despite this, I still get the same error message :

ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: invalid CA certificate (_ssl.c:997)

Øystein_Kolsrud
Employee
Employee

Well, as I mentioned, I don't know much about Python, so I'll not be able to help you anymore here. But I do get a couple of hits when I search for the error message you get including this one that with a little luck can help you:

https://stackoverflow.com/questions/27835619/urllib-and-ssl-certificate-verify-failed-error