h2020-westlife-eu / virtualfolder

Virtual Folder
http://internal-wiki.west-life.eu/w/index.php?title=D6.1
MIT License
1 stars 0 forks source link

SSLError when trying to upload from HTTPS server #62

Closed mtrellet closed 6 years ago

mtrellet commented 6 years ago

While the implementation of the Upload Dir Picker on my local setup went fine, its implementation on our server (https://milou.science.uu.nl/cgi/servicesdevel/DISVIS/disvis/run/aaa_3s7C1ud7) leads to the following error:

SSLError: HTTPSConnectionPool(host='portal.west-life.eu', port=443): Max retries exceeded with url: //webdav/eyJ1c2VybmFtZSI6Im1pa2FlbC50cmVsbGV0QGdtYWlsLmNvbSJ9.1eMwf4.jSFarQPZiMnNMvbWYd9sd5U2WPo/b2drop/disvis_upload_dir/aaa_3s7C1ud7.tgz (Caused by SSLError(CertificateError("hostname 'portal.west-life.eu' doesn't match 'staging.axonea.com'",),))

I'm not really sure if my previous attempts led to this issue or there is a real problem with the certificate. Since the local implementation works (HTTP -> HTTPS) I would guess that the issue stands when using HTTPS to HTTPS communication, but cannot be 100% sure.

francoisruty commented 6 years ago

Hello, I'm not familiar with the uload dir picker, can you point me to the procedure you followed to set things up?

mtrellet commented 6 years ago

Sure! To give some context, we implement it with Flask, on the web client side (results.html) we have the following code:

var popup;
var target;
//opens popup window in defined location, sets the target element id.
function openwindow() {
  target = 'uploaddirid';
  popup=window.open('https://portal.west-life.eu/virtualfolder/uploaddirpickercomponent.html', 'newwindow', 'width=640, height=480');
}
//receives message from popup window, fills target element with the data received
function receiveMessage(event) {
    var url = window.location.href;
    if (event.data != "") {
       $("#vf_upload_dir").show();
       document.getElementById(target).innerHTML = " IN PROGRESS...";
       $.getJSON('/upload_to_vf', {
           webdav_url: event.data,
           file_url: url
        }, function(data) {
            document.getElementById(target).innerHTML = " SUCCESS - Open VF";
            document.getElementById(target).setAttribute("href", event.data);
            {#$("#result").text(data.result);#}
        });
    }
}

So the WEBDAV URL is sent to Flask and processed by the following function in views.py:

@app.route('/upload_to_vf')
def upload_to_vf():
    webdav_url = request.args.get('webdav_url')
    file_url = request.args.get('file_url')
    logging.info("Webdav URL: {}\nFile URL: {}".format(webdav_url, file_url))
    import easywebdav
    url = urlparse(webdav_url)
    file = urlparse(file_url).path
    jobid = str(file).split("/")[-1]
    archive_file = join(app.config['RESULTS_DIRECTORY'], jobid, jobid+".tgz")
    webdav = easywebdav.connect(url.hostname, protocol=url.scheme, path=url.path)
    logging.info("Uploading {} to {}".format(archive_file, webdav_url))
    webdav.upload(archive_file, os.path.basename(archive_file))
    return ('', 204)

When I run a local server I successfully send the archive file to the B2DROP folder I've selected in the pop-up window but when I try the same thing from our web server (https://milou.science.uu.nl) I get the error pasted in my initial message.

TomasKulhanek commented 6 years ago

@francoisruty They followed procedure at https://h2020-westlife-eu.gitbooks.io/virtual-folder-docs/content/doc/integration-guide/working-with-webdav.html to use webdav url programmatically in Python.

It seems that their subsequent SSL request doesn't go to portal.west-life.eu but to some web-app of opthalmology near Paris. ?

TomasKulhanek commented 6 years ago

@mtrellet I see weird URL with double slash in the beginning //webdav/eyJ1c2VybmFtZSI6Im1pa2FlbC50cmVsbGV0QGdtYWlsLmNvbSJ9.1eMwf4.jSFarQPZiMnNMvbWYd9sd5U2WPo/b2drop/disvis_upload_dir/aaa_3s7C1ud7.tgz Can you eliminate it in your code?

mtrellet commented 6 years ago

@TomasKulhanek The url.path I'm passing to webdav.connect() returns: /webdav/eyJ1c2VybmFtZSI6Im1pa2FlbC50cmVsbGV0QGdtYWlsLmNvbSJ9.1eP9QU.u9iyHRv3AZvPh7RptgF5hy4g0Ks/b2drop/disvis_upload_dir/. So only with one "/". I tried to remove the leading "/" in the url.path but I got the same error, only with one "/" in the url:

SSLError: HTTPSConnectionPool(host='portal.west-life.eu', port=443): Max retries exceeded with url: /webdav/eyJ1c2VybmFtZSI6Im1pa2FlbC50cmVsbGV0QGdtYWlsLmNvbSJ9.1eP9QU.u9iyHRv3AZvPh7RptgF5hy4g0Ks/b2drop/disvis_upload_dir/aaa_3s7C1ud7.tgz (Caused by SSLError(CertificateError("hostname 'portal.west-life.eu' doesn't match 'staging.axonea.com'",),))
mtrellet commented 6 years ago

Note: I checked and I use exactly the same arguments in my local implementation that works (tried 2min ago).

francoisruty commented 6 years ago

@TomasKulhanek on our company server, we have one public ip address, and a nginx load balancer which forward incoming http requests to the right docker containers, depending on the hostname provided in the request.

We are indeed hosting "staging.axonea.com" but I have trouble understanding why the nginx load balancer forwards requests to the wrong server I have re-checked all the nginx configs and everything is in order, it's really weird If you enter in your browser https://portal.west-life.eu/, you end up at the right place, which proves that the config is good

francoisruty commented 6 years ago

one remark: any request in http is turned into https by the nginx load balancer ex: if you enter in your browser http://portal.west-life.eu/, it becomes https://portal.west-life.eu/

francoisruty commented 6 years ago

some people had the same issue: https://github.com/requests/requests/issues/3403 by analogy it would mean mikael put in the request hostname header "staging.axonea.com" but it doesn't make sense, I think there is sth else

TomasKulhanek commented 6 years ago

No other progress. Will close - open it if the issue appears again.

mtrellet commented 6 years ago

To come back on this issue, I did some tests today to see if anything was solved, does not seem so, with the same observations, my local webserver (Flask development server) is working well to upload results to the interface, the development version of DisVis does not work (example there: https://milou.science.uu.nl/cgi/servicesdevel/DISVIS/disvis/run/aac_3tlUb6yP - click on Upload archive to VF to trigger the pipeline.)

Here are the logs I get from Flask:


2018-03-20 03:24:04,674 - urllib3.connection - ERROR - connection:360 _match_hostname - Certificate did not match expected hostname: portal.west-life.eu. Certificate: {'notAfter': 'May 29 16:26:15 2018 GMT', 'subjectAltName': (('DNS', 'concourse.luna-technology.com'),), 'subject': ((('commonName', u'concourse.luna-technology.com'),),)}
2018-03-20 03:24:04,681 - disvis_app - ERROR - app:1423 log_exception - Exception on /upload_to_vf [GET]
Traceback (most recent call last):
  File "/home/enmrdevel/services/DISVIS/env/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/enmrdevel/services/DISVIS/env/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/enmrdevel/services/DISVIS/env/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/enmrdevel/services/DISVIS/env/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/enmrdevel/services/DISVIS/env/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/enmrdevel/services/DISVIS/disvis-webserver/disvis_app.py", line 879, in upload_to_vf
    webdav.upload(archive_file, os.path.basename(archive_file))
  File "/home/enmrdevel/services/DISVIS/env/lib/python2.7/site-packages/easywebdav/client.py", line 155, in upload
    self._upload(f, remote_path)
  File "/home/enmrdevel/services/DISVIS/env/lib/python2.7/site-packages/easywebdav/client.py", line 160, in _upload
    self._send('PUT', remote_path, (200, 201, 204), data=fileobj)
  File "/home/enmrdevel/services/DISVIS/env/lib/python2.7/site-packages/easywebdav/client.py", line 97, in _send
    response = self.session.request(method, url, allow_redirects=False, **kwargs)
  File "/home/enmrdevel/services/DISVIS/env/lib/python2.7/site-packages/requests/sessions.py", line 508, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/enmrdevel/services/DISVIS/env/lib/python2.7/site-packages/requests/sessions.py", line 618, in send
    r = adapter.send(request, **kwargs)
  File "/home/enmrdevel/services/DISVIS/env/lib/python2.7/site-packages/requests/adapters.py", line 506, in send
    raise SSLError(e, request=request)
SSLError: HTTPSConnectionPool(host='portal.west-life.eu', port=443): Max retries exceeded with url: /webdav/eyJ1c2VybmFtZSI6Im1pa2FlbC50cmVsbGV0QGdtYWlsLmNvbSJ9.1ey6wN.tAyTv7_rQ8rYbAERq8ESaC-3G6M/b2drop/disvis_upload_dir/aac_3tlUb6yP.tgz (Caused by SSLError(CertificateError("hostname 'portal.west-life.eu' doesn't match 'concourse.luna-technology.com'",),))```
TomasKulhanek commented 6 years ago

It seems that I reproduced it in using Python 2.7.5 and urllib3. Simple test for python2 (urlib2 and urllib3) and python3 (urllib ???). Could you test it on your server: https://gist.github.com/TomasKulhanek/67942cc928dba51c29d4235db03008ae

Using urllib and urllib2 in Python 2.7.5 and Python 3.4.5 seems to work. HTTP 200 returned from VF.

TomasKulhanek commented 6 years ago

Is there way you can upgrade Flask to be used by Python 3? Or try to upgrade urllib3? It seems that urllib was split among more modules in Python 3, I have no capacity to investigate particular patches which may fix the issue, as it seems that it is bug in underlying connectionpool implementation rather than server configuration of Virtual Folder Portal.

TomasKulhanek commented 6 years ago

Update: Installed certifi and urllib3[secure] seems to fix the problem on failing test. Thus I cannot reproduce it on Python 2.7.5 using urllib3 anymore. bash-4.2$ python --version Python 2.7.5 bash-4.2$ pip show urllib3

Metadata-Version: 2.0 Name: urllib3 Version: 1.22

bash-4.2$ python testvfpy23.py 200 HTTPHeaderDict({'Content-Language': 'en', 'Transfer-Encoding': 'chunked', 'Strict-Transport-Security': 'max-age=17280000', 'Vary': 'Accept-Encoding, Accept-Language, Cookie', 'Server': 'nginx', 'Connection': 'keep-alive', 'Date': 'Tue, 20 Mar 2018 10:37:55 GMT', 'X-Frame-Options': 'SAMEORIGIN', 'Content-Type': 'text/html;charset=ISO-8859-1'})

mtrellet commented 6 years ago

Is there way you can upgrade Flask to be used by Python 3? Or try to upgrade urllib3?

Theoretically no issue to upgrade Flask to python3, we did it for several web-servers not later than last week. However, the current production servers for disvis and powerfit are running on a rather old cluster where python versions are limited to 2.7.13 maximum. Just checked and we were running python2.7.2 (!), so I updated to 2.7.13 in a virtual env. and tested things. And it seems to work! Thanks a lot for your help Tomas!

francoisruty commented 6 years ago

hi guys sorry for being late on this issue reopen, is it solved then, or do you need me to test anything?