3

How can I hide the password in QGIS vector layer(postgis) in a plug in (via pyqgis)?

If the layer is created.

uri = QgsDataSourceURI()

uri.setConnection(self.uri.host(),self.uri.port() 
   ,self.uri.database(),self.uri.username(),self.uri.password())

uri.setDataSource(schema,vista, geom, '',pk_field)

vlayer = QgsVectorLayer(uri.uri(False), vista,'postgres')

I just opened the Python console in QGIS, select the layer to discover the database password and type.

layer=iface.activeLayer()

layer.source()

And it displays the user and password of the postgis database I am connecting.

I want to avoid that so important information, like the user and password of the postgis database I am connecting to, could be displayed so simply, without a way to hide it.

  • What's the threat here? That a rogue agent will get to your keyboard and find your PostGIS credentials? Or that you will accidentally expose your PostGIS credentials while doing other stuff? – Spacedman Dec 5 '17 at 23:24
  • After you login in widows, tell me if there is any way to ask the OS to print in the screen the password... there is no way. The same happens with databases, if the password is encripted. You can't see it, or ask the database for it, you just login. – Alfredo Garcia Dec 6 '17 at 17:54
  • If a database connection is remote it needs to send credentials on every call, so it has to keep the password (or an equally privileged token) somewhere on the local machine - most securely in the client process's memory. But even that can be searched by a process of the same user. – Spacedman Dec 6 '17 at 18:19
3

Thanks Gustry for your guide. This pyQgis, code finally worked:

def getURI(self):
    uri = QgsDataSourceURI()
    uri.setConnection(self.host,self.port , self.database, "","", QgsDataSourceURI.SSLdisable,"")
    configId='nnnID'
    self.initAuthManager(configId)
    uri.setAuthConfigId(configId)
    return uri


def initAuthManager(self,configId):
    self.AUTHDB_MASTERPWD = 'yourPluginId'
    if self.am==None:
        self.am=QgsAuthManager().instance()
    if not self.am.masterPasswordHashInDb():
        self.am.setMasterPassword(self.AUTHDB_MASTERPWD, True)
        self.am.authenticationDbPath()
        self.am.masterPasswordIsSet()

    cfg = QgsAuthMethodConfig()
    cfg.setId(configId)
    cfg.setName('yourPluginName')
    cfg.setMethod('Basic')
    cfg.setConfig('username', "secretuser")
    cfg.setConfig('password', "secretpassword")
    self.am.storeAuthenticationConfig(cfg)

def insertLayer(self):
    uri= self.getURI
    vlayer = QgsVectorLayer(uri.uri(False), table,'postgres')
    QgsMapLayerRegistry.instance().addMapLayer(vlayer,True)
1

It depends on what is your final purpose.

  • Plugin writers must use publicSource

It seems you need to display the source of the layer within your plugin. So you can use QgsMapLayer.publicSource() instead of QgsMapLayer.source().

Gets a version of the internal layer definition that has sensitive bits removed (for example, the password). This function should be used when displaying the source name for general viewing.

https://qgis.org/api/classQgsMapLayer.html#a2da43913a3a0ed20b4873b2276e2e7f9

  • The user must use the authentication system when they add layers in QGIS

When the user is adding a layer, there is warning from QGIS saying that password and user are stored in the project. This is a security issue.

Unsecure way of storing user/password

But the user should use the Authentification System provided in QGIS: https://docs.qgis.org/2.14/en/docs/user_manual/auth_system/auth_overview.html

Secure way of storing user/password

For example, I'm adding the same layer with these two different methods. First by adding my credentials following my first screenshot. I got the warning from QGIS about password. Then I added the layer again with the authentification system (cf the second screenshot above):

iface.activeLayer().source()
u'dbname=\'stdm\' host=localhost port=5433 user=\'etienne\' password=\'etienne\' sslmode=disable key=\'id\' srid=4326 type=MultiPolygon table="public"."buildings" (geom) sql='
iface.activeLayer().source()
u'dbname=\'stdm\' host=localhost port=5433 sslmode=disable authcfg=1363gs5 key=\'id\' srid=4326 type=MultiPolygon table="public"."buildings" (geom) sql='

My password is not there anymore.

  • The problem here is that an average user can open the Python console available in QGis and type: layer=iface.activeLayer() layer.source() And obtain the database user and password. I think there must be an option to prevent this attack. There must be a way to hide the user and password for the layer. – Alfredo Garcia Dec 6 '17 at 15:08
  • That's why I said it depends on the final purpose of your question. I added some explanations if you add layers using the authentification system in QGIS. – etrimaille Dec 6 '17 at 15:30
  • Thank you very much for the example, I reproduce it with no problem using the QGis UI, now I will try to reproduce it via PyQgis. Thanks a lot. – Alfredo Garcia Dec 6 '17 at 18:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.