Can Maven re-sign dependencies? - java

I'm using maven-jarsigner-plugin to sign a shaded uber-jar of mine. I do need to distribute some dependencies in their own jars though, and want to take those jars from a Maven repo, clear them of any existing signatures, and sign them with my own certificate.
Are there any Maven plugins that do this, or would i involve some Ant plugin hackery?

Turns out maven-jarsigner-plugin can re-sign existing jars using it's removeExistingSignatures config element. So simple!
I use maven-dependency-plugin to copy artifacts into a .war project in the generate-resources phase, then sign them in the process-resources phase.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>copy</id>
<phase>generate-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.lwjgl.lwjgl</groupId>
<artifactId>lwjgl-platform</artifactId>
<version>2.9.0</version>
<classifier>natives-osx</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>src/main/webapp/</outputDirectory>
<destFileName>lwjgl-platform-natives-osx.jar</destFileName>
</artifactItem>
</artifactItems>
<outputDirectory>src/main/webapp</outputDirectory>
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jarsigner-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<id>sign</id>
<phase>process-resources</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
<configuration>
<keystore>${basedir}/path/to/my.keystore</keystore>
<alias>alias</alias>
<storepass>password</storepass>
<keypass>password</keypass>
<verbose>true</verbose>
<archiveDirectory>src/main/webapp/</archiveDirectory>
<processMainArtifact>false</processMainArtifact>
<removeExistingSignatures>true</removeExistingSignatures>
</configuration>
</plugin>

I know it is not a really good answer, but I would try a solution in these steps:
copy dependencies by maven-dependency-plugin
antrun: <unzip> them, strip everything from /META-INF directory except MANIFEST.MF, <jar> again and sign them again by using <jarsign> ant task.
The main problem I have found since I work with maven (quite recently I admit) is that it makes you go through its predefined pipeline, and this kind of things (which is more common than it seems) will make you need some ant hackery as you call it ;)

Never used it, but it seems the webstart-maven-plugin can unsign and sign jars.
http://mojo.codehaus.org/webstart/webstart-maven-plugin/unsign-mojo.html
Hope this help.

Using maven:
Create an empty maven jar module per jar that you want to resign, do a maven dependency:unpack of one of the jars, filtering the signature files and copying the files to src/main/java.
Then sign the jar with maven-jarsigned-plugin, the result will be a jar containing the same classes.
An alternative non-maven based:
The above way does not scale well, it would probably be simpler to create a script that follows these steps.
The simplest way to do it would be:
Instead of resigning the jars, consider registering the public key of the signer in your maven repository, meaning you trust the person that created these jars and accept any jars coming from them.
The truth is you already trust them since you are using their code and resigning it, so it would be simpler to configure the repository to accept their signature, in the same way that the repository was already configured by someone to accept your signature.
The repository is linked to a key store containing the public keys of the accepted jar signers, it would be a matter of asking the team that handles the repository to add one more key to their list of trusted signers, they would know how to do that for sure.

Related

How to skip the importCertificate goal if certificate is already exist by using keytool-maven-plugin?

I'm using keytool-maven-plugin to import alias.cer file into java cacerts store, it works fine. The problem occurs when building the project second time; getting an error because alias.cer file is already added to store. I couldn't see any parameter to fix the problem in plugin. There are 'skip' and 'skipIfExist' parameters. These parameters are not for this purpose; skip disables the plugin, skipIfExist skips if the store already exist.
How could I solve the problem? or do you know alternative plugin for this goal?
I realized that this plugin developed over the java keytool. There isn't any parameter in keytool for the 'skip if certificate is already exist' purpose. Therefore, I've used 'skip' parameter to handle this problem by adding a custom parameter to use while building the project.
<properties>
<cert.skip>true</cert.skip>
</properties>
<plugin>
<!-- https://mvnrepository.com/artifact/org.codehaus.mojo/keytool-maven-plugin -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>keytool-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<goals>
<goal>importCertificate</goal>
</goals>
<phase>generate-sources</phase>
</execution>
</executions>
<configuration>
<skip>${cert.skip}</skip>
<keystore>${JAVA_HOME}/lib/security/cacerts</keystore>
<storepass>changeit</storepass>
<alias>alias</alias>
<file>${basedir}/src/main/resources/alias.cer</file>
<noprompt>true</noprompt>
</configuration>
</plugin>
Usage: mvn clean install -Dcert.skip=false

Maven: Replace token in source file before compilation

I want to replace a token #NAME# in a source file (in my case *.java) before compilation.
I try to use google replacer plugin but I am open for anything which will help me.
1.pom.xml
The pom file look like this
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>src/main/java/com/test/sample/File.java</include>
</includes>
<replacements>
<replacement>
<token>#NAME#</token>
<value>New content</value>
</replacement>
</replacements>
</configuration>
</plugin>
But after I run mvn package the output is:
--- replacer:1.5.3:replace (default) # MyProject --- [INFO] Replacement run on 0 file.
Because there is no error I do not know what I have done wrong.
Maybe:
Defined phase is wrong
Defined include is wrong
...
Greetings!
I think there are two options.
If you keep using the plugin I think you need to add the ${basedir} to the include statement:
<include>${basedir}/src/main/java/com/test/sample/File.java</include>
If you dont want to modify the file in src/main but filter the file and add that one to the build you can use the standard resource filtering and the buildhelper plugin to add those "generated sources" to the build.
So step one would be using resource filtering to copy the file: http://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html
And then use the http://www.mojohaus.org/build-helper-maven-plugin/ to add those sources to the build.
Some IDEs (IntelliJ) will recognize /target/genereated-sources automatically if you keep using that folder (its not standard but very common). If you search for "maven" and "generated-sources" you will find quite some tutorials.
Hope this helps :)
While this is something you usually should not do in the first place, sometimes you have no choice (in my case it was "converting" an old project to Maven with changing as little of the code as possible). The above somehow did not work (while I could replace a placeholder in the source file and add the generated-sources folder to be compiled, it complained about duplicate source files).
Then I found an easier way by using the templating-maven-plugin as described here http://www.mojohaus.org/templating-maven-plugin/examples/source-filtering.html:
Put the file with the placeholder in the folder /src/main/java-templates. Excerpt from my source code:
public static final String APPLICATION_VERSION = "r${project.version}";
Add the following to your pom's plugins section:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>templating-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<id>filter-src</id>
<goals>
<goal>filter-sources</goal>
</goals>
</execution>
</executions>
</plugin>

Packaging war file with maven

I thought that, if my project is named my-web-application, than when I call mvn clean install maven first compiles to target\my-web-application-1.0 folder and than "zips" that folder to my-web-application-1.0.war...
But as I found recently it's not how it (maybe just with default settings) works.
I'm using some 3rd party components and I'd like to modify some styles (.css) and behavior (.js) for those components, so I simply replace content in dependency jar with my modification using
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<plugin>
execution example follows (it zips org folder to componentToModify.jar)
<execution>
<id>fix</id>
<phase>package</phase>
<configuration>
<executable>jar</executable>
<workingDirectory>${basedir}</workingDirectory>
<arguments>
<argument>-uvf</argument>
<argument>target/${project.artifactId}-${project.version}/WEB-INF/lib/componentToModify.jar</argument>
<argument>org</argument>
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
what correctly modifies the componentToModify.jar in the target\my-web-application-1.0, but final war doesn't contain the modifications. It seems that libs are zipped to war from local repository.
Is there some reason for such behavior and can I change it somehow?
Not completely sure but would using an Overlay help here?
http://maven.apache.org/plugins/maven-war-plugin/overlays.html
If all else fails, you may just want to modify the 3rd party application and produce your own jar with your changes.

maven properties-maven-plugin doesn't work when deploying artifact to Nexus

I am using properties-maven-plugin to read a external property file under root dir to maintain the version of parent module since there are quite a number of sub-modules in my project and the dependency tree is kinda deep.
It works fine when I build locally and install the artifacts into local repo but got the 401 error when I try to use "mvn clean deploy" to publish them to Nexus. I am pretty sure this is caused by the ineligible artifact name(releaseurl/{external.version}), external.version is supposed to be the property read from the external file. However, it ended up not being read and it just worked fine when I explicitly declare the version in the project.parent.version tag. Any thoughts or workaround? or even how you handle the version control when trying to use same version for parent and child in all the modules when dealing with a multi-module porject.
The maven pom for the plugin is as below, I saw some comments online regarding the phase, not sure if it will work if change initialize to something else:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>external-file.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>

In Maven2, is there a way to scope a dependency to "package only" and keep it off the test classpath?

Setup
I'm packaging a WAR with a number of legacy jar dependencies in it (for the sake of keeping this simple, they can not possibly be altered or excluded from the deployed WAR).
Issue
Including either or both of two of these jars will cause inexorable errors at test-time. If I exclude the dependencies altogether, the tests pass happily, but the WAR will lack real-world runtime classes it needs.
Hope
Maven2 offers compile, test, runtime, system, and provided scopes. Sadly, none of these will be included in the assembly but kept off the test classpath. My hope is that I'm missing some obvious way to handle this case entirely within the dependency management feature.
Fear
I'll have to use the assembly plugin to copy these problem jars into the target. I don't want to have to skirt the dependency management system to copy jars in the clear into the target, as I don't want to manage these jars outside the internal repository.
Thoughts? Alternatives?
Of course it figures that I'd come across a potential solution to this moments after posting a question. It appears that the copy goal of the dependency plugin may handle this. Going to try this out now: http://maven.apache.org/plugins/maven-dependency-plugin/usage.html
Edit: Turns out that this worked fine for my needs, snippet below:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>copy</goal>
</goals>
</execution>
</executions>
<configuration>
<artifactItems>
<artifactItem>
<groupId>group</groupId>
<artifactId>artifact</artifactId>
<version>version</version>
<type>jar</type>
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/lib</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</plugin>
Break the test classes out of the jar file into a separate jar which is only for tests, and add an exclusion to the dependency on the jar with the legacy dependencies.

Categories

Resources