Skip to content

Commit 4329128

Browse files
committed
[tests] PKI authentication tests
1 parent f1791ec commit 4329128

File tree

7 files changed

+236
-4
lines changed

7 files changed

+236
-4
lines changed

src/app/qgsidentifyresultsdialog.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,20 @@ QgsIdentifyResultsWebView::QgsIdentifyResultsWebView( QWidget *parent ) : QgsWeb
7575
#ifdef QGISDEBUG
7676
settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
7777
#endif
78+
page()->setForwardUnsupportedContent( true );
79+
connect( page(), SIGNAL( downloadRequested( QNetworkRequest ) ), this, SLOT( download( QNetworkRequest ) ) );
80+
connect( page(), SIGNAL( unsupportedContent( QNetworkReply* ) ), this, SLOT( unsupportedContent( QNetworkReply* ) ) );
81+
82+
}
83+
84+
void QgsIdentifyResultsWebView::download( QNetworkRequest request )
85+
{
86+
qDebug() << "Download Requested: " << request.url();
87+
}
88+
89+
void QgsIdentifyResultsWebView::unsupportedContent( QNetworkReply *reply )
90+
{
91+
qDebug() << "Unsupported Content: " << reply->url();
7892
}
7993

8094
void QgsIdentifyResultsWebView::print()
@@ -590,6 +604,7 @@ void QgsIdentifyResultsDialog::mapLayerActionDestroyed()
590604
}
591605
}
592606

607+
593608
QgsIdentifyPlotCurve::QgsIdentifyPlotCurve( const QMap<QString, QString> &attributes,
594609
QwtPlot* plot, const QString &title, QColor color )
595610
{

src/app/qgsidentifyresultsdialog.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131

3232
#include <QWidget>
3333
#include <QList>
34+
#include <QNetworkRequest>
35+
#include <QNetworkReply>
3436

3537
class QCloseEvent;
3638
class QTreeWidgetItem;
@@ -57,6 +59,8 @@ class APP_EXPORT QgsIdentifyResultsWebView : public QgsWebView
5759
QSize sizeHint() const override;
5860
public slots:
5961
void print();
62+
void download( QNetworkRequest request );
63+
void unsupportedContent( QNetworkReply* reply );
6064
protected:
6165
void contextMenuEvent( QContextMenuEvent* ) override;
6266
QgsWebView *createWindow( QWebPage::WebWindowType type ) override;

src/providers/postgres/qgspostgresconn.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ QgsPostgresConn::QgsPostgresConn( const QString& conninfo, bool readOnly, bool s
209209
// expand connectionInfo
210210
QgsDataSourceURI uri( conninfo );
211211
QString expandedConnectionInfo = uri.connectionInfo( true );
212+
QgsMessageLog::logMessage( tr( "Connection info: " ) + expandedConnectionInfo );
212213

213214
mConn = PQconnectdb( expandedConnectionInfo.toLocal8Bit() ); // use what is set based on locale; after connecting, use Utf8
214215

tests/src/python/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ IF (WITH_SERVER)
150150
ADD_PYTHON_TEST(PyQgsServerAccessControl test_qgsserver_accesscontrol.py)
151151
ADD_PYTHON_TEST(PyQgsServerWFST test_qgsserver_wfst.py)
152152
ADD_PYTHON_TEST(PyQgsOfflineEditingWFS test_offline_editing_wfs.py)
153-
ADD_PYTHON_TEST(PyQgsAuthManagerPasswordEndpointTest test_authmanager_password_endpoint.py)
154-
ADD_PYTHON_TEST(PyQgsAuthManagerPKIEndpointTest test_authmanager_pki_endpoint.py)
153+
ADD_PYTHON_TEST(PyQgsAuthManagerPasswordOWSTest test_authmanager_password_ows.py)
154+
ADD_PYTHON_TEST(PyQgsAuthManagerPKIOWSTest test_authmanager_pki_ows.py)
155155
ADD_PYTHON_TEST(PyQgsAuthManagerPKIPostgresTest test_authmanager_pki_postgres.py)
156156
ENDIF (WITH_SERVER)

tests/src/python/test_authmanager_password_endpoint.py renamed to tests/src/python/test_authmanager_password_ows.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
configuration to access an HTTP Basic protected endpoint.
99
1010
11-
From build dir, run: ctest -R PyQgsAuthManagerUsernamePasswordEnpointTest -V
11+
From build dir, run: ctest -R PyQgsAuthManagerPasswordOWSTest -V
1212
1313
.. note:: This program is free software; you can redistribute it and/or modify
1414
it under the terms of the GNU General Public License as published by

tests/src/python/test_authmanager_pki_endpoint.py renamed to tests/src/python/test_authmanager_pki_ows.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
configuration to access an HTTP Basic protected endpoint.
99
1010
11-
From build dir, run: ctest -R PyQgsAuthManagerPKIEndpointTest -V
11+
From build dir, run: ctest -R PyQgsAuthManagerPKIOWSTest -V
1212
1313
.. note:: This program is free software; you can redistribute it and/or modify
1414
it under the terms of the GNU General Public License as published by
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Tests for auth manager PKI access to postgres.
4+
5+
This is an integration test for QGIS Desktop Auth Manager postgres provider that
6+
checks if QGIS can use a stored auth manager auth configuration to access
7+
a PKI protected postgres.
8+
9+
Configuration form the environment:
10+
11+
* QGIS_POSTGRES_SERVER_PORT (default: 55432)
12+
* QGIS_POSTGRES_EXECUTABLE_PATH (default: /usr/lib/postgresql/9.3/bin)
13+
14+
15+
From build dir, run: ctest -R PyQgsAuthManagerPKIPostgresTest -V
16+
17+
.. note:: This program is free software; you can redistribute it and/or modify
18+
it under the terms of the GNU General Public License as published by
19+
the Free Software Foundation; either version 2 of the License, or
20+
(at your option) any later version.
21+
"""
22+
import os
23+
import time
24+
import signal
25+
import subprocess
26+
import tempfile
27+
28+
from shutil import rmtree
29+
30+
from utilities import unitTestDataPath
31+
from qgis.core import (
32+
QgsAuthManager,
33+
QgsAuthMethodConfig,
34+
QgsVectorLayer,
35+
QgsDataSourceURI,
36+
QgsWKBTypes,
37+
)
38+
39+
from PyQt4.QtNetwork import QSslCertificate
40+
41+
from qgis.testing import (
42+
start_app,
43+
unittest,
44+
)
45+
46+
47+
__author__ = 'Alessandro Pasotti'
48+
__date__ = '25/10/2016'
49+
__copyright__ = 'Copyright 2016, The QGIS Project'
50+
# This will get replaced with a git SHA1 when you do a git archive
51+
__revision__ = '$Format:%H$'
52+
53+
QGIS_POSTGRES_SERVER_PORT = os.environ.get('QGIS_POSTGRES_SERVER_PORT', '55432')
54+
QGIS_POSTGRES_EXECUTABLE_PATH = os.environ.get('QGIS_POSTGRES_EXECUTABLE_PATH', '/usr/lib/postgresql/9.3/bin')
55+
56+
assert os.path.exists(QGIS_POSTGRES_EXECUTABLE_PATH)
57+
58+
QGIS_AUTH_DB_DIR_PATH = tempfile.mkdtemp()
59+
60+
# Postgres test path
61+
QGIS_PG_TEST_PATH = tempfile.mkdtemp()
62+
63+
os.environ['QGIS_AUTH_DB_DIR_PATH'] = QGIS_AUTH_DB_DIR_PATH
64+
65+
qgis_app = start_app()
66+
67+
QGIS_POSTGRES_CONF_TEMPLATE = """
68+
hba_file = '%(tempfolder)s/pg_hba.conf'
69+
listen_addresses = '*'
70+
port = %(port)s
71+
max_connections = 100
72+
unix_socket_directories = '%(tempfolder)s'
73+
ssl = true
74+
ssl_ciphers = 'DEFAULT:!LOW:!EXP:!MD5:@STRENGTH' # allowed SSL ciphers
75+
ssl_cert_file = '%(server_cert)s'
76+
ssl_key_file = '%(server_key)s'
77+
ssl_ca_file = '%(sslrootcert_path)s'
78+
password_encryption = on
79+
"""
80+
81+
QGIS_POSTGRES_HBA_TEMPLATE = """
82+
hostssl all all 0.0.0.0/0 cert clientcert=1
83+
host all all 127.0.0.1/32 trust
84+
"""
85+
86+
87+
class TestAuthManager(unittest.TestCase):
88+
89+
@classmethod
90+
def setUpAuth(cls):
91+
"""Run before all tests and set up authentication"""
92+
authm = QgsAuthManager.instance()
93+
assert (authm.setMasterPassword('masterpassword', True))
94+
cls.pg_conf = os.path.join(cls.tempfolder, 'postgresql.conf')
95+
cls.pg_hba = os.path.join(cls.tempfolder, 'pg_hba.conf')
96+
# Client side
97+
cls.sslrootcert_path = os.path.join(cls.certsdata_path, 'chains_subissuer-issuer-root_issuer2-root2.pem')
98+
cls.sslcert = os.path.join(cls.certsdata_path, 'gerardus_cert.pem')
99+
cls.sslkey = os.path.join(cls.certsdata_path, 'gerardus_key.pem')
100+
cls.auth_config = QgsAuthMethodConfig("PKI-Paths")
101+
cls.auth_config.setConfig('certpath', cls.sslcert)
102+
cls.auth_config.setConfig('keypath', cls.sslkey)
103+
cls.auth_config.setName('test_pki_auth_config')
104+
assert os.path.isfile(cls.sslcert)
105+
assert os.path.isfile(cls.sslkey)
106+
assert os.path.isfile(cls.sslrootcert_path)
107+
cls.username = 'Gerardus'
108+
cls.sslrootcert = QSslCertificate.fromPath(cls.sslrootcert_path)
109+
assert cls.sslrootcert is not None
110+
authm.storeCertAuthorities(cls.sslrootcert)
111+
authm.rebuildCaCertsCache()
112+
authm.rebuildTrustedCaCertsCache()
113+
authm.rebuildCertTrustCache()
114+
assert (authm.storeAuthenticationConfig(cls.auth_config)[0])
115+
assert cls.auth_config.isValid()
116+
117+
# Server side
118+
cls.server_cert = os.path.join(cls.certsdata_path, 'localhost_ssl_cert.pem')
119+
cls.server_key = os.path.join(cls.certsdata_path, 'localhost_ssl_key.pem')
120+
cls.server_rootcert = cls.sslrootcert_path
121+
122+
# Place conf in the data folder
123+
with open(cls.pg_conf, 'w+') as f:
124+
f.write(QGIS_POSTGRES_CONF_TEMPLATE % {
125+
'port': cls.port,
126+
'tempfolder': cls.tempfolder,
127+
'server_cert': cls.server_cert,
128+
'server_key': cls.server_key,
129+
'sslrootcert_path': cls.sslrootcert_path,
130+
})
131+
132+
with open(cls.pg_hba, 'w+') as f:
133+
f.write(QGIS_POSTGRES_HBA_TEMPLATE)
134+
135+
@classmethod
136+
def setUpClass(cls):
137+
"""Run before all tests:
138+
Creates an auth configuration"""
139+
cls.port = QGIS_POSTGRES_SERVER_PORT
140+
cls.dbname = 'test_pki'
141+
cls.tempfolder = QGIS_PG_TEST_PATH
142+
cls.certsdata_path = os.path.join(unitTestDataPath('auth_system'), 'certs_keys')
143+
cls.hostname = 'localhost'
144+
cls.data_path = os.path.join(cls.tempfolder, 'data')
145+
os.mkdir(cls.data_path)
146+
147+
cls.setUpAuth()
148+
subprocess.check_call([os.path.join(QGIS_POSTGRES_EXECUTABLE_PATH, 'initdb'), '-D', cls.data_path])
149+
150+
cls.server = subprocess.Popen([os.path.join(QGIS_POSTGRES_EXECUTABLE_PATH, 'postgres'), '-D',
151+
cls.data_path, '-c',
152+
"config_file=%s" % cls.pg_conf],
153+
env=os.environ, stdout=subprocess.PIPE)
154+
# Create a DB
155+
subprocess.check_call([os.path.join(QGIS_POSTGRES_EXECUTABLE_PATH, 'createdb'), '-h', 'localhost', '-p', cls.port, 'test_pki'])
156+
# Inject test SQL from test path
157+
test_sql = os.path.join(unitTestDataPath('provider'), 'testdata_pg.sql')
158+
subprocess.check_call([os.path.join(QGIS_POSTGRES_EXECUTABLE_PATH, 'psql'), '-h', 'localhost', '-p', cls.port, '-f', test_sql, cls.dbname])
159+
# Create a role
160+
subprocess.check_call([os.path.join(QGIS_POSTGRES_EXECUTABLE_PATH, 'psql'), '-h', 'localhost', '-p', cls.port, '-c', 'CREATE ROLE "%s" WITH SUPERUSER LOGIN' % cls.username, cls.dbname])
161+
162+
@classmethod
163+
def tearDownClass(cls):
164+
"""Run after all tests"""
165+
cls.server.terminate()
166+
os.kill(cls.server.pid, signal.SIGABRT)
167+
del cls.server
168+
time.sleep(2)
169+
rmtree(QGIS_AUTH_DB_DIR_PATH)
170+
rmtree(cls.tempfolder)
171+
172+
def setUp(self):
173+
"""Run before each test."""
174+
pass
175+
176+
def tearDown(self):
177+
"""Run after each test."""
178+
pass
179+
180+
@classmethod
181+
def _getPostGISLayer(cls, type_name, layer_name=None, authcfg=None):
182+
"""
183+
PG layer factory
184+
"""
185+
if layer_name is None:
186+
layer_name = 'pg_' + type_name
187+
uri = QgsDataSourceURI()
188+
uri.setWkbType(QgsWKBTypes.Point)
189+
uri.setConnection("localhost", cls.port, cls.dbname, "", "", QgsDataSourceURI.SSLverifyFull, authcfg)
190+
uri.setKeyColumn('pk')
191+
uri.setSrid('EPSG:4326')
192+
uri.setDataSource('qgis_test', 'someData', "geom", "", "pk")
193+
# Note: do not expand here!
194+
layer = QgsVectorLayer(uri.uri(False), layer_name, 'postgres')
195+
return layer
196+
197+
def testValidAuthAccess(self):
198+
"""
199+
Access the protected layer with valid credentials
200+
"""
201+
pg_layer = self._getPostGISLayer('testlayer_èé', authcfg=self.auth_config.id())
202+
self.assertTrue(pg_layer.isValid())
203+
204+
def testInvalidAuthAccess(self):
205+
"""
206+
Access the protected layer with not valid credentials
207+
"""
208+
pg_layer = self._getPostGISLayer('testlayer_èé')
209+
self.assertFalse(pg_layer.isValid())
210+
211+
if __name__ == '__main__':
212+
unittest.main()

0 commit comments

Comments
 (0)