Archive

Posts Tagged ‘JAR’
  • What archive format should you use, WAR or JAR?

    Female hitting a male with boxing gloves on

    :page-liquid: :icons: font :experimental:

    Some time ago, RAM and disk space were scarce resources. At that time, the widespread strategy was to host different applications onto the same platform. That was the golden age of the application server. I wrote in an link:{% post_url 2014-10-26-on-resources-scarcity-application-servers-and-micro-services %}[earlier post^] that the current tendency toward cheaper resources will make it obsolete, in the short or long term. However, a technology trend might bring it back in favor.

    Having an application server is good when infrastructure resources are expensive, and sharing them across apps brings a significant cost decrease. On the down side, it requires a deep insight into the load of each application sharing the same resources, as well as skilled sysadmins that can deploy on the same app server applications that are compatible. For old-timers, does an application requiring to be run alone because it mismanages resources ring a bell? When infrastructure costs decrease, laziness and aversion to risk take precedence over them, and hosting a single app on an application server become the norm. At that point, the next logical step is to consider why application servers as dedicated components are still required. It seems the Spring guys came to the same conclusion, for Spring Boot applications’ default mode is to package executable JARs - also known as Fat JARs. Those apps can be run as java -jar fat.jar. Hence the famous:

    [quote, Josh Long] __ Make JAR, not WAR __

    I’m still not completely sold on that, as I believe it too easily discards the expertise of most Ops teams regarding application servers’ management. However, one compelling argument about Fat JARs is that since the booting technology is in charge of app management from the start, it can handle load classes in any way it wants. For example, with https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html[Dev Tools^], Spring Boot provides a mechanism based on two classloaders, one for libraries and one for classes, so that classes can be changed and reloaded without restarting the whole JVM - a neat trick that gives a very fast feedback loop at each code change.

    It wrongly thought that application server providers were still stuck with the legacy way - thanks to https://twitter.com/ivar_grimstad[Ivar Grimstad^] for making me aware of this option (a good reason to visit talks that do not necessarily target your interest at conferences). http://wildfly-swarm.io/[Wildlfy^], https://tomee.apache.org/advanced/shading/index.html[TomEE^] and other app server implementers can be configured to package Fat JARs as well, albeit with one huge difference: there’s nothing like Spring Dev Tools, so the restart of the whole app server is still required when code changes. The only alternative for faster feedback regarding those changes is to work at a lower level e.g. JRebel licenses for the whole team. However, there’s still one reason to use WAR archives, and that reason is Docker. By providing a common app server Docker image as a base image, one just needs to add one’s WAR on top of it, thus making the WAR image quite lightweight. And this cannot be achieved (yet?) with the JAR approach.

    Note that it’s not Spring Boot vs JavaEE but mostly JAR vs WAR, as Spring Boot is perfectly able to package either format, while many app server providers as well. As I pointed out above, the only missing piece is for the later to reload classes instead of restarting the whole JVM when a change occurs - but I believe it will happen at some point.

    Choosing between the WAR and the JAR approaches is highly dependent whether the company values more fast feedback cycles during development or more optimized and manageable Docker images.

    Categories: Java Tags: WARJARJavaEESpring Bootarchive
  • Signing and verifying a standalone JAR

    Seal

    :revdate: 2017-02-05 16:00:00 +0100 :page-liquid: :icons: font :experimental:

    link:{% post_url 2017-02-05-proposal-java-policy-files-crafting-process %}[Last week^], I wrote about the JVM policy file that explicitly lists allowed sensitive API calls when running the JVM in sandboxed mode. This week, I’d like to improve the security by signing the JAR.

    == The nominal way


    This way doesn’t work. Readers more interested in the solution than the process should skip it. **

    === Create a keystore

    The initial step is to create a keystore if none is already available. There are plenty of online tutorials showing how to do that.

    [source,bash]

    keytool -genkey -keyalg RSA -alias selfsigned -keystore /path/to/keystore.jks -storepass password -validity 360 —-

    Fill in information accordingly.

    === Sign the application JAR

    Signing the application JAR must be part of the build process. With Maven, the https://maven.apache.org/plugins/maven-jarsigner-plugin/[JAR signer plugin^] is dedicated to that. Its usage is quite straightforward:

    [source,xml]

    maven-jarsigner-plugin 1.4 sign sign /path/to/keystore.jks selfsigned ${store.password} ${key.password}

    To create the JAR, invoke the usual command-line and pass both passwords as system properties:

    [source,bash]

    mvn package -Dstore.password=password -Dkey.password=password —-

    Alternatively, Maven’s https://maven.apache.org/guides/mini/guide-encryption.html[encryption capabilities^] can be used to store passwords in a dedicated settings-security.xml to further improve security.

    === Configure the policy file

    Once the JAR is signed, the policy file can be updated to make use of it. This requires only the following configuration steps:

    1. Point to the keystore
    2. Configure the allowed alias

    [source]

    keystore “keystore.jks”;

    grant signedBy “selfsigned” codeBase “file:target/spring-petclinic-1.4.2.jar” { … } —-

    Notice the signedBy keyword followed by the alias name - the same one as in the keystore above.

    === Launching the JAR with the policy file

    The same launch command can be used without any change:

    [source,bash]

    java -Djava.security.manager -Djava.security.policy=jvm.policy -jar target/spring-petclinic-1.4.2.jar —-

    Unfortunately, it doesn’t work though this particular permission had already been configured!

    [source]

    Caused by: java.security.AccessControlException: access denied (“java.lang.reflect.ReflectPermission” “suppressAccessChecks”) at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472) at java.security.AccessController.checkPermission(AccessController.java:884) at java.lang.SecurityManager.checkPermission(SecurityManager.java:549) at java.lang.reflect.AccessibleObject.setAccessible(AccessibleObject.java:128) at org.springframework.util.ReflectionUtils.makeAccessible(ReflectionUtils.java:475) at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:141) at org.springframework.boot.SpringApplication.createSpringFactoriesInstances(SpringApplication.java:420) —-

    The strangest part is that permissions requested before this one work all right. The reason is to be found in the particular structure of the JAR created by the Spring Boot plugin: JAR dependencies are packaged untouched in a BOOT-INF/lib folder in the executable JAR. Then Spring Boot code uses custom class-loading magic to load required classes from there.

    JAR signing works by creating a specific hash for each class, and by writing them into the JAR manifest file. During the verification phase, the hash of a class is computed and compared to the hash of the manifest. Hence, permissions related to classes located in the BOOT-INF/classes folder work as expected.

    However, the org.springframework.boot.SpringApplication class mentioned in the stack trace above is part of the spring-boot.jar located under BOOT-INF/lib: verification fails as there’s no hash available for the class in the manifest.

    Thus, usage of the Spring Boot plugin for JAR creation/launch is not compatible with JAR signing.

    == The workaround

    Aside from Spring Boot, there’s a legacy way to create standalone JARs: the https://maven.apache.org/plugins/maven-shade-plugin/[Maven Shade plugin^]. This will extract every class of every dependency in the final JAR. This is possible with Spring Boot apps, but it requires some slight changes to the POM:

    1. In the POM, remove the Spring Boot Maven plugin
    2. Configure the main class in the Maven JAR plugin: + [source,xml] —-
    maven-jar-plugin 3.0.2 org.springframework.samples.petclinic.PetClinicApplication
    1. Finally, add the Maven Shade plugin to work its magic: + [source,xml] —-
    maven-shade-plugin 2.4.3 true package shade

    WARNING: The command-line to launch the JAR doesn’t change but permissions depend on the executed code, coupled to the JAR structure. Hence, the policy file should be slightly modified.

    == Lessons learned

    While it requires to be a little creative, it’s entirely possible to sign Spring Boot JARs by using the same techniques as for any other JARs.

    To go further:

    • https://maven.apache.org/plugins/maven-jarsigner-plugin/[Jarsigner Plugin^]
    • https://maven.apache.org/plugins/maven-shade-plugin/[Shade Plugin^]
    • http://docs.spring.io/spring-boot/docs/current/maven-plugin/[Spring Boot plugin^]
    • http://docs.spring.io/spring-boot/docs/current/reference/html/executable-jar.html[Spring Boot executable JAR format^]
    Categories: Java Tags: JVMsecurityJARSpring Bootpolicy