jeudi 19 mai 2011

Création d'une mini PKI




Au moment d'ajouter la couche SSL à une application web, vient toujours la même questions "Comment ça marche déjà? Je l'ai déjà fait il y a plusieurs années, je me suis pris la tête mais je ne me rappelle plus comment!"... et je recommence à zéro! Alors voici un lien pour créer sa propre AC.



A des fins de tests on créé souvent des certificats autosignés (self-signed) car c'est facile. Toutefois pour rendre le test plus proche de la situation réelle, il peu être interressant de travailler avec des certificats qui sont signés par une autorité de certification, mais comment créer une autorité de certification??? Réponse sur 
http://artisan.karma-lab.net/node/1153 !


samedi 26 février 2011

MVP et GWT




J'ai trouvé deux articles intéressants sur le pattern MVP sur ce blog:




http://www.mikaelkrok.net/le-design-pattern-mvp-et-gwt-1-introduction



et




http://www.mikaelkrok.net/le-design-pattern-mvp-et-gwt-2-mvp-en-detail





Et voilà comment on fait un billet marque page!


vendredi 18 février 2011

MDB: utiliser des EJB sécurisés







Allez encore un petit billet sur la sécurité et les MDB.

Lorsqu'un MDB reçoit un message, il peut arriver (et même dans la plupart des cas!) qu'il doive consommer des services qui sont exposés par d'autres EJB. Supposons que l'EJB en question comprenne un contrôle d'accès sur ses méthodes:





@Stateless
@Local(LocalMyService.class)
@DeclareRoles("authenticated")
@RolesAllowed("authenticated")
public class MyServiceImpl implements LocalMyService {




... et que ce service est injecté dans un MDB:





@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "user",
propertyValue = "mdbuser"),
@ActivationConfigProperty(propertyName = "password",
propertyValue = "mdbpassword"),
@ActivationConfigProperty(propertyName = "acknowledgeMode",
propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination",
propertyValue = "/queue/myQueue")
})
public class MyMDB implements MessageListener {
@EJB
private LocalMyService service;

@Override
public void onMessage(Message message) {
[...]
service.myMethod();










Là l'affaire se corse car les messages JMS n'embarquent pas de contexte de sécurité (après recherche et sauf erreur de ma part), et lors de la réception d'un message le MDB se verra l'accès refusé au service. Et bien c'est
presque pas grave, car la spec EJB couvre ce problème et permet la substitution de rôle avec l'annotation javax.annotation.security.@RunAs qui prend en paramètre le nom du rôle à donner au bean (ici le MDB):








@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "user",
propertyValue = "mdbuser"),
@ActivationConfigProperty(propertyName = "password",
propertyValue = "mdbpassword"),
@ActivationConfigProperty(propertyName = "acknowledgeMode",
propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination",
propertyValue = "/queue/myQueue")
})
@RunAs("authenticated")
public class MyMDB implements MessageListener {
@EJB
private LocalMyService service;

@Override
public void onMessage(Message message) {
[...]
service.myMethod();













Il est intéressant de noter que j'ai écrit "
presque pas grave"! Presque, car le conteneur JEE sélectionné pour le projet en question était JBoss 6.0.0.Final qui est directement impacté par le bug 
EJBTHREE-1945. Le sujet de bug est que le rôle est correctement substitué dans le premier appel de méthode sécurisé, mais si cette méthode fait elle-même appel à une autre méthode sécurisée , le rôle est perdu... autant dire que tout l'intérêt de RunAs est caduque! 






J'ai donc demandé s'il existait un moyen de contournement et je me suis inspiré de la réponse pour mon besoin en créant un intercepteur assigné au MDB qui authentifie le MDB avant l'invocation de la méthode onMessage:









public class RunAsInterceptor {
@AroundInvoke
public Object intercept(InvocationContext ctx) throws Throwable {
SecurityClient securityClient = null;

try {
securityClient = SecurityClientFactory.getSecurityClient();
securityClient.setSimple(userName, password);
securityClient.login();

return ctx.proceed();

} finally {
if (securityClient != null) {
securityClient.logout();
}
}
}
}







L'ombre au tableau est qu'une classe hors spec JEE issue de l'API propre à JBoss est impliquée (SecurityClient), je n'ai pas poussé pour trouver un moyen d'authentification avec les outils JEE stricts, si quelqu'un a ça en stock, je suis preneur! Je vous laisse le soin de définir comment paramétrer userName et password, moi je l'ai fait avec le chargement de propriétés dans le constructeur sans arguments. 






L'utilisation dans le MDB:






@MessageDriven(activationConfig = {
[...]
})
@Interceptors({RunAsInterceptor.class})
public class MyMDB implements MessageListener {



L'avantage de cette conception est que lorsque les gens de JBoss se décideront à résoudre ce problème qui date de 2009, il n'y aura qu'à dégager l'intercepteur et le remplacer par @Runas!



Mais bon, c'est la tour de Babel!


Message Driven Bean: configuration de l'accès à une Destination sécurisée









Pour des besoins évidents, on m'a demandé de sécuriser l'accès aux Destinations JMS (Queue/Topic), c'est à dire les composants doivent s'authentifier pour pouvoir publier ou consommer des  message.

Quand la connexion est créée programmatiquement, pas de soucis:




connectionFactory.createConnection(jmsUserName, jmsPassword);


Toutefois, la question s'est posée lorsque j'ai du déployer un MDB et après avoir fouillé dans la JSR EJB spec 3.1, je n'ai pas trouvé comment indiquer dans les méta données les valeurs user et password. Puis en élargissant le champ de mes recherches avec Google, je suis tombé sur la config suivante qui répond au besoin:




@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "user",
propertyValue = "mdbuser"),
@ActivationConfigProperty(propertyName = "password",
propertyValue = "mdbpassword"),
@ActivationConfigProperty(propertyName = "acknowledgeMode",
propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination",
propertyValue = "/queue/myQueue")
})
public class MyMDB implements MessageListener {
D'accord, c'était quasi-évident... mais comme je trouve que ça manque un peu de documentation, je remets une couche!


jeudi 10 février 2011

Aspirer un site avec wget




Ce matin je voulais pouvoir accéder à la documentation GWT offline, mais Google ne propose pas cette option, alors j'ai essayé de récupérer le maximum d'informations avec wget.



Voici les options que j'ai choisi et pourquoi je les ai choisies:




$ wget -nc -k -q -r -p -L -R community.html http://code.google.com/webtoolkit/doc/latest/



-nc: no clobber: pour que chaque ressource ne soit téléchargée qu'une seule fois

-k : pour que les liens soient transformés en liens locaux de manière à faciliter la consultation locale

-q : pour que l'affichage sur la console ne prenne pas plus de temps que le téléchargement lui même!

-p : pour que toutes les ressources nécessaire à chaque page soit également téléchargées

-L: pour éviter de télécharger tout Internet

-R: je ne voulais pas community car j'avais peur de télécharger tout le forum!

-r : recursive... of course



Voilà, c'est une note de coin de table, n'hésitez pas à apporter des précisions si elle vous semble incomplète.


lundi 31 janvier 2011

Maven Surefire: Lancer un seul test




Il est parfois fastidieux d'avoir à lancer l'intégralité des tests d'un projet ou module maven si on a besoin d'en lancer un seul. Pour éviter cela on peut indiquer à surefire quel test exécuter:






$ mvn test -Dtest=OnlyMe





On notera également qu'il n'est pas nécessaire d'utiliser le "Fully qualified name" de la classe de test, le nom de la classe est suffisant.



Plus d'infos:  
http://maven.apache.org/plugins/maven-surefire-plugin/examples/single-test.html


http://maven.apache.org/plugins/maven-surefire-plugin/test-mojo.html#test


lundi 24 janvier 2011

Hibernate: valeur des paramètres et log




Toujours galère de d'analyser les logs d'une appli utilisant Hibernate car les requêtes sont paramétrées (heureusement) et les paramètres ne sont pas directement accessible (on voit des '?' en lieu et place des valeurs dans les clause where).



Pour y remédier, rien de plus simple, il faut activer les loggers d'Hibernate qui journalisent ces informations. Donc dans log4j.properties (ou sa version XML), placer la directive suivante:




log4j.category.org.hibernate.type.descriptor.sql=TRACE



Cela permettra de trouver dans les logs les messages suivants pour chaque requête paramétrée envoyée par Hibernate:






4000 [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder  - binding parameter [1] as [BIGINT] - 1295864313859


4000 [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder  - binding parameter [2] as [TIMESTAMP] - Mon Jan 24 11:18:33 CET 2011


4000 [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder  - binding parameter [3] as [BIGINT] - 1295864313843