Sécurité

    Un client FlowerDocs, 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’algorithme de hashage SHA-256 et d’une clé secrète.

    A chaque requête reçue, le Core valide le jeton fourni à 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 core.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 à FlowerDocs peuvent être définis au niveau du Core. Ces utilisateurs peuvent être utilisés comme compte de service, pour des administrateurs etc.

    L’utilisateur system est le compte utilisé par les différentes applications FlowerDocs. 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 FlowerDocs simplifiant l’authentification auprès de FlowerDocs

    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 profils (rôles, groupes, équipes) du compte

    Ces comptes additionnels peuvent être configurés dans les fichiers core.properties et gui.properties tels 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 core.properties et gui.properties, Flower fourni un mécanisme de chiffrement des secrets.


    Afin d’indiquer à FlowerDocs 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 réalisé de plusieurs façons à partir d’un secret principal :

    
    <clm> encrypt --secret=<secret> --password=<propriété à chiffrer>
    
    
    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 les fichiers core.properties et gui.properties (déconseillé)


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

    LDAP par défaut

    Cette partie concerne la configuration d’un annuaire par défaut pour une instance FlowerDocs.

    Cette partie n’est pas à suivre dans le cas d’une configuration de l’annuaire à travers l’interface d’administration.

    Accès

    Pour configurer l’accès à l’annuaire d’entreprise, il nécessaire d’identifier le type nécessaire :

    • simple : LDAP simple de type Apache Directory Server ou OpenLDAP
    • ad : Microsoft Active Directory
    • ad-ds : Microsoft ADLDS
    • embedded : Apache Directory Server embarqué sur le port 3389

    Le type d’annuaire peut ensuite être défini par application WEB :

    • Pour la GUI grâce à la propriété : gui.ldap.type
    • Pour le Core grâce à la propriété : ws.ldap.type

    Exemple : Configuration d’un serveur embarqué

    gui.ldap.type=embedded
    ws.ldap.type=simple

    Pour configurer l’accès à l’annuaire LDAP, il est nécessaire de renseigner la propriété ldap.

    Propriété Valeur par défaut Description
    ldap.bind.url ldap://localhost:389 Adresse de l’annuaire
    ldap.bind.root Noeud de base dans la structure LDAP
    ldap.base.dn Base de recherche des utilisateurs

    Note : Dans le cas où l’annuaire LDAP est embarqué, il est nécessaire d’ajouter la propriété ldap.bind.root correspondant au noeud de base dans la strucutre LDAP.

    Compte d’accès

    Un compte de type admnistrateur doit être configuré permettant d’effectuer des actions :

    • recherche d’utilisateur
    • récupération d’utilisateur
    • authentification
    • etc.
    Propriété Description
    ldap.bind.dn Distinguished Name de l’utilistateur
    ldap.bind.password Mot de passe de l’utilistateur

    Attributs / mapping

    Afin de récupérer (ou authentifier) des utilisateurs contre l’annuaire configuré, il faut également définir :

    Propriété Description
    ldap.attr.id Attribut permettant de récupérer l’identifiant d’un utilisateur

    Exemples :

    • MS Active Directory : sAMAcountName
    • MS Active Directory LDS : uid
    • Apache Directory Server : uid

    D’autres attributs utilisés pour le mapping d’utilisateur peuvent être définis :

    Propriété Description
    ldap.attr.display.name Attribut permettant de récupérer l’identifiant d’un utilisateur
    ldap.attr.password Attribut permettant de récupérer le mot de passe d’un utilisateur

    Administration du LDAP

    Création d’un utilisateur

    Depuis l’interface d’administration, il est possible de créer des utilisateurs avec un mot de passe par défaut. Pour cela, le mot de passe ne doit pas être obligatoire.

    Propriété Description
    ldap.default.password Mot de passe par défaut si aucun n’est défini lors de la création
    ldap.user.password.mandatory Booléen définissant le critère obligatoire du champ mot de passe

    La création d’utilisateurs ou de groupes ne peut être effectuée qu’à la racine du noeud d’accès au LDAP.

    Exemple : Pour un MS Active Directory: <domaine>/<base DN>

    Batch

    Pour créer plusieurs utilisateurs en une seule requête, il est possible d’envoyer la requête :

    • Méthode : POST

      <UserBatch xmlns:ns2="http://flower.com/docs/domain/security" xmlns:ns3="http://flower.com/docs/domain/common">
      <users>
          <ns3:id>user_id</ns3:id>
          <ns2:displayName>My Display name</ns2:displayName>
          <ns2:credentialsExpired>false</ns2:credentialsExpired>
      </users>
      </UserBatch>

    Exemples de configuration

    LDAP embarqué

    ldap.bind.url=ldap://localhost:3389
    ldap.bind.root=dc=arondor,dc=com
    ldap.base.dn=ou=employees
    ldap.attr.id=uid
    ldap.bind.dn=uid=fadmin,ou=Administrators,ou=employees,dc=arondor,dc=com
    ldap.bind.password=okidoki

    ADLDS

    ldap.bind.url=ldap://ldap.company.com:389
    ldap.bind.root=dc=arondor,dc=dev
    ldap.bind.dn=CN=fadmin,OU=Demo,OU=FlowerDocs,DC=arondor,DC=dev
    ldap.bind.password=okidoki
    ldap.base.dn=OU=Demo,OU=FlowerDocs
    ldap.attr.id=CN
    ldap.attr.display.name=displayName

    OpenLDAP

    OpenLDAP requiert que le base DN utilisé

    ldap.bind.url=ldap://ldap.company.com:389
    ldap.bind.root=
    ldap.base.dn=dc=arondor,dc=dev
    ldap.attr.id=CN
    ldap.bind.dn=CN=admin,DC=arondor,DC=dev
    ldap.bind.password=okidoki
    ldap.attr.display.name=displayName

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


    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.

    Configuration

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

    • ClientId : l’identifiant représentant la GUI FlowerDocs
    • ClientSecret : le mot 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 : 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
    • MemberOfAttribute : Nom de l’attribut permettant de fournir des groupes

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


    Classe de documents 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:tagReferences tagName="MemberOfAttribute" 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>

    Connexion automatique

    Pour authentifier un utilisateur automatiquement à l’aide de ce mécanisme d’authentification, il est possible d’ajouter le paramètre sso=auto dans l’URL.

    Avec ce paramètre, l’utilisateur, lorsqu’il accède à la page de connexion est automatiquement authentifié en utilisant OpenId Connect.

    Les permissions

    De manière générale, les permissions autorisées sont :

    Permission Description
    CREATE Autorise la création
    READ Autorise l’accès en lecture
    UPDATE Autorise la modification
    DELETE Autorise la suppression
    READ_HISTORY Accès à l’historique
    READ_TASK_HISTORY Accès au suivi des tâches

    Les permissions spécifiques aux documents :

    Permission Description
    READ_CONTENT Accès en lecture du contenu
    UPDATE_CONTENT Modification du contenu
    DOWNLOAD_CONTENT Téléchargement du contenu (visionneuse)
    PRINT Impression (visionneuse)
    CREATE_ANNOTATION Création d’annotation (visionneuse)
    READ_ANNOTATION Lecture des annotations existantes (visionneuse)
    BUILD_NEW_DOCUMENT Activation du découpage de document (visionneuse)

    Les permissions spécifiques aux tâches :

    Permission Description
    APPROPRIATE S’approprier une tâche non assignée
    APPROPRIATE_ALREADY_ASSIGNED S’approprier une tâche déjà assignée
    ASSIGN Assigner une tâche à un utilisateur
    APPLY_ANSWER Appliquer une réponse
    UPDATE_CONTENT Modification des pièces jointes
    DELETE_CONTENT Suppression d’une pièce jointe
    READ_CONTENT Visualisation des pièces jointes

    Les identités

    Au sens FlowerDocs, une identité est soit un utilisateur, un groupe ou une équipe. La notion d’équipe a été introduite afin de centraliser et mutualiser la gestion des autorisations communes à une ou plusieurs identités.

    ACL Proxy

    Les objets de type ACLProxy permettent d’ajouter un aspect métier à la gestion des habilitations.

    Un proxy est également un SecurityObject permettant de définir la sécurité à appliquer sur un composant. Il s’appuie sur des conditions pour déterminer quelle est l’ACL à appliquer sur un composant.

    Exemple :

    Pour une classe de documents Facture, le proxy suivant pourrait être utilisé :

    • si montant < 100€ : tout le monde a le droit de voir / modifier le document
    • si 100€ < montant : tout le monde a le droit de voir en lecture seule le document

    Schéma

                          SecurityObject
                                |
             _______________________________
            |                               |
     AcessControlList  <-----            ACLProxy
            |                |              |
            | 1:N            |              | * rules : List<ACLRule>  ---
            |                |                                           |
    AccessControlEntry       |                                           |
                             |                                           |
                             |           ACLRule  <-----------------------
                             |              |
                             |              | * conditions : List<String>
                             |____1:1_______| * aclId : Id
    

    Rôles

    Les rôles donnent accès à des fonctionnalités FlowerDocs à travers la notion d’équipe.

    Pour affecter un rôle à un utilisateur :

    • créez une équipe dont l’identifiant est le nom du rôle
    • ajoutez des utilisateurs dans une équipe
    Rôle Description
    ADMIN Administre un scope
    DOCUMENT_CREATOR Accède à l’onglet Insérer