Master m-Rehab

Cliquer pour télécharger la présentation du cours

Installation des logiciels :

NOTE Mysql installation avec Windows:

  • Windows 64-bit, ZIP Archive puis ne pas « créer de compte » juste « No thanks, just start my download. »
  • Installation si nécessaire de « Redistribuable Visual C++ pour Visual Studio 2012 » fichiers vcredist_x64.exe et vcredist_x86.exe depuis https://www.microsoft.com/fr-fr/download/details.aspx?id=30679
  • En cas de soucis, possibilité d’installer MAMP : https://www.mamp.info/en/downloads/

Accès aux fichiers pour TP

Liens vers le fichier SQL ci-dessous pour importation dans une base de données :


Accès à la base de données depuis R

install.packages("RMySQL")
library(RMySQL)

L’accès à un serveur de base de données Mysql suppose plusieurs informations techniques, l’adresse du serveur de base de données (ici 127.0.0.1), un compte sur cette base de données (ici root), un mot de passe correspondant à ce compte (ici «  » pour indiquer mot de passe vide), un port de base de données (ici et par défaut 3306 mais sur Mamp cela peut être 8889) et enfin une base de données (ici sante)

DB <- dbConnect(MySQL(), user="root", host="127.0.0.1", password="",dbname="sante" , port=3306)

Une fois la connexion réalisée, on peut lister les tables dans cette base de données sante.

dbListTables(DB)

Et enfin poser des questions en SQL

resultat <- dbGetQuery(DB, "SELECT * FROM data")
print( resultat )

Importation en CSV

La première étape est de trouver le dossier dans lequel Mysql accepte l’importation d’un fichier CSV, la requête SQL est la suivante :

SHOW VARIABLES LIKE "secure_file_priv"
Dossier Mysql autorisé pour importation de fichier CSV

Dans mon cas le dossier est dans c:\Developpement\Wamp64\tmp\ du coup je peux placer mon fichier analyse.csv dans ce dossier et lancé cette requête SQL après avoir créé la table analyse :

LOAD DATA INFILE 'c:/Developpement/wamp64/tmp/analyse.csv' 
INTO TABLE analyse 
FIELDS TERMINATED BY ',' 
ENCLOSED BY '"'
LINES TERMINATED BY '\r\n'
IGNORE 1 ROWS;

Publié dans Médecine | Laisser un commentaire

Protégé : Accès serveur calcul CERIS

Cette publication est protégée par un mot de passe. Pour la voir, veuillez saisir votre mot de passe ci-dessous :

Publié dans Développement | Saisissez votre mot de passe pour accéder aux commentaires.

Ajout de Javadoc dans un programme Java

La constitution de la documentation dans un projet Java peut être simplement réalisé directement dans le code source en utilisant un formatage spécifique dans un commentaire.

Le système Javadoc existe depuis la création de Java (https://en.wikipedia.org/wiki/Javadoc) et invite le développeur à produire directement dans son programme la documentation.

En premier lieu, on peut documenter le package si un fichier package-info.java est disponible. Je vous renvoie vers cette documentation qui explique l’utilité de ce fichier: https://www.baeldung.com/java-package-info. Dans le cas d’un petit projet informatique, voici un commentaire explique l’utilisation d’un package:

/**
 * main est le package principal du projet de test d'intégration de Jenkins
 */
package main;

Pour faire la suite, nous allons documenter une classe Main dans le fichier main.java :

/**
 * Classe de test pour l'intégration de Jenkins
 * @author Pierre Jean
 * @version 1.0
 */
public class Main {

Il faut être humble dans la constitution de la documentation. À mon avis, il vaut mieux produire la documentation progressivement en mettant les premiers éléments puis progressivement compléter cette documentation par ajout de détails.

L’étape suivante est l’ajout de la documentation d’une méthode basique.

	/**
	 * Méthode pour afficher le double de ce nombre 
	 * <p>
	 * Cette méthode sert pour tester l'intégration l'affichage d'un nombre. 
	 * Ce nombre est calculé en appelant une méthode d'une classe Calcul
	 * qui retourne le double du nombre.
	 * <p>
	 * Cette méthode permet de réaliser un test unitaire avec Jenkins.
	 *
	 * @param  nombre paramètre du nombre pour réaliser le doublement
	 * @return retourne le nombre affiché 
	 */
	public int afficheDeuxFois(int nombre) {
		System.out.println(Calcul.doublement(nombre));
		return Calcul.doublement(nombre);
	}

J’ai ajouté beaucoup d’explication sur une méthode très basique pour détailler la forme de cette documentation avec un seul paramètre et une valeur de retour.

Nous pouvons maintenant imaginer la génération de la documentation sous la forme de pages HTML via le Menu Project > Generate Javadoc …

Menu Generate Javadoc

Puis dans l’interface suivante, on indique sur quel projet (ou quels projets) on souhaite générer la Javadoc et le dossier de génération de cette documentation.

Projet et dossier de la génération de la documentation

La génération de la documentation va fabriquer différents fichiers HTML dans le dossier doc visible dans Eclipse. On doit donc indiquer si on souhaite réécrire dans le dossier en remplaçant l’ancien contenu.

Mises à jour par remplacement des dossiers

La fabrication du contenu est visible dans Eclipse dans le dossier doc indiqué dans les étapes précédentes. Il suffit ensuite d’ouvrir le fichier index.html via le menu « Open With » > « Web Browser » pour afficher la documentation finale.

Le rendu final de la documentation est alors affiché dans une forme standardisé réalisant les liens entre les différentes pages de la documentation.

Page finale de la documentation

La création de la documentation est simplifiée et standardisée facilement. Chaque langage de programmation dispose de sa propre version de Javadoc.

Publié dans Développement, IMT Mines Alès | Laisser un commentaire

Utilisation de Jenkins avec un simple projet Java en local

L’objectif est de tester l’outil d’intégration Jenkins de manière très simple. Du coup, j’ai choisi de ne pas utiliser d’outils de gestion de code sources de type git, svn ou autre, mais juste de lancer un simple test en automatique.

Une autre contrainte a été d’utiliser Jenkins dans un conteneur Docker qui est démarré simplement via cette commande :

docker run --name=jenkins -p 8080:8080 -p 50000:50000 --restart=on-failure jenkins/jenkins:lts-jdk11

Le conteneur Jenkins est accessible via le navigateur sur l’URL http://127.0.0.1:8080/ avec les plugins recommandés.

Maintenant, on va fabriquer le code java basique qui ne fait que tester une fonction qui double un nombre passé en paramètre, voici le code :

public class Calcul {
	
	public static int doublement(int nombre) {
		return nombre * 2;
	}

}

Et le test avec Junit 5

class CalculTest {

	@Test
	void testDoublement() {		
		assertEquals(Calcul.doublement(0) , 0);
		assertEquals(Calcul.doublement(1) , 2);
	}

}

Le test est vraiment basic juste pour vérifier le fonctionnement. Maintenant pour tester en ligne de commande en pur Java (qui est aussi utiliser avec Jenkins d’ailleurs ), on peut utiliser cette outil de Junit en ligne de commande.

Télécharger le fichier junit-platform-console-standalone-1.8.2.jar de Console Launcher : https://junit.org/junit5/docs/snapshot/user-guide/#running-tests-console-launcher qui permet d’appeler l’outil de test Junit5 via une ligne de commande.

En local on peut donc lancer cette commande, par exemple dans le workspace:

java -jar c:\DEV20\eclipse-workspace-jee\JenkinsDemo\junit-platform-console-standalone-1.8.2.jar -cp c:\DEV20\eclipse-workspace-jee\JenkinsDemo\bin --scan-classpath  --disable-banner

Voici la sortie détaillée :

.
+-- JUnit Jupiter [OK]
| '-- CalculTest [OK]
|   '-- testDoublement() [OK]
'-- JUnit Vintage [OK]

Test run finished after 44 ms
[         3 containers found      ]
[         0 containers skipped    ]
[         3 containers started    ]
[         0 containers aborted    ]
[         3 containers successful ]
[         0 containers failed     ]
[         1 tests found           ]
[         0 tests skipped         ]
[         1 tests started         ]
[         0 tests aborted         ]
[         1 tests successful      ]
[         0 tests failed          ]

Ou la version avec erreur d’un test :

.
+-- JUnit Jupiter [OK]
| '-- CalculTest [OK]
|   '-- testDoublement() [X] expected: <2> but was: <1>
'-- JUnit Vintage [OK]

Failures (1):
  JUnit Jupiter:CalculTest:testDoublement()
    MethodSource [className = 'test.CalculTest', methodName = 'testDoublement', methodParameterTypes = '']
    => org.opentest4j.AssertionFailedError: expected: <2> but was: <1>
       org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55)
       org.junit.jupiter.api.AssertionUtils.failNotEqual(AssertionUtils.java:62)
       org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:150)
       org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:145)
       org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:527)
       test.CalculTest.testDoublement(CalculTest.java:14)
       java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
       java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
       java.base/java.lang.reflect.Method.invoke(Method.java:568)
       [...]

Test run finished after 47 ms
[         3 containers found      ]
[         0 containers skipped    ]
[         3 containers started    ]
[         0 containers aborted    ]
[         3 containers successful ]
[         0 containers failed     ]
[         1 tests found           ]
[         0 tests skipped         ]
[         1 tests started         ]
[         0 tests aborted         ]
[         0 tests successful      ]
[         1 tests failed          ]

Pour disposer seulement de cette réponse en cas d’erreur, il faut ajouter le paramètre « –details=none » qui n’affichera qu’en cas d’erreur.

À présent, on peut copier tout le dossier du projet dans le conteneur Jenkins, car il n’a pas accès au dossier c:\DEV20\eclipse-workspace-jee\JenkinsDemo\ mais on aurait pu monter dans le conteneur Jenkins le dossier.

docker cp C:\DEV20\eclipse-workspace-jee\JenkinsDemo jenkins:/home

Donc l’ensemble des fichiers du projet et l’outil junit-platform-console-standalone-1.8.2.jar de Console Launcher se trouve dans le dossier /home/JenkinsDemo. On peut donc ensuite tester dans le conteneur comme ceci.

docker exec --user=root --workdir=/home/JenkinsDemo/ -it  jenkins  /bin/bash

On peut donc ensuite tester notre test dans le conteneur :

java -jar /home/JenkinsDemo/junit-platform-console-standalone-1.8.2.jar -cp /home/JenkinsDemo/bin/  --scan-classpath  --disable-banner --deta
ils=none

Passons maintenant dans Jenkins pour créer un job, « Construire un projet free-style » puis il faut utiliser le bouton « Avancé » pour avoir accès au dossier :

Puis, il faut indiquer le dossier de travail :

Maintenant, on va ajouter notre script comme critère de Build :

La commande testée précédemment doit être entrée pour valider le projet:

java -jar /home/JenkinsDemo/junit-platform-console-standalone-1.8.2.jar -cp /home/JenkinsDemo/bin/  --scan-classpath  --disable-banner --details=none

On peut ensuite sauvegarder les modifications et lancer ce job via « Lancer ce build » et on peut vérifier l’exécution dans le résultat de la console :

Cela permet de vérifier que les opérations s’exécutent correctement. A l’inverse voici une sortie de console en erreur après un échec du test :

Pour conclure et simplifié, on aurait pu monter le dossier du projet Eclipse directement dans le /home du conteneur avec cette commande :

docker run -it -v C:\DEV20\eclipse-workspace-jee\JenkinsDemo\:/home/JenkinsDemo/ --name=jenkins -p 8080:8080 -p 50000:50000 --restart=on-failure jenkins/jenkins:lts-jdk11

Le reste serait identique et grâce à Java portable entre Windows et Linux du conteneur, les commandes avec JUnit sont compatibles.

Publié dans Développement, IMT Mines Alès | Laisser un commentaire

Ajout d’un dossier de contenu statique à Tomcat 9

Cas pratique, un programme Tomcat doit produire un fichier de données à télécharger, par exemple un fichier backup.csv.

Produire ce dossier dans le dossier WebContent ou webapp n’est pas possible, car à chaque redémarrage d’une nouvelle version de notre application, le contenu d’un de ces dossiers serait régénéré.

La solution vient d’un dossier de contenu dit statique (static en VO), en modifiant le fichier server.xml de notre serveur Tomcat. On identifie le projet qui doit disposer d’un dossier statique (dans l’exemple, c’est le tag <Context> du projet DevWeb) et on peut y ajouter les instructions pour indiquer à Tomcat qu’un URL peut accéder à ce dossier.

Il faut changer le tag <Context/> en tag double <Context></Context> et y ajouter ces informations de ressources. (Les doubles slashs sont à adapter au type de système d’exploitation).

<Context docBase="DevWeb" path="/DevWeb" reloadable="true" 			source="org.eclipse.jst.jee.server:DevWeb">
  <Resources>
    <PreResources
base="C://Users//pierre.jean//Site-Web//data" 							className="org.apache.catalina.webresources.DirResourceSet"		 webAppMount="/static" />
  </Resources>
</Context>

L’URL pour accéder à la ressource est relative à l’URL du <Context> englobant, notre url est donc http://127.0.0.1:8080/DevWeb/static/backup.csv

Pour lister le contenu du dossier, la première solution est de modifier le fonctionnement général de Tomcat en modifiant le fichier web.xml. Il faut changer la valeur de la servlet par défaut gérant la liste des dossiers en passant à la valeur true la propriété listings comme indiqué ci-dessous.

    <servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

La seconde option est de créer dans le dossier WebContent/WEB-INF/ un fichier tomcat-web.xml (ou web.xml mais Tomcat ne le conseille pas pour éviter de déployer ce fichier spécifique dans un serveur autre que Tomcat).

Le contenu du fichier tomcat-web.xml est donc le suivant pour surcharger les réglages par défaut du fichier web.xml généraliste au niveau du serveur Tomcat:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
	<servlet>
		<servlet-name>default</servlet-name>
		<servlet-class>
			org.apache.catalina.servlets.DefaultServlet
		</servlet-class>
		<init-param>
			<param-name>debug</param-name>
			<param-value>0</param-value>
		</init-param>
		<init-param>
			<param-name>listings</param-name>
			<param-value>true</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>default</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</web-app>

Après, il n’est pas forcément recommandé en production de donner des accès à un dossier tout entier, mais dans le contexte du projet de recherche, Tomcat est prévu dans un container en local de la machine.

On peut aussi modifier le rendu par défaut de la liste des contenus d’un dossier dans TOmcat mais je vous renvoie sur la documentation, ce n’est pas un besoin que j’ai eu.

Publié dans Développement | Laisser un commentaire

Émission d’un email en Java via un hébergement OVH

Envoyer un email technique depuis un code Java via un compte configuré chez OVH est assez simple si on a trouvé la bonne combinaison de paramètres…

Voici la liste des réglages pour un compte que l’on va appeler publication@euromov.eu et dont le mot de passe a été généré par la console OVH. Attention, l’envoie d’un trop grand nombre d’emails entrainera le blocage de votre compte par OVH. L’entreprise surveille ce genre de fonctionnalité car régulièrement les sites web et autres serveurs de l’entreprise servent à des pirates pour envoyer des emails en masse souvent à l’insu du propriétaire du compte chez OVH.

Le réglage mail.debug est à mettre à true au besoin pour voir les messages d’échange entre le serveur et votre code Java:

Properties prop = new Properties();
prop.put("mail.debug", "false");
prop.put("mail.smtp.auth", "true");		
prop.put("mail.smtp.ssl.protocols", "TLSv1.2");
prop.put("mail.smtp.host", "ssl0.ovh.net");
prop.put("mail.smtp.starttls.enable", "true"); 
prop.put("mail.smtp.ssl.trust", "ssl0.ovh.net");
prop.put("mail.smtp.port", "587");
prop.put("mail.smtp.socketFactory.port", "587");
prop.put("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory");	Session session = Session.getInstance(prop, new Authenticator() {
  @Override
   protected PasswordAuthentication getPasswordAuthentication() {
	return new PasswordAuthentication("publication@euromov.eu", "MOT_DE_PASSE_A_GENERER_DANS_CONSOLE_OVH");}
   });
		
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("publication@euromov.eu"));
message.setRecipients(
Message.RecipientType.TO, InternetAddress.parse("directeurs@toto.com"));
message.setSubject("Mail Subject");
String msg = "This is my first email using JavaMailer";

MimeBodyPart mimeBodyPart = new MimeBodyPart();
mimeBodyPart.setContent(msg, "text/html; charset=utf-8");

Multipart multipart = new MimeMultipart();
multipart.addBodyPart(mimeBodyPart);
message.setContent(multipart);
Transport.send(message);

Pour rappel 2 JARS sont nécessaires pour ce code :

Bon email, mais encore une fois attention aux spams.

Publié dans Développement | Laisser un commentaire

Langage R liaison base de données

Installation de WAMP : https://www.wampserver.com/ ou MAMP : https://www.mamp.info/en/downloads/

Supposons un accès à un fichier « sante.accdb » contenant une table data de cette nature :

id date_analyse      glycemie
1   2022-03-17       10
2   2022-03-18       20

On peut interroger en langage R en SQL vers Microsoft Accces.

En premier lieu il faut installer le module pour R pour accéder à Accces:

install.packages("RODBC")
library(RODBC)

Une fois l’installation réalisée de ce module, on peut ouvrir le fichier Accès et intérroger en SQL la base de données:

con <- odbcConnectExcel2007("C:/Users/utilisateur/Documents/sante.accdb")
resultat <- sqlQuery(con,"select date_analyse from data")
print( resultat )

On peut faire de manière similaire sur MySQL avec des commandes similaires, en premier lieu en installant le module pour la liaison avec le serveur de base de données MySQL :

install.packages("RMySQL")
library(RMySQL)

L’accès à un serveur de base de données Mysql suppose plusieurs informations techniques, l’adresse du serveur de base de données (ici 127.0.0.1), un compte sur cette base de données (ici root), un mot de passe correspondant à ce compte (ici «  » pour indiquer mot de passe vide), un port de base de données (ici et par défaut 3306) et enfin une base de données (ici sante)

DB <- dbConnect(MySQL(), user="root", host="127.0.0.1", password="",dbname="sante" , port=3306)

Une fois la connexion réalisée, on peut lister les tables dans cette base de données sante.

dbListTables(DB)

Et enfin poser des questions en SQL

resultat <- dbGetQuery(DB, "SELECT * FROM data")
print( resultat )

Test unitaire en R

Installation de l’outil de test

install.packages("testthat")
library(testthat)

Test d’une valeur égale via :

expect_equal( 95 , dbGetQuery(DB, "SELECT max(age) from import")[,1] )

Pas de réponse si tout va bien, mais si on test ceci :

expect_equal( 92 , dbGetQuery(DB, "SELECT max(age) from import")[,1] )
Error: 92 not equal to dbGetQuery(DB, "SELECT max(age) from import")[, 1].
1/1 mismatches
[1] 92 - 95 == -3

Publié dans Développement | Laisser un commentaire

Génération d’un PDF depuis une JSP avec iText5 et iText7

NOTA : la version utilisée dans cette première version est la iText5 une prochaine version utilisera la nouvelle version iText7

En premier lieu il faut récupérer les bibliothèques jar suivantes:

  • itextpdf-5.5.13.3.jar
  • log4j-1.2.16.jar
  • slf4j-api-1.7.9.jar
  • slf4j-log4j12-1.7.13.jar

Placer ces fichiers dans le dossier WebContent/WEB-INF/lib de votre application Dynamic Web Application , les sélectionner et faire click droit > Build Path > Add to Build Path

Vous pouvez maintenant coder une simple JSP pour générer un ficheir PDF. Attention, si vous cette erreur « getOutputStream() has already been called for this response » il faut retirer tout espace ou retour chariot qui pourrait être interprétés par la JSP comme du HTML à envoyer donc tout se trouve sur une seule ligne pour les tag JSP de type <%@page import %>:

<%@ page language="java" contentType="application/pdf; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%><%@page import="com.itextpdf.text.Document" %><%@page import="com.itextpdf.text.PageSize" %><%@page import="com.itextpdf.text.Paragraph" %><%@page import="com.itextpdf.text.pdf.PdfWriter" %><%
Document document = new Document(PageSize.A4, 36, 36, 36, 72);

PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline; filename=\"todo.pdf\"");

document.open();
document.add( new Paragraph ("Hello world"));
document.add( new Paragraph ("Bonjour le monde"));
document.close();
writer.close();
%>

Version iText7

Pour la version iText7, après avoir ajouté les bilbiothèques suivantes en remplacement de celles de iText5:

  • barcodes-7.2.1.jar
  • commons-7.2.1.jar
  • font-asian-7.2.1.jar
  • forms-7.2.1.jar
  • hyph-7.2.1.jar
  • io-7.2.1.jar
  • kernel-7.2.1.jar
  • layout-7.2.1.jar
  • log4j-1.2.16.jar
  • pdfa-7.2.1.jar
  • pdftest-7.2.1.jar
  • sign-7.2.1.jar
  • slf4j-api-1.7.9.jar
  • slf4j-log4j12-1.7.13.jar
  • styled-xml-parser-7.2.1.jar
  • svg-7.2.1.jar

Du coup le code pour la JSP est similaire avec l’utilisation d’un ByteArrayOutputStream pour gérer le PDF en mémoire.

<%@ page language="java" contentType="application/pdf; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%><%@ page import="com.itextpdf.io.source.ByteArrayOutputStream" %><%@ page import="com.itextpdf.kernel.pdf.PdfDocument" %><%@ page import="com.itextpdf.kernel.pdf.PdfWriter" %><%@ page import="com.itextpdf.layout.Document" %><%@ page import="com.itextpdf.layout.element.Paragraph" %><%
ByteArrayOutputStream memory = new ByteArrayOutputStream();
Document document = new Document(new PdfDocument(new PdfWriter(memory)));
document.add( new Paragraph ("Hello world"));
document.close();
ServletOutputStream servletOutputStream = response.getOutputStream();
servletOutputStream.write(memory.toByteArray());
servletOutputStream.flush();
servletOutputStream.close();
%>
Publié dans Développement | Laisser un commentaire

Alternative tcpdump windows 10 avec pktmon

L’outil pktmon.exe disponible par défaut dans Windows 10 Pro permet de faire un peu de dump de paquet TCP.

Bien sûr, la solution de npcap/winpcap/wireshark est beaucoup plus performant, mais avec quelques commandes on peut extraire l’information utile. Je me concentre surtout sur la partie HTTP qui me permet de vérifier les échanges de données même si la limitation de pktmon à ne pas pouvoir fonctionner sur la boucle locale 127.0.0.1 est clairement une limitation pour moi.

Démarrons par ajouter un filtre sur le protocole TCP sur le port 80

 C:\Windows\system32\pktmon.exe filter add -t TCP  -p 80

On peut lister ces filtres avec la commande suivante

 C:\Windows\system32\pktmon.exe filter list

Filtres de paquet :
     # Nom    Protocole Port
     - ---    --------- ----
     1 <vide> TCP         80

Et pour démarrer la capture, on voit le rappel de la liste des paquets

 C:\Windows\system32\pktmon.exe  start --etw  --pkt-size 0

Filtres de paquet :
     # Nom    Protocole Port
     - ---    --------- ----
     1 <vide> TCP         80

Un fichier PktMon.etl va donc être fabriqué contenant les opérations que l’on fait avec son navigateur vers un port 80 d’un serveur web par exemple.

Mais je vous propose cette version du filtrage pour se concentrer sur la partie Web des requêtes :

C:\Windows\system32\pktmon.exe filter add Port80 -t TCP PSH -p 80 -m 00-AA-BB-CC-DD-EE

On ajoute un nom Port80 et on va récupérer que les paquets marqués TCP de type PUSH (codé PSH) sur le port 80 en provenance de la Mac Address de ma carte réseau 00-AA-BB-CC-DD-EE à remplacer par votre valeur.

Il suffit maintenant d’arrêter la capture est de convertir le fichier PktMon.etl en format lisible à moins d’utiliser l’outil d’analyse de Microsoft Network Monitor.

Le fichier ftp.txt est assez clair pour être lu et vérifier les packets TCP

C:\Windows\system32\pktmon.exe  stop

C:\Windows\system32\pktmon.exe  format PktMon.etl -o file.txt

Exemple d’accès sur un site web en méthode GET en regardant le contenu du fichier file.txt :

00-AA-BB-CC-DD-EE > 00-11-12-13-14-15, ethertype IPv4 (0x0800), length 457: 192.168.1.1.49676 > 213.186.33.2.80: Flags [P.], seq 2764848503:2764848906, ack 3028623659, win 513, length 403: HTTP: GET /accueil/?s=test HTTP/1.1

On peut retirer le filtre au besoin pour revenir dans l’état initial

C:\Windows\system32\pktmon.exe  filter remove

On peut aussi exporter dans un format plus verbeux avec l’option de formatage etl2txt:

C:\Windows\system32\pktmon.exe  etl2txt .\PktMon.etl v 3 -m -o file.txt

Cela va produire les entête HTTP des contenus des requêtes HTTP par exemple avec le fichier JavaScript suivant :

	HTTP/1.1 200 OK
	date: Wed, 23 Feb 2022 15:11:35 GMT
	content-type: application/javascript
	content-length: 229
	server: Apache
	last-modified: Tue, 10 Dec 2019 18:53:39 GMT
	accept-ranges: bytes
	cache-control: max-age=900
	expires: Wed, 23 Feb 2022 15:26:35 GMT
	vary: Accept-Encoding
	x-iplb-request-id: C1339D28:28B3_D5BA2102:0050_62164EA7_6F6E:1CD33
	x-iplb-instance: 29005
	
	
	
	var $j = jQuery.noConflict();
	
	$j(document).ready(function() {
	    // Toggle Single Bibtex entry
	    $j('a.papercite_toggle').click(function() {
		$j( "#" + $j(this).attr("id") + "_block" ).toggle();
		return false;
	    });
	});

Ensuite on pourra utiliser les outils de développements des navigateurs pour une lecture plus simple, mais la liaison TPC/IP sur le contenu est clairement lisible avec cet outil fourni par défaut.

L’option suivante est soit de faire plus de réseau avec tcpdump ou wireshark qui sont dédiés aux couches réseaux soit de partir en développement web avec les outils embarqués dans les navigateurs Web.


La partie que je chercherai à ajouter prochainement, est la capture de la boucle locale via des outils tierce comme indiqué sur cette page : https://wiki.wireshark.org/CaptureSetup/Loopback

Je pense que cette option semble prometteuse même si je n’arrive pas encore à la faire fonctionner : https://web.archive.org/web/20150726062624/http://ig2600.blogspot.com/2011/03/powershell-script-to-enable-windows-to.html

Publié dans Développement | Laisser un commentaire

Ajout de l’authentification One-Time-Password à taiga.io

La nouvelle version de taiga.io avec docker inclus un installateur bien simplifié.

Il me parait utile d’y ajouter simplement l’authentification OTP qui permet d’accepter le mot de passe ajouté avec 6 chiffres calculé par l’horloge à partir d’un code. Vous trouverez des explications sur ce processus dans cet article: https://en.wikipedia.org/wiki/One-time_password

Le seul fichier à éditer pour inclure l’OTP dans taiga est le fichier /taiga-back/taiga/users/services.py dans le containeur taiga-docker_taiga-back_1.

En premier lieu, il faut ajouter au containeur taiga-docker_taiga-back_1 le module pyotp:

docker exec -it taiga-docker_taiga-back_1 pip install pyotp

Ensuite on peut copier sur la machine hôte le fichier services.py pour y ajouter l’OTP:

docker cp taiga-docker_taiga-back_1:/taiga-back/taiga/users/services.py  services.py 

Nous pouvons donc éditer le fichier services.py pour y adjoindre et modifier le programme, en premier lieu en important le module pyotp avant toutes les fonctions:

import pyotp

Puis on va chercher la fonction get_and_validate_user qui a cette forme:

def get_and_validate_user(*, username: str, password: str) -> bool:
    """
    Check if user with username/email exists and specified
    password matchs well with existing user password.

    if user is valid,  user is returned else, corresponding
    exception is raised.
    """

    user = get_user_by_username_or_email(username)


    if not user.check_password(password) or not user.is_active or user.is_system:
        raise exc.WrongArguments(_("Username or password does not matches user."))

    return user

Nous allons ajouter l’extraction des 6 derniers symboles du mot de passe pour trouver le code PIN à valider par OTP avec le code fourni en paramètre. Donc la nouvelle version de la fonction get_and_validate_user

def get_and_validate_user(*, username: str, password: str) -> bool:
    """
    Check if user with username/email exists and specified
    password matchs well with existing user password.

    if user is valid,  user is returned else, corresponding
    exception is raised.
    """

    user = get_user_by_username_or_email(username)

    """
    PJE   verification OTP
    """
    totp = pyotp.TOTP("base32secret3232")
    passwordPIN = password
    password = passwordPIN[:-6]
    pin = totp.verify( passwordPIN[-6:] , valid_window=2 )
    if pin is False:
        raise exc.WrongArguments(_("Username or password does not matches user PIN."))

    """
    / PJE   verification OTP
    """


    if not user.check_password(password) or not user.is_active or user.is_system:
        raise exc.WrongArguments(_("Username or password does not matches user."))

    return user

En incluant dans la fonction d’authentification, l’extraction des 6 derniers symboles fournis par l’utilisateur, on peut ajouter une authentification avec code OTP. On note une nouvelle exception envoyé par le serveur en cas d’erreur sur le code PIN.

NOTA: je pensais avoir un problème de Timezone dans le containeur mais au final, je pense que c’est valide comme installation. J’ai testé quelques solutions de changement dans le containeur de timezone mais finalement je pense que je peux aussi m’appuyer sur l’argument for_time de la fonction verify : https://pyauth.github.io/pyotp/_modules/pyotp/totp.html#TOTP.verify

Publié dans Développement | Laisser un commentaire