Philipps Blog


2011/11/20  Jenkins/Hudson Password Hash Format

Filed under:Java,Security — Philipp @ 4:37 pm

Nice to know:

The Build-In Security Realm of Jenkins/Hudson is based on acegisecurity. The Hash is Sha256 based. For a Salt

foo

and a password

bar

, you have to Hash

bar{foo}

, that’s then

77ce9123f864f6749a2b2c99b988089c21d33e39247f7b1276dfad01a112f038

(via hashgenerator.de)

You find the Hashes in <Jenkins-Dir>/users/<username>/config.xml

it is then storred as

 

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user>
    <fullName>user</fullName>
    <properties>
        <jenkins.security.ApiTokenProperty>
            <apiToken>…</apiToken>
        </jenkins.security.ApiTokenProperty>
        <hudson.model.MyViewsProperty>
            <views>
                <hudson.model.AllView>
                    <owner reference="../../.."/>
                    <name>Alle</name>
                    <filterExecutors>false</filterExecutors>
                    <filterQueue>false</filterQueue>
                    <properties/>
                </hudson.model.AllView>
            </views>
        </hudson.model.MyViewsProperty>
        <hudson.security.HudsonPrivateSecurityRealm_-Details>
            <passwordHash>foo:77ce9123f864f6749a2b2c99b988089c21d33e39247f7b1276dfad01a112f038</passwordHash>
        </hudson.security.HudsonPrivateSecurityRealm_-Details>
        <hudson.tasks.Mailer_-UserProperty>
            <emailAddress>mail@example.com</emailAddress>
        </hudson.tasks.Mailer_-UserProperty>
    </properties>
</user>

 

2011/11/09  maven is not ant

Filed under:Build,Java,Tooling — Philipp @ 11:00 pm

Neben vielen berechtigten Kritikpunkten die manch einer dem Build-Tool Maven vorwerfen kann, ist oftmals der falsche Einsatz einer der Hauptgründe für die schlechte Perfomance (d.h. lange Build-Zeiten) die fehlerhafte Nutzung von Maven Features.

Oft sieht man, dass Module untereinander durch relative Pfadangaben verknüpft sind. Dies mag bei Ant-Builds ein gängiges Mittel sein, aber wenn man sich vor Augen hält, dass jeder Modul eines Projektes für sich genommen ausgecheckt und gebaut werden können soll, so ist klar, dass man eine abstractere Art und Weise benötigt, einzelne Module miteinander zu verbinden.

Und auch hierfür eignet sich das Mitte der Dependencies. Zu einem vollständigen (und nützlichem) Maven-Build-System gehört zwangsläufig auch ein (eigenes) funktionierendes Maven-Repository (sei es nun Archiva oder Nexus). So ein Repository dient nicht nur zum Lagern von Artefakten, sondern auch als Dreh- und Angelpunkt der einzelnen Module untereinander.

Nehmen wir an, ein Projekt besitzt folgende Struktur:

Root
  |-Modul A
  |-Modul B
    |-Modul C

Nehmen wir weiterhin an, dass Modul A von C abhängt, weil C zum Beispiel XSD Scripte enthält, die separat von einem Fachler aktualisiert werden, aber für die Generierung von Java-Klassen in A benötigt werden.

Würde es nach Ant-Manier gehen, so wäre folgendes denkbar:

<project>
...
    <build>
        <plugins>
            ...
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>xmlbeans-maven-plugin</artifactId>
                <version>2.3.3</version>
                <executions>
                    <execution>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>xmlbeans</goal>
                        </goals>
                    </execution>
                </executions>
                <inherited>true</inherited>
                <configuration>
                    ...
                    <schemaDirectory>../B/C/xsd</schemaDirectory>
                    <classGenerationDirectory>${project.build.directory}/classes</classGenerationDirectory>
                </configuration>
            </plugin>
            ...
        </plugins>
    </build>
...
</project>

Dies dürfte aber spätestens beim Release Build scheitern, weil hier jedes Modul für das Releas separat innerhalb des eigenen Target-Dirs ausgecheckt wird (spätestens hier kommt es dann mit den relativen Pfaden nicht mehr hin).

Was also tun?
Abhilfe schaft das maven-dependency-plugin, welches dem aktuellen Modul erlaub direkt auf die Daten eines einzelnen Artefacts zugreifen zu können. Damit das Artefact durch das Plugin verarbeitet werden kann, sollte es (logischerweise) auch als Dependency im eingetragen sein. So ist sogar sicher gestellt, dass immer der aktuellste Codestand verwendet wird, denn sollt ein Artefact im Repository neuere sein als das, welches lokal vorgehalten wird, so wird dieses heran gezogen.

Die obige Konfiguration würde sich also wie folgt ändern:

<project>
...
    <dependencies>
        ...
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>C</artifactId>
            <version>${project.version}</version>
        </dependency>
        ...
    </dependencies>
    <build>
        <plugins>
            ...
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.3</version>
                <executions>
                    <execution>
                        <id>src-dependencies</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <!-- use copy-dependencies instead if you don't want to explode the
                                sources -->
                            <goal>unpack</goal>
                        </goals>
                        <configuration>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>com.example</groupId>
                                    <artifactId>C</artifactId>
                                    <version>${project.version}</version>
                                    <classifier>resources</classifier>
                                    <type>zip</type>
                                    <includes>**/*.xsd</includes>
                                    <overWrite>true</overWrite>
                                    <outputDirectory>${project.build.directory}/C</outputDirectory>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>            
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>xmlbeans-maven-plugin</artifactId>
                <version>2.3.3</version>
                <executions>
                    <execution>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>xmlbeans</goal>
                        </goals>
                    </execution>
                </executions>
                <inherited>true</inherited>
                <configuration>
                    ...
                    <schemaDirectory>${project.build.directory}/C/xsd</schemaDirectory>
                    <classGenerationDirectory>${project.build.directory}/classes</classGenerationDirectory>
                </configuration>
            </plugin>
            ...
        </plugins>
    </build>
...
</project>

Zu beachten ist hier, dass die Reihenfolge der beiden Plugins wichtig ist, weil ansonsten die Code-Generierung nicht auf die entpackten Dateien der Dependency zugreifen kann. Ich gebe zu, es handelt sich hier um ein einfaches Beispiel, aber zumindest der Drang, sich durch relative Pfade innerhalb von Maven-Files zu helfen ist meiner Beobachtung nach recht weit verbreitet :-/.

2011/11/06  Upload von Third-Party Artefakten in ein Maven Repository per SCP

Filed under:Java — Philipp @ 6:50 pm

Manchmal gibt es den Fall, dass es notwendig ist, eine externe Bibliothek in einem Maven Projekt einzubinden. Um nun im Build Zyklus des Maven-Projektes keinen Bruch zu erhalten bietet es sich an, dass Artefakt manuell als Maven Artefakt im Repository zur Verfügung zu stellen.

Wir benutzen bei consolving.de u.a. ein öffentliches Maven Repository ( maven.javastream.de ) in dem wir einige OSS Artefakte den Entwicklern unter unseren Kunden zur Verfügung stellen. Hierbei handelt es sich nicht um ein vollständiges Repository System wie Archiva oder Nexus, sondern um ein lokales Repositry, welche statisch per Web-Server zur Verfügung stellt wird. Das ganze wird befüllt durch einen Jenkins-CI Server, der im Hintergrund alle Projekte periodisch neu dorthin deployed.

Es sind vier Schritte notwendig damit ein Deployment über SCP möglich ist:

  1. Das Verzeichnis des Repositories muss per scp erreichbar sein – hierzu bietet es sich an, den SSH-Key auf dem Server zu hinterlegen.
  2. Einrichten der notwendigen Credentials unter der ~/.m2/settings.xml
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <settings>
         <servers>
             <server>
                 <id>maven.javastream.de</id>
                 <username>##user##</username>
                 <privateKey>##user##</privateKey>
             </server>
         </servers>
     </settings>
  3. Vorbereiten des Third-Parts Projektes
    Ein vollständiges Maven-Artefakt besteht aus drei Teilen: 1. das Binary, 2. die Sourcen und 3. die JavaDoc Dateien. Alle drei Teile sollten als JAR gepackt werden.
    Nachfolgend ein Script, welches die drei notwendigen Teile in Archive packt:

    #!/bin/bash
    
    # Direkt aus dem Directory zu packen scheint die einzige Möglichkeit zu sein, dass die einzelnen Dateien direkt im Root des JARs liegen.
    cd src
    jar -c . > ../src.jar
    cd ..
    
    cd doc
    jar -c . > ../doc.jar
    cd .
    
    cd lib
    jar -c . > ../lib.jar
    cd .
  4. Zuletzt werden nun die drei JARs per Maven-Command in das Repository geladen:
    #!/bin/bash
    
    #Binary
    mvn deploy:deploy-file -DgroupId=de.javastream \
      -DartifactId=example \
      -Dversion=1.0 \
      -Dpackaging=jar \
      -Dfile=lib.jar \
      -DrepositoryId=maven.javastream.de \
      -Durl=scp://maven.javastream.de/home/javastream.de/maven
    
    # Javadoc
    mvn deploy:deploy-file -DgroupId=de.javastream \
      -DartifactId=example \
      -Dversion=1.0 \
      -Dclassifier=javadoc \
      -Dpackaging=jar \
      -Dfile=doc.jar \
      -DrepositoryId=maven.javastream.de \
      -Durl=scp://maven.javastream.de/home/javastream.de/maven
    
    # Sourcen
    mvn deploy:deploy-file -DgroupId=de.javastream \
      -DartifactId=example \
      -Dversion=1.0 \
      -Dclassifier=sources \
      -Dpackaging=jar \
      -Dfile=src.jar \
      -DrepositoryId=maven.javastream.de \
      -Durl=scp://maven.javastream.de/home/javastream.de/maven