Coding Stories

Singe savant en ingénierie logicielle

Signer Les JARs Avec Maven

| Comments

Après avoir vu cette question sur stackoverflow j’ai pensé que présenter la façon dont je gère la signature de code avec maven pouvait en intéresser certains.

Utiliser deux keystores

Tout d’abord il s’agit de produire un keystore pour le développement ; soit un certificat auto-signée, soit un certificat émis par une PKI interne à votre organisation si d’aventure vous en disposez une. Appelons le `dev.keystore. Ce keystore va être enregistré dans le SCM et de cette façon le serveur d’intégration continue pourra signer les builds de développement.

Le deuxième keystore contiendra la clé de production, c’est-à-dire un certificat signé par une autorité de certification délivrant des certificats de signature de code. Comptez entre 100 et 300€/an. Appelons le `prod.keystore. Idéalement ce keystore sera conservé en sécurité et protégé par un mot de passe sûr, connu uniquement des personnes autorisées (par exemple le responsable des releases).

Pour les détails de la génération de la clé et l’obtention d’un certificat je vous laisse regarder la documentation de keytool.

Configurer maven

Le plugin maven-jarsigner-plugin comme son nom l’indique permet de signer des jar. Comme il est lié par défaut à la phase package de maven il sera appelé automatiquement une fois le jar généré. Configurons-le.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-jarsigner-plugin</artifactId>
        <version>1.2</version>
        <executions>
          <execution>
            <goals>
              <goal>sign</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <keystore>${keystore.path}</keystore>
          <storetype>${keystore.type}</storetype>
          <alias>${keystore.alias}</alias>
          <storepass>${keystore.store.password}</storepass>
          <keypass>${keystore.key.password}</keypass>
        </configuration>
      </plugin>
    <plugins>
  <build>
  ...
  <properties>
    <keystore.path>dev.keystore</keystore.path>
    <keystore.type>JKS</keystore.type>
    <keystore.alias>signingKey</keystore.alias>
    <keystore.password>changeit</keystore.password>
    <keystore.store.password>${keystore.password}</keystore.store.password>
    <keystore.key.password>${keystore.password}</keystore.key.password>
  </properties>

Ensuite dans le fichier ${HOME}/.m2/settings.xml on définit un profil codesigning :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<settings>
  <profiles>
    <profile>
      <id>codesigning</id>
      <properties>
        <keystore.path>~/private/prod.keystore</keystore.path>
        <keystore.alias>codesigning</keystore.alias>
        <keystore.type>JKS</keystore.type>
        <keystore.store.password>${keystore.password}</keystore.store.password>
        <keystore.key.password>${keystore.password}</keystore.key.password>
        <keystore.password>aVeryStringPassword</keystore.password>
      </properties>
    </profile>
  </profiles>
</settings>

Désormais pour signer avec la clé de production il suffit de lancer maven avec le bon profil.

1
mvn clean install -Pcodesigning

Si vous être parano, il est possible de ne pas mettre le mot de passe dans le fichier settings.xml. Dans ce cas on le passe à maven en paramètre.

1
mvn clean install -Pcodesigning -Dkeystore.password=aVeryStringPassword

Faire une release

La version stable du produit se doit d’être signée par la clé de production. Pour cela on passe le profil au plugin release :

1
mvn release:perform -Darguments="-Pcodesigning -Dkeystore.password=aVeryStringPassword"

Et comme je trouve cette syntaxe peu agréable à utiliser, j’ai configuré le plugin dans le pom.xml.

1
2
3
4
5
6
7
8
9
10
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-release-plugin</artifactId>
  <version>2.0</version>
  <configuration>
    <arguments>-Pcodesigning -Dkeystore.password=${keystore.password}</arguments>
    <goals>deploy</goals>
    <useReleaseProfile>false</useReleaseProfile>
  </configuration>
</plugin>

de cette façon on peut se contenter d’appeler cette commande :

1
mvn release:perform -Dkeystore.password=aVeryStringPassword

Comments