Les extraits de code sur cette page nécessitent les importations suivantes si vous êtes en dehors de la console pyqgis :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from qgis.core import (
  QgsApplication,
  QgsRasterLayer,
  QgsAuthMethodConfig,
  QgsDataSourceUri,
  QgsPkiBundle,
  QgsMessageLog,
)

from qgis.gui import (
    QgsAuthAuthoritiesEditor,
    QgsAuthConfigEditor,
    QgsAuthConfigSelect,
    QgsAuthSettingsWidget,
)

from qgis.PyQt.QtWidgets import (
    QWidget,
    QTabWidget,
)

from qgis.PyQt.QtNetwork import QSslCertificate

14. Infrastructure d’authentification

14.1. Introduction

Les infrastructures d’authentification de la référence utilisatieur peuvent être lu dans le manuel d’utilisateur le paragraphe Aperçu du Système d’authentification .

Ce chapitre décrit les les bonnes pratiques de développement pour l’utilisation du système d’authentification.

Dans QGIS Desktop, le système d’authentification est régulièrement utilisé par les fournisseurs de données lorsqu’une accréditation est nécessaire pour l’acquisition de certaines ressources, par exemple, lorsqu’une couche nécessite une connexion à une base Postgres.

Il existe aussi quelques widgets de la bibliothèque graphique de QGIS que les développeur de plugin peuvent utiliser pour intégrer facilement le système d’authentification dans leur code :

Les tests dans le code source sont un bon exemple d’infrastructure d’authentification.

Avertissement

Du fait de contraintes de sécurité ayant conduit au design de l’infrastructure d’authentification, seules quelques méthodes internes sont exposées en Python.

14.2. Glossaire

Voici quelques définitions des principaux éléments étudiés dans ce chapitre.

Mot de passe principal

Mot de passe permettant l’accès et le décryptage des informations stockées dans la base de données d’authentification de QGIS.

Base de données d’authentification

Une base de donnée sqlite qgis-auth.db cryptée des Mot de passe principal où les Configurations d’authentification sont stockées. Par exemple vos noms d’utilisateur et mots de passe, vos certificats et clés personnelles et plus généralement toutes vos méthodes d’authentification

Base de données d’authentification

Base de données d’authentification

Configuration de l’authentification

Un ensemble de données d’authentification dépendant de la Méthode d’authentification. Par exemple, une méthode basique d’authentification enregistre le couple Nom d’utilisateur / Mot de passe.

Configuration de l’authentification

Configuration de l’authentification

Méthode d’authentification

Une méthode pour s’authentifier. Chaque méthode a son propre protocole utilisé pour accorder le statut “authentifié”. Chaque méthode est mise à disposition comme une librairie chargée dynamiquement pendant la phase d’initialisation de l’infrastructure d’authentification de QGIS.

14.3. QgsAuthManager le point d’entrée

Le singleton QgsAuthManager est le point d’entrée pour utiliser les informations d’identification stockées dans la base de données QGIS cryptée Authentication DB, c’est-à-dire le fichier qgis-auth.db sous le dossier actif user profile.

Cette classe s’occupe de l’interaction avec l’utilisateur : en lui demandant de définir un mot de passe maître ou en l’utilisant de manière transparente pour accéder à des informations stockées cryptées.

14.3.1. Initier le gestionnaire et définir le mot de passe principal

L’extrait suivant donne un exemple de définition d’un mot de passe principal pour ouvrir l’accès aux paramètres d’authentification. Les commentaires du code sont importants pour comprendre l’extrait.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
authMgr = QgsApplication.authManager()

# check if QgsAuthManager has already been initialized... a side effect
# of the QgsAuthManager.init() is that AuthDbPath is set.
# QgsAuthManager.init() is executed during QGIS application init and hence
# you do not normally need to call it directly.
if authMgr.authenticationDatabasePath():
    # already initialized => we are inside a QGIS app.
    if authMgr.masterPasswordIsSet():
        msg = 'Authentication master password not recognized'
        assert authMgr.masterPasswordSame("your master password"), msg
    else:
        msg = 'Master password could not be set'
        # The verify parameter checks if the hash of the password was
        # already saved in the authentication db
        assert authMgr.setMasterPassword("your master password",
                                          verify=True), msg
else:
    # outside qgis, e.g. in a testing environment => setup env var before
    # db init
    os.environ['QGIS_AUTH_DB_DIR_PATH'] = "/path/where/located/qgis-auth.db"
    msg = 'Master password could not be set'
    assert authMgr.setMasterPassword("your master password", True), msg
    authMgr.init("/path/where/located/qgis-auth.db")

14.3.2. Remplir authdb avec une nouvelle entrée de configuration d’authentification

Tout justificatif stocké est une instance Authentication Configuration de la classe QgsAuthMethodConfig à laquelle on accède en utilisant une chaîne unique comme la suivante: :

authcfg = 'fm1s770'

cette chaîne est générée automatiquement lors de la création d’une entrée en utilisant l’API ou l’interface graphique QGIS, mais il peut être utile de la définir manuellement à une valeur connue dans le cas où la configuration doit être partagée (avec des identifiants différents) entre plusieurs utilisateurs au sein d’une organisation.

QgsAuthMethodConfig est la classe de base pour toute Méthode d’authentification. Toute méthode d’authentification définit une table de hachage de configuration où les informations d’authentification seront stockées. Ci-après, un extrait utile pour stocker les informations d’identification de type PKI-path pour une hypothétique utilisatrice nommée alice :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
authMgr = QgsApplication.authManager()
# set alice PKI data
config = QgsAuthMethodConfig()
config.setName("alice")
config.setMethod("PKI-Paths")
config.setUri("https://example.com")
config.setConfig("certpath", "path/to/alice-cert.pem" )
config.setConfig("keypath", "path/to/alice-key.pem" )
# check if method parameters are correctly set
assert config.isValid()

# register alice data in authdb returning the ``authcfg`` of the stored
# configuration
authMgr.storeAuthenticationConfig(config)
newAuthCfgId = config.id()
assert newAuthCfgId

14.3.2.1. Méthodes d’authentification disponibles

Les bibliothèques de Méthode d’authentification sont chargées dynamiquement pendant l’initialisation du gestionnaire d’authentification. Les méthodes d’authentification disponibles sont :

  1. Basique: authentification avec utilisateur et mot de passe

  2. Esri-Token: authentification basée sur le jeton ESRI

  3. Identity-Cert: authentification par certificat d’identité

  4. OAuth2: authentification OAuth2

  5. PKI-Paths PKI paths authentication

  6. PKI-PKCS#12 PKI PKCS#12 authentication

14.3.2.2. Populate Authorities

1
2
3
4
5
6
7
8
9
authMgr = QgsApplication.authManager()
# add authorities
cacerts = QSslCertificate.fromPath( "/path/to/ca_chains.pem" )
assert cacerts is not None
# store CA
authMgr.storeCertAuthorities(cacerts)
# and rebuild CA caches
authMgr.rebuildCaCertsCache()
authMgr.rebuildTrustedCaCertsCache()

14.3.2.3. Manage PKI bundles with QgsPkiBundle

La classe QgsPkiBundle est une classe de commodité permettant d’emballer des paquets d’ICP composés sur la chaîne SslCert, SslKey et CA. Ci-après, un extrait pour obtenir la protection par mot de passe :

1
2
3
4
5
6
7
8
9
# add alice cert in case of key with pwd
caBundlesList = []  # List of CA bundles
bundle = QgsPkiBundle.fromPemPaths( "/path/to/alice-cert.pem",
                                     "/path/to/alice-key_w-pass.pem",
                                     "unlock_pwd",
                                     caBundlesList )
assert bundle is not None
# You can check bundle validity by calling:
# bundle.isValid()

Référez-vous à la documentation de la classe QgsPkiBundle pour extraire les cert/clés/CA du bundle.

14.3.3. Supprimer une entrée de l’authdb

Nous pouvons supprimer une entrée de Base de données d’Authentification en utilisant son identifiant authcfg avec le code suivant :

authMgr = QgsApplication.authManager()
authMgr.removeAuthenticationConfig( "authCfg_Id_to_remove" )

14.3.4. Laissez l’extension authcfg à QgsAuthManager

La meilleure façon d’utiliser un Authentication Config stocké dans la Basse de données d’Authentication est de le référencer avec l’identifiant unique authcfg. L’expansion, signifie le convertir d’un identifiant en un ensemble complet de justificatifs d’identité. La meilleure façon d’utiliser la Configuration d’authentification stockée est de la laisser gérée automatiquement par le gestionnaire d’authentification. L’utilisation courante d’une configuration stockée est de se connecter à un service d’authentification comme un WMS ou un WFS ou à une base de données.

Note

Tenez compte du fait que tous les fournisseurs de données QGIS ne sont pas intégrés à l’infrastructure d’authentification. Chaque méthode d’authentification, dérivée de la classe de base QgsAuthMethod prend en charge un ensemble différent de fournisseurs. Par exemple, la méthode certIdentity() prend en charge la liste de fournisseurs suivante :

authM = QgsApplication.authManager()
print(authM.authMethod("Identity-Cert").supportedDataProviders())

Exemple de sortie :

['ows', 'wfs', 'wcs', 'wms', 'postgres']

Par exemple, pour accéder à un service WMS en utilisant des informations d’identification stockées identifiées par authcfg = 'fm1s770', il suffit d’utiliser authcfg dans l’URL de la source de données comme dans l’extrait suivant :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
authCfg = 'fm1s770'
quri = QgsDataSourceUri()
quri.setParam("layers", 'usa:states')
quri.setParam("styles", '')
quri.setParam("format", 'image/png')
quri.setParam("crs", 'EPSG:4326')
quri.setParam("dpiMode", '7')
quri.setParam("featureCount", '10')
quri.setParam("authcfg", authCfg)   # <---- here my authCfg url parameter
quri.setParam("contextualWMSLegend", '0')
quri.setParam("url", 'https://my_auth_enabled_server_ip/wms')
rlayer = QgsRasterLayer(str(quri.encodedUri(), "utf-8"), 'states', 'wms')

En majuscules, le provider wms prendra soin d’étendre le paramètre URI authcfg avec l’identifiant juste avant d’établir la connexion HTTP.

Avertissement

Le développeur devra laisser l’extension authcfg à la QgsAuthManager, de cette façon il sera sûr que l’extension ne sera pas faite trop tôt.

Habituellement, une chaîne URI, construite en utilisant la classe QgsDataSourceURI, est utilisée pour définir une source de données de la manière suivante :

authCfg = 'fm1s770'
quri = QgsDataSourceUri("my WMS uri here")
quri.setParam("authcfg", authCfg)
rlayer = QgsRasterLayer( quri.uri(False), 'states', 'wms')

Note

Le paramètre False est important pour éviter l’expansion complète de l’URI de l’id authcfg présent dans l’URI.

14.3.4.1. Exemples PKI avec d’autres fournisseurs de données

Un autre exemple peut être lu directement dans les tests QGIS en amont comme dans test_authmanager_pki_ows ou test_authmanager_pki_postgres.

14.4. Adapter les plugins pour utiliser l’infrastructure d’authentification

De nombreux plugins tiers utilisent httplib2 ou d’autres bibliothèques réseau Python pour gérer les connexions HTTP au lieu de s’intégrer avec QgsNetworkAccessManager et l’intégration de l’infrastructure d’authentification correspondante.

Pour faciliter cette intégration, une fonction d’aide Python a été créée, appelée « NetworkAccessManager ». Son code se trouve ici.

Cette classe d’aide peut être utilisée comme dans l’extrait suivant :

1
2
3
4
5
6
http = NetworkAccessManager(authid="my_authCfg", exception_class=My_FailedRequestError)
try:
  response, content = http.request( "my_rest_url" )
except My_FailedRequestError, e:
  # Handle exception
  pass

14.5. Interfaces d’authentification

Ce paragraphe liste les fenêtres utiles à l’intégration d’une infrastructure d’authentification dans des interfaces personnalisées.

14.5.1. Fenêtre de sélection des identifiants

S’il est nécessaire de sélectionner une configuration d’authentification à partir du jeu stocké dans la Base de données d’authentification, il est disponible dans la classe d’interface QgsAuthConfigSelect.

../../_images/QgsAuthConfigSelect.png

et peut être utilisé comme dans l’extrait suivant :

1
2
3
4
5
6
7
8
# create the instance of the QgsAuthConfigSelect GUI hierarchically linked to
# the widget referred with `parent`
parent = QWidget()  # Your GUI parent widget
gui = QgsAuthConfigSelect( parent, "postgres" )
# add the above created gui in a new tab of the interface where the
# GUI has to be integrated
tabGui = QTabWidget()
tabGui.insertTab( 1, gui, "Configurations" )

L’exemple ci-dessus est tiré du code source de QGIS. Le deuxième paramètre du constructeur de l’interface graphique se réfère au type de fournisseur de données. Ce paramètre est utilisé pour restreindre la compatibilité de la Méthode d’authentification avec le fournisseur spécifié.

14.5.2. Authentication Editor GUI

L’interface graphique complète utilisée pour gérer les références, les autorités et pour accéder aux utilitaires d’authentification est gérée par la classe QgsAuthEditorWidgets.

../../_images/QgsAuthEditorWidgets.png

et peut être utilisé comme dans l’extrait suivant :

1
2
3
4
5
# create the instance of the QgsAuthEditorWidgets GUI hierarchically linked to
# the widget referred with `parent`
parent = QWidget()  # Your GUI parent widget
gui = QgsAuthConfigSelect( parent )
gui.show()

Un exemple intégré peut être trouvé dans le fichier test.

14.5.3. Authorities Editor GUI

Une interface graphique utilisée pour gérer uniquement les autorités est gérée par la classe QgsAuthAuthoritiesEditor.

../../_images/QgsAuthAuthoritiesEditor.png

et peut être utilisé comme dans l’extrait suivant :

1
2
3
4
5
# create the instance of the QgsAuthAuthoritiesEditor GUI hierarchically
#  linked to the widget referred with `parent`
parent = QWidget()  # Your GUI parent widget
gui = QgsAuthAuthoritiesEditor( parent )
gui.show()