Solutions de contournement des difficultés rencontrées lors de la réalisation d'un POC dans le cadre d'une recherche d'une solution satisfaisante à la gestion de la sécurité.Description de la problématique.Dans le cadre de la réalisation de la partie workflow d'un POC, un problème relatif à la gestion de la sécurité est apparu. Nous désirions ne donner à chaque acteur du workflow que l'accès à son propre espace de travail (son " home folder " avec ses sous-folders). Si l'on donne à chaque acteur un droit exclusif sur son espace de travail, les actions du workflow qui sont déclenchées par d'autres acteurs n'auront pas accès à cet espace de travail alors que la logique du workflow nécessite de tels accès. Cette situation est essentiellement due au fait que le workflow est réalisé par un script exécuté avec les droits de l'utilisateur courant dans la session qui a déclenché son exécution (dans le cas de notre workflow l'exécution du script est déclenchée par des règles liées aux évènements sur les répertoires). Description des solutions envisagées.Nous avons envisagé diverses pistes :1. Exécuter le script de réalisation du workflow via la " command servlet ". La situation obtenue au niveau de la problématique de la gestion de la sécurité est relativement semblable à l'exception du fait que le workflow doit intervenir dans moins de répertoires (il n'est plus nécessaire de copier ou déplacer le document à traiter dans divers répertoires mais par contre le workflow doit pouvoir écrire dans des " INPUT BOXES ").2. Faire en sorte que le webClient ne présente pas certains folders à l'utilisateurs alors que celui-ci a sur ces folders les droits suffisants pour que le workflow y réalise les tâches nécessaires.3. Faire en sorte que le script soit exécuté avec les droits de l'administrateur.La première piste a été abordée avant que cette problématique de gestion de la sécurité n'apparaisse dans le but de dégager une solution plus simple dans la réalisation de notre workflow. Comme signalé ci-avant cette solution réduit les problèmes de gestion de la sécurité mais ne les résout pas complètement.La seconde piste a donné lieu à deux approches : a. la recherche d'une solution permettant de poser sur un folder des droits suffisants pour le workflow mais tels que le client web ne " montre " pas ce folder à l'utilisateur,b. l'utilisation de folders " écrans " qui cachent à l'utilisateur des sous-folders sur lesquels il a des droits d'accès.L'approche " a " consisté à modifier les droits nécessaires pour faire certaines opérations dont le script a besoin. Le principal blocage que nous rencontrions était dû au fait que si le script n'avait pas le droit " Read " sur un folder, il ne pouvait pas obtenir sa référence via l'appel des fonctions JavaScript telles que " childByNamePath " et il ne pouvait pas non plus réaliser une quelconque opération dans le folder (comme la création d'un fichier dans ce folder). Or, dès que nous donnions à un utilisateur du workflow, le droit " Read " sur un folder, le webClient montrais à cet utilisateur la présence de ce folder (et c'est ce qu'on veut éviter). La solution consiste à donner des droits, aux folders auxquels le workflow doit avoir accès ; droits tels que le webClient ne montre pas ces folders à l'utilisateur et tels que le script puisse quand même y accéder. Nous avons obtenu cela en définissant un nouveau profil de droits " jsCoordinator " (droits de coordination pour le code JavaScript) ; ce profil donne sur un folder tous les droits d'un " Coordinateur " sauf le droit " ReadContent ". Le webClient ne montre pas à l'utilisateur un folder sur lequel il a juste le profil " jsCoordinator " (pour que le webClient montre un folder à l'utilisateur il faut que celui-ci ait le groupe de droits " Read " sur ce folder, groupe de droits qui regroupe les droits " ReadProperties ", " ReadContent " et " ReadChildren "). Il a ensuite fallu modifier le fichier " public-services-security-context.xml " (nous sommes conscient que c'est délicat dans la mesure où cela peut influer sur le comportement du webClient) ; nous avons un peu modifié la définition des droits nécessaires à l'exécution des services dont le code JavaScript a absolument besoin : cela a consisté à déclarer que les services de recherche peuvent retourner un nœud si l'utilisateur a les droits de lecture de ses propriétés et de ses fils (nous avons retiré la nécessité d'avoir aussi le droit de lecture du contenu de ce nœud). La poursuite de cette piste a amené un second problème : lorsque le script créait un fichier dans un folder sur lequel il avait juste les droits " jsCoordinator ", le fichier créé héritait des droits du folder et donc le script ne pouvait pas lire le contenu de ce fichier (ni écrire dans le contenu de ce fichier). Contrairement au workflow initialement développé pour le POC, le workflow alternatif doit pouvoir écrire dans le contenu de fichiers (pour les fichiers qui constituent les messages du workflow). Notre première idée pour résoudre ce problème a été de faire en sorte que le script attribue explicitement des droits aux objets qu'il crée : la documentation de Alfresco renseigne des fonctions JavaScript permettant d'accéder aux droits d'un objet mais ces fonctions ne seront disponibles que dans la version 1.4. Nous aurions pu trouver un contournement (comme créer l'objet dans un folder où le script a des droits suffisants puis déplacer ce fichier vers le répertoire cible) mais nous n'avons pas poursuivi cette voie en raison du caractère délicat de la modification du fichier " public-services-security-context.xml ".L'approche " b " a été plus fructueuse. Nous avons appliqué le principe suivant : on limite l'accès au répertoire principal de chaque type d'acteur (home_folder pour ce type d'utilisateurs) ; le workflow ne va travailler qu'avec des sous-répertoires de ces répertoires protégés. Nous rendons les sous-répertoires accessibles au workflow (cela signifie en clair que nous avons donné le profil " Coordinateur " à tous les acteurs du workflow sur ces sous-répertoires, nous pourrions sans doute réduire un peu le profil sur certains de ces folders mais le principe restera le même). Cela fonctionne car Alfresco va laisser le script accéder à un sous-répertoire même s'il n'a pas le droit d'accéder à son répertoire parent. Cette façon de procéder est loin d'être parfaite : via une recherche, un utilisateur du workflow pourrait accéder à un de ces sous-répertoires et y réaliser des opérations " manuelles " alors que l'intention est bien que seul le workflow puisse agir dans ces répertoires. De plus, cette situation empêche le script du workflow d'accéder directement aux " home folders " : il ne peut accéder qu'aux sous répertoires de ceux-ci. Cela implique qu'il ne peut pas, par exemple, consulter les noms de ces " home folders ". Il restait à résoudre un problème au niveau de la recherche de la liste des groupes à proposer comme candidats " targets ". Cette liste est actuellement établie en repérant les folders qui répondent au pattern /BAL_GR.*/. Pour parcourir ces folders dans le but d'établir cette liste, le script devrait avoir le droit " Read " sur ces folders. Cette liste est essentiellement constante, nous avons en conséquence utilisé le contournement suivant : la liste sera établie une seule fois, à la première exécution du workflow et stockée ensuite dans un objet de gestion du workflow (objet commun à toutes les instances du workflow) - cet objet est créé dans le répertoire où nous mettons les objets de gestion qui représentent l'état de chaque instance du workflow. Ainsi, il suffit que celui qui exécute le premier dépôt d'un fax à traiter ait les droits suffisants pour lire les noms des folders BAL_GR… (on peut envisager dans la procédure d'installation du workflow de spécifier que l'administrateur doit faire cette opération initiale et en profiter pour faire un test du bon fonctionnement du workflow). Cette technique ne serait pas totalement applicable au workflow initialement développé pour le POC, car dans ce cas la désignation par l'acteur " routeur " des groupes cibles passe par une relation établie avec l'interface-utilisateur du webClient (écran d'édition des propriétés) et cela nécessite que cet acteur ait au minimum un accès " Read " aux folders de ces groupes. Pour le workflow initial du POC, on pourrait envisager de contourner ce problème en désignant désormais les groupes cibles au lieu des folders cibles (l'utilisateur a accès à la liste des groupes d'utilisateurs même s'il n'a pas accès à leurs espaces de travail) mais alors il nous reste à trouver un moyen pour retrouver le chemin d'accès à l'espace de travail d'un utilisateur à partir de la référence à l'objet " person " qui le représente (dans un objet " person " se trouve une référence au " home folder " mais nous avons besoin du chemin d'accès de ce " home folder " et pas suffisamment de droits pour lire les attributs de cet objet " folder ").La piste " 3 " a été relativement simple à mettre en œuvre et semble constituer une solution intéressante en attendant que Alfresco implémente l'équivalent (ce point est repris chez Alfresco parmi les tâches à faire mais sa réalisation n'est pas encore planifiée). Pour réaliser la mise en œuvre de cette piste, nous avons procédé comme suit : - Ecriture d'une classe directement inspirée de la classe " ScriptActionExecutor " ; j'ai nommé cette nouvelle classe " ScriptActionExecutorWithAdminRights ". Dans le code de cette classe, nous avons juste placé les lignes suivantes avant l'appel de la méthode " executeScript " : // authenticate as admin
// authenticate
AuthenticationService authenticationService = serviceRegistry.getAuthenticationService();
authenticationService.authenticate("admin", "admin".toCharArray());
- Remplacement dans le fichier de configuration " action-services-context.xml " de la référence à la classe " org.alfresco.repo.action.executer " par la référence à la nouvelle classe.- Placement de la nouvelle classe dans l'environnement accessible au serveur applicatif (pour mon test, je l'ai simplement placée avec les folders qui correspondent au package Java dans le répertoire tomcatwebappsalfrescoWEB-INFclasses). Bien sûr, le code devrait être un peu plus élaboré : le mot de passe de l'utilisateur " admin " ne peut pas être placé ainsi en " dur " dans le code.Il est à remarquer que cette piste " 3 " n'aboutit pas à la résolution du problème que l'on rencontre avec le workflow initialement développé pour le POC au niveau de l'attribution des droits nécessaires pour que le " dispatcher " puisse sélectionner les répertoires cibles (par contre, avec le workflow alternatif cela ne poserait pas problème car la liste des répertoires cibles est constituée par le script exécuté par notre nouvelle classe " ScriptActionExecutorWithAdminRights "). Ici, aussi on pourrait passer par la sélection des groupes d'utilisateurs en lieu et place de la sélection de leur espace de travail (le script exécuté avec les droits de l'administrateur pourrait alors retrouver les chemins des espaces de travail correspondants). Il resterait des problèmes avec le workflow initialement développé pour le POC car celui-ci réalise des " copy " & " move " de fichiers (dans des folders qui devraient être protégés) par exécution directes de règles du " simple workflow " (et donc sans passer par un script). Par contre, pour notre version alternative du workflow il faut réaliser l'équivalent de ce que nous avons fait pour les scripts exécutés par des règles lorsque les scripts sont exécutés via la servlet " action ". Cela nécessite la modification de la servlet " command/ ScriptCommandProcessor.java " :- Ecriture d'une classe directement inspirée de la classe " ScriptCommandProcessor " ; j'ai nommé cette nouvelle classe " ScriptCommandProcessorWithAdminRights ". Dans le code de cette classe, nous avons juste placé les lignes suivantes avant l'appel de la méthode " executeScript " : // authenticate as admin
// authenticate
AuthenticationService authenticationService = serviceRegistry.getAuthenticationService();
authenticationService.authenticate("admin", "admin".toCharArray());
- Remplacement dans le fichier de configuration " web-client-config.xml " de la référence à la classe " org.alfresco.web.app.servlet.command.ScriptCommandProcessor" par la référence à la nouvelle classe. <config evaluator="string-compare" condition="Command Servlet">
<!– The list of registered servlet command processors –>
<!– Command processors implement org.alfresco.web.app.servlet.command.CommandProcessor –>
<!– They register a class impl against a unique name. All calls to the command servlet –>
<!– which match the name are forwared to the class instance –>
<command-servlet>
<command-processor name="workflow" class="org.alfresco.web.app.servlet.command.WorkflowCommandProcessor" />
<command-processor name="script" class="com.fujitsu.web.app.servlet.command.ScriptCommandProcessorWithAdminRights" />
<!– command-processor name="script" class="org.alfresco.web.app.servlet.command.ScriptCommandProcessor" / –>
</command-servlet>
</config>
- Placement de la nouvelle classe dans l'environnement accessible au serveur applicatif (pour mon test, je l'ai simplement placée avec les folders qui correspondent au package Java dans le répertoire tomcatwebappsalfrescoWEB-INFclasses).