3liz / py-qgis-server

QGIS embbeded WMS/WFS/WCS asynchronous scalable http server
https://docs.3liz.org/py-qgis-server
Mozilla Public License 2.0
68 stars 16 forks source link

QGIS Server URL paths in secure mode #38

Closed NyakudyaA closed 2 years ago

NyakudyaA commented 2 years ago

Problem

I have setup a running instance of this container using 3liz/qgis-map-server:3.22 in docker. I am using a service file to connect to the database resources.

When trying to access the resources in the browser I can get proper getcapabilities using the encoded URL parameters of the map i.e

http://localhost:32780/ows/?SERVICE=WMS&VERSION=1.1.0&REQUEST=GetCapabilities&MAP=postgresql%3A%3Fservice%3Ddev%26sslmode%3Drequire%26schema%3Dpublic%26project%3Dsample

However, passing the same request without an encoded URL path doesn't work i.e

http://localhost:32780/ows/?SERVICE=WMS&VERSION=1.1.0&REQUEST=GetCapabilities&MAP=postgresql:?service=dev&sslmode=require&schema=public&project=sample

I get the error Project 'postgresql:?service=dev' not found

For the second part, I can understand why the URL might fail because of failure to escape special characters

This now presents challenges when trying to get a getcapabilities response from owslib

>>> from owslib.wms import WebMapService
>>> wms = WebMapService('http://localhost:32780/ows/?SERVICE=WMS&VERSION=1.1.0&REQUEST=GetCapabilities&MAP=postgresql%3A%2F%2Fdocker%3Adocker%40db%3A5432%3Fsslmode%3Drequire%26dbname%3Ddata%26schema%3Dpublic%26project%3Dsample', version='1.3.0')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/owslib/wms.py", line 54, in WebMapService
    return wms130.WebMapService_1_3_0(
  File "/usr/lib/python3/dist-packages/owslib/map/wms130.py", line 75, in __init__
    self._capabilities = reader.read(self.url, timeout=self.timeout)
  File "/usr/lib/python3/dist-packages/owslib/map/common.py", line 65, in read
    u = openURL(spliturl[0], spliturl[1], method='Get',
  File "/usr/lib/python3/dist-packages/owslib/util.py", line 214, in openURL
    req.raise_for_status()
  File "/usr/lib/python3/dist-packages/requests/models.py", line 943, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: http://localhost:32780/ows/?MAP=postgresql://docker:docker@db:5432?sslmode=require&dbname=data&schema=public&project=sample&service=WMS&request=GetCapabilities&version=1.3.0

Also trying, the same URL that works in the browser in QGIS Desktop fails with Download of capabilities failed

Note: I am not sure if this should be a question to owslib or QGIS Desktop or here. Feel free to close and I will ask in the OWSlib channel

dmarteau commented 2 years ago

http://localhost:32780/ows/?SERVICE=WMS&VERSION=1.1.0&REQUEST=GetCapabilities&MAP=postgresql:?service=dev&sslmode=require&schema=public&project=sample

This url is invalid because postgresql:? is not a valid project uri.

Note that the correct syntax for a posgresql stored Qgis project is postgres://[user[:pass]@]host[:port]/?dbname=X&schema=Y&project=Z

dmarteau commented 2 years ago

Note that in secure mode the only parameters allowed for postgres project's uri are service,project,dbname and schema.

NyakudyaA commented 2 years ago

http://localhost:32780/ows/?SERVICE=WMS&VERSION=1.1.0&REQUEST=GetCapabilities&MAP=postgresql:?service=dev&sslmode=require&schema=public&project=sample

This url is invalid because postgresql:? is not a valid project uri.

Thanks, I thought it follows the way QGIS interprets the URI for Postgres projects in the properties project

Note that the correct syntax for a posgresql stored Qgis project is postgres://[user[:pass]@]host[:port]/?dbname=X&schema=Y&project=Z

even a simple request like

http://localhost:32783/ows/?SERVICE=WMS&VERSION=1.1.0&REQUEST=GetCapabilities&MAP=postgres://docker:docker@]db:5432/?dbname=data&schema=public&project=sample

doesn't get resolved until you url encode the parameter map=postgres%3A%2F%2Fdocker%3Adocker%40db%3A5432%2F%3Fdbname%3Ddata%26schema%3Dpublic%26project%3Dsample

NyakudyaA commented 2 years ago

Note that in secure mode the only parameters allowed for postgres project's uri are service,project,dbname and schema.

I have tried the following postgres://service=dev/?dbname=data&schema=public&project=sample or postgres://service=dev&schema=public&project=sample without any luck.

Are there any other docs or examples in the code that I can look at so that I can also update the documentation at some point

dmarteau commented 2 years ago

postgres://service=dev/?dbname=data&schema=public&project=sample

service is a parameter: postgres:///?service=dev&...

dmarteau commented 2 years ago

Also make sure that your service file is accesible from your container.

Note: You may define the service and the service file with standards libpq environment variables: PGSERVICEFILE, PGSERVICE etc.... This will save you passing the variable in the url.

Note also that the postgres protocol supports passing the project as path in the MAP uri, i.e postgres:sample

NyakudyaA commented 2 years ago

thanks, @dmarteau So far from my testing I have the following setup

QGIS_SERVER_LANDING_PAGE_PROJECTS_PG_CONNECTIONS=postgresql:?service=dev&sslmode=require&schema=public
QGSRV_CACHE_INSECURE=no
PGSERVICEFILE=/srv/etc/pg_service.conf
QGSRV_CACHE_DEFAULT_HANDLER=postgres

And the conclusions I have drawn from this are that

dmarteau commented 2 years ago

I consider this issue as resolved.