Sécurité

Sécurisation du Core et de la GUI

    Cette section adresse les aspects de sécurité concernant la GUI et le Core.

    Un client Flower, comme la GUI, nécessite d’être authentifié pour pouvoir communiquer avec le Core. Cette authentification est soumise sous la forme d’un jeton JWT.


    Un jeton est généré par le Core et est signé grâce à un HMAC calculé à partir de l’agorithme de hashage SHA-256 et d’une clé secrète.

    A chaque requête reçue, le Core valide le jeton fourni et est validé à l’aide de la clé secrète.


    Par défaut, cette clé secrète est générée au démarrage du Core de manière aléatoire (sur 32 caractères). Il est conseillé de la définir dans le fichier flowerdocs.properties grâce au paramètre token.key.


    Un jeton est valide pendant 3600s (soit 60 minutes) à partir du moment où il a été généré. Pour changer cette durée de validité, le paramètre token.expiration.time (durée en secondes) peut être défini au niveau du Core.


    Dans certains cas, il peut être nécessaire d’inclure le mot de passe du compte utilisé dans le jeton généré. Cette configuration peut être activée à l’aide des paramètres :

    • Inclusion : token.password.include (valeur par défaut false)
    • Passphrase : token.password.passphrase
    • Iv : token.password.iv

    La durée de vie du token doit être supérieure à celle de la session utilisateur pouvant être définie grâce à gui.session.timeout (secondes - valeur par défaut 1800)

    Des utilisateurs propres à Flower peuvent être définis au niveau du Core. Ces utilisateurs peuvent être utilisés comme compte de service, pour des administrateurs…

    L’utilisateur system est le compte utilisé par les différentes applications Flower. Ses informations peuvent être configurées à l’aide des paramètres system.admin.username et system.admin.password.


    Ce compte est utilisé par :

    • La GUI pour charger sa configuration
    • Le Core pour exécuter les OperationHandlers
    • Le CLM pour gérer les scopes
    • Le client Java Flower simplifiant l’authentification auprès de Flower

    Pour chacune de ces applications, il est conseillé de configurer le compte utilisé (un différent pour chaque application).


    Le Core permet de définir des comptes additionnels et leurs informations :

    • id : l’identifiant du compte
    • password : le mot de passe du compte
    • profiles : les profiles (rôles, groupes, équipes) du compte

    Ces comptes additionnels peuvent configurés dans le fichier flowerdocs.properties tel que :

    internal.realm.users[0].id=client1
    internal.realm.users[0].password=<password>
    internal.realm.users[0].profiles=ADMIN,ALL_USERS,JURIDIQUE,COMMERCE,MARKETING,COMPTABILITE
    

    Les différents comptes définis, au niveau du Core, peuvent être utilisés pour l’ensemble des scopes existants.

    Il est déconseillé de stocker des mots de passe en clair dans des fichiers de configuration. Afin d’éviter de stocker les différents secrets en clair dans les fichiers flowerdocs.properties, Flower fourni un mécanisme de chiffrement des secrets.


    Afin d’indiquer à Flower que la valeur d’une propriété est chiffrée, elle doit être définie telle que ENC(<valeur chiffrée>). Une propriété chiffrée est déchiffrée au démarrage de l’application à l’aide de son secret principal (secret). Ainsi un chiffrement différent peut être défini pour chacune des applications.

    L’application ne peut pas démarrer si une propriété, indiquée comme étant chiffrée, ne peut être déchiffrée.


    Le chiffrement de propriété peut être realisé à l’aide de plusieurs façons à partir d’un secret principal (pouvant être différent par application) :


    CLM
    <clm> encrypt --secret=<secret> --password=<propriété à chiffrer>
    

    CURL
    curl -X POST \
      <core>/rest/encrypt \
      -H 'token: <token>' \
      -d toEncrypt
    

    Le secret de chacune des applications peut être défini de différentes manières :

    • comme variable d’environnement
    • comme propriété de la JVM
    • dans le fichier flowerdocs.properties (déconseillé)

    Il est conseillé de définir, avec cette méthode, les propriétés token.key et system.admin.password à minima.

    Basé sur le protocole OAuth 2 et son mécanisme de code d’autorisation, OpenID Connect est utilisé par la GUI Flower afin de fournir à ses utilisateurs un mécanisme de Single Sign On.

    authorizationgranttype ..

    Ce mécanisme d’authentification est configurable depuis la console d’administration Flower. Les informations listées ci-dessous peuvent être configurées :

    • ClientId : l’identifiant représentant la GUI Flower
    • ClientSecret : le mot de passe de passe associé à l’identifiant
    • RedirectUriTemplate : template utilisé pour la génération du paramètre redirect_uri (la valeur doit être définie à {baseUrl}/login/oauth2/code/{registrationId})
    • Scope : les scopes OAuth 2.0 (à minima openid et email)
    • AuthorizationUri : Endpoint d’autorisation de l’utilisateur
    • TokenUri : Endpoint permettant de récupérer les jetons
    • JwkSetUri : Endpoint utilisé pour accéder à la clé publique (JWK) du serveur d’autorisations permettant de valider les informations reçues
    • UserInfoUri : Endpoint exposant les attributs (ou claims) des utilisateurs
    • UserNameAttributeName : Le nom de l’attribut à utiliser comme identifiant de l’utilisateur
    • RegistrationId : Identifiant unique du serveur d’autorisation
    • ClientName : Libellé du client
    • Icon : Icône Font Awesome à afficher sur la page de connexion

    Pour plus de détails, consulter les spécifications OpenId Connect


    Classe de document OAuthClientConfiguration
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <ns5:DocumentClass category="DOCUMENT" active="false" technical="true" xmlns="http://flower.com/docs/domain/common"
    	xmlns:ns2="http://flower.com/docs/domain/componentclass" xmlns:ns3="http://flower.com/docs/domain/i18n"
    	xmlns:ns5="http://flower.com/docs/domain/documentclass">
    	<id>OAuthClientConfiguration</id>
    	<ns2:tagReferences tagName="ClientId" mandatory="true" multivalued="false" technical="false" readonly="false" order="0" />
    	<ns2:tagReferences tagName="ClientSecret" mandatory="true" multivalued="false" technical="false" readonly="false" order="0" />
    	<ns2:tagReferences tagName="RedirectUriTemplate" mandatory="true" multivalued="false" technical="false" readonly="false" order="0" />
    	<ns2:tagReferences tagName="Scope" mandatory="false" multivalued="true" technical="false" readonly="false" order="0" />
    	<ns2:tagReferences tagName="AuthorizationUri" mandatory="true" multivalued="false" technical="false" readonly="false" order="0" />
    	<ns2:tagReferences tagName="TokenUri" mandatory="true" multivalued="false" technical="false" readonly="false" order="0" />
    	<ns2:tagReferences tagName="JwkSetUri" mandatory="false" multivalued="false" technical="false" readonly="false" order="0" />
    	<ns2:tagReferences tagName="UserInfoUri" mandatory="true" multivalued="false" technical="false" readonly="false" order="0" />
    	<ns2:tagReferences tagName="UserNameAttributeName" mandatory="true" multivalued="false" technical="false" readonly="false" order="0" />
    	<ns2:tagReferences tagName="RegistrationId" mandatory="true" multivalued="false" technical="false" readonly="false" order="0" />
    	<ns2:tagReferences tagName="ClientName" mandatory="false" multivalued="false" technical="false" readonly="false" order="0" />
    	<ns2:tagReferences tagName="Icon" mandatory="false" multivalued="false" technical="false" readonly="false" order="0" />
    	<ns2:displayNames language="EN">
    		<ns3:value>oAuthClients configuration</ns3:value>
    	</ns2:displayNames>
    	<ns2:displayNames language="FR">
    		<ns3:value>Configuration des oAuth clients </ns3:value>
    	</ns2:displayNames>
    </ns5:DocumentClass>
    


    Exemple pour Google
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <ns3:Document category="DOCUMENT" name="Google" xmlns="http://flower.com/docs/domain/common"
    	xmlns:ns2="http://flower.com/docs/domain/component" xmlns:ns3="http://flower.com/docs/domain/document">
    	<id>Google</id>
    	<ns2:data>
    		<ns2:classId>OAuthClientConfiguration</ns2:classId>
    	</ns2:data>
    	<ns2:Tags>
    		<ns2:tags name="ClientId" readOnly="false">
    			<ns2:value>***</ns2:value>
    		</ns2:tags>
    		<ns2:tags name="ClientSecret" readOnly="false">
    			<ns2:value>***</ns2:value>
    		</ns2:tags>
    		<ns2:tags name="RedirectUriTemplate" readOnly="false">
    			<ns2:value>{baseUrl}/login/oauth2/code/{registrationId}</ns2:value>
    		</ns2:tags>
    		<ns2:tags name="Scope" readOnly="false">
    			<ns2:value>openid</ns2:value>
    			<ns2:value>profile</ns2:value>
    			<ns2:value>email</ns2:value>
    			<ns2:value>address</ns2:value>
    			<ns2:value>phone</ns2:value>
    		</ns2:tags>
    		<ns2:tags name="AuthorizationUri" readOnly="false">
    			<ns2:value>https://accounts.google.com/o/oauth2/v2/auth</ns2:value>
    		</ns2:tags>
    		<ns2:tags name="TokenUri" readOnly="false">
    			<ns2:value>https://www.googleapis.com/oauth2/v4/token</ns2:value>
    		</ns2:tags>
    		<ns2:tags name="JwkSetUri" readOnly="false">
    			<ns2:value>https://www.googleapis.com/oauth2/v3/certs</ns2:value>
    		</ns2:tags>
    		<ns2:tags name="UserInfoUri" readOnly="false">
    			<ns2:value>https://www.googleapis.com/oauth2/v3/userinfo</ns2:value>
    		</ns2:tags>
    		<ns2:tags name="UserNameAttributeName" readOnly="false">
    			<ns2:value>sub</ns2:value>
    		</ns2:tags>
    		<ns2:tags name="RegistrationId" readOnly="false">
    			<ns2:value>google</ns2:value>
    		</ns2:tags>
    		<ns2:tags name="ClientName" readOnly="false">
    			<ns2:value>Google</ns2:value>
    		</ns2:tags>
    		<ns2:tags name="Icon" readOnly="false">
    			<ns2:value>border-danger text-danger mdi mdi-google</ns2:value>
    		</ns2:tags>
    	</ns2:Tags>
    </ns3:Document>
    


    La clé secrète du Core doit être partagée avec la GUI pour pouvoir utiliser ce mécanisme. Il est donc nécessaire de renseigner, dans le fichier de configuration de la GUI, la même valeur pour la propriété token.key que pour le Core.