5

On Aug 14th, the gtecybertrust5ca certifcate used by Glassfish expired causing my Arquillian tests to print errors.

This problem is similar to this one: Certificate has expired” in log by starting Glassfish 3.1.2 except, I am using the Embedded version of Glassfish via Maven, Arquillian and SureFire to run unit and integration tests.

I have tried instructing Maven to use a local keystore, the one that comes with the JRE, in an effort to keep the expired cert from being used. I verified the expired certificate is not contained within this keystore:

C:\Java\jdk1.7.0_25\jre\lib\security>keytool -list -keystore cacerts

I instruct SureFire via Maven to start the JVM with arguments to use the cacerts trusted keystore:

         <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.16</version>
          <configuration>                
              <argLine>
                -Djavax.net.ssl.trustStore=C:\Java\jdk1.7.0_25\jre\lib\security\cacerts
                -Djavax.net.ssl.trustStorePassword=changeit
              </argLine>
              ....
          </configuration>
      </plugin>

      <!-- Configure the Embedded GlassFish Maven plugin -->
      <plugin>
          <groupId>org.glassfish.embedded</groupId>
          <artifactId>maven-embedded-glassfish-plugin</artifactId>
          <version>4.0</version>
          <configuration>
              <app>${project.build.directory}/${project.build.finalName}.war</app>
              <port>7070</port>
              <containerType>web</containerType>
          </configuration>
      </plugin>

I also added JVM arguments where Maven is start within Maven's mvn.bat file:

@REM Use specified java cert trust
set MAVEN_OPTS=%MAVEN_OPTS% 
 -Djavax.net.ssl.trustStore=%JAVA_HOME%\jre\lib\security\cacerts 
 -Djavax.net.ssl.trustStorePassword=changeit

%MAVEN_JAVA_EXE% %MAVEN_OPTS% ...

Here's the Surefire invocation of the JVM used to run the unit tests:

Forking command line: cmd.exe /X /C "C:\Java\jdk1.7.0_25\jre\bin\java 
-Djavax.net.ssl.trustStore=C:\Java\jdk1.7.0_25\jre\lib\security\cacerts 
-Djavax.net.ssl.trustStorePassword=changeit ..."
Running com.networkfleet.ssp.activation.SelectedActivationTableBeanTest

The command line args do seem to match the expected system properties Glassfish expects per its com.sun.enterprise.security.ssl.impl.SecuritySupportImpl and com.sun.enterprise.server.pluggable.SecuritySupport classes:

@Contract
public abstract class SecuritySupport {

public static final String KEYSTORE_PASS_PROP = "javax.net.ssl.keyStorePassword";
public static final String TRUSTSTORE_PASS_PROP = "javax.net.ssl.trustStorePassword";
public static final String KEYSTORE_TYPE_PROP = "javax.net.ssl.keyStoreType";
public static final String TRUSTSTORE_TYPE_PROP = "javax.net.ssl.trustStoreType";
public static final String keyStoreProp = "javax.net.ssl.keyStore";
public static final String trustStoreProp = "javax.net.ssl.trustStore";

However, they do not appear to be picked up by Glassfish, because the expired cert is still being found in whatever trusted keystore it defaults to.

I would really appreciate some help. Thanks.

Community
  • 1
  • 1
Heather92065
  • 7,333
  • 6
  • 31
  • 39
  • did you set the Djavax.net.ssl.trustStore jvm option for your glassfish maven plugin? – happymeal Aug 19 '13 at 09:13
  • Yes, I did. I added it in two places. The first to the mvn.bat that start the Maven jvm and the second within the pom.xml where the unit tests are forked: -Djavax.net.ssl.trustStore=C:\Java\jdk1.7.0_25\jre\lib\security\cacerts.jks -Djavax.net.ssl.trustStorePassword=changeit – Heather92065 Aug 19 '13 at 16:21
  • Are you using netbeans? Could be you edited the mvn.bat from an external maven but you are still using the netbeans internal maven. – happymeal Aug 20 '13 at 00:22
  • I'm using the command line. It seems Glassfish isn't picking up the trustStore settings. I'll edit the question with the debug showing the invocation of the jvm by Surefire within the Maven test. – Heather92065 Aug 20 '13 at 14:44
  • @Heather92115 could you include the Arquillian test class that tests the https URL? – Ted Dec 17 '14 at 19:06
  • I haven't included such a test. Sorry. – Heather92065 Dec 17 '14 at 19:38

3 Answers3

8

I finally got to the bottom of the issue by tracing the Glassfish code that loads the certs. The embedded, at least, version ignores any passed in parameters and looks to its classpath to find the trusted key store to load. It then writes it to a temp location and instructs the server to load and use it.

To get rid of the error messages, grab the cacerts.jks file from its temp location (after running Maven and seeing the expired exception) I found it at: C:\Users\{myUserName}\AppData\Local\Temp\gfembed872323756359721458tmp\config\cacerts.jks.

Copy this file to your project under resources/config/cacerts.jks (it will need to be loaded into your test classpath).

From the command prompt in the directory where you copied the keystore, use your JDK keytool to remove the expired key as follows:

keytool -delete -keystore cacerts.jks -alias gtecybertrust5ca

The Embedded Glassfish should now pick up your updated keystore instead of its default hardcoded version.

Rolando Isidoro
  • 4,983
  • 2
  • 31
  • 43
Heather92065
  • 7,333
  • 6
  • 31
  • 39
  • 5
    Password is changeit when removing – Orbita Aug 30 '13 at 08:22
  • Removing the outdated certificate from standalone GF works well. As soon as I put cacerts,jks to `test/resources/config` I am getting `SEVERE: Startup service failed to start : com.sun.enterprise.security.admin.cli.SecureAdminStartupCheck` and the domain refuses to start. Any solution for this? I am using embedded GF 3.1.2.2. – botchniaque Nov 26 '14 at 12:50
  • You're going to have to put the cacerts.jks file in your src directory (src/main/resources/config), not the test. When you build your final war or ear file be sure to exclude this file. – Heather92065 Nov 26 '14 at 17:24
1

I fixed the issue following the steps:

  1. Find precise date of expiration in logs of your application (in my case it was Aug 15 2013)

  2. Extract files from glassfish-.jar into folder glassfish-

  3. In glassfish-* find a folder config. It contains needed cacerts.jks

  4. Using java keytool I list all certificates using the answer I found here

list all certificates from cacerts.jks, the keytool from java can do that. I copied the cacerts.jks file in the keytool folder but is optional if keytool is working well : C:\glassfish3\jdk7\bin>keytool -list -v -keystore cacerts.jks -storepass changeit > listaCertificados.txt

  1. Open you listaCertificados.txt and find names of certificates by date you found at first step in your application logs
  2. again

i deleted the gtecybertrust5ca (use the name of certificates that expired in ur case) certified that expired in august 2013. The command is: keytool -delete -alias gtecybertrust5ca -keystore cacerts.jks -storepass changeit

  1. the last: updating glassfish-*.jar with changed config folder (7-zip didn't help me)

jar uf glassfish-* config

Community
  • 1
  • 1
Yauhen
  • 2,435
  • 1
  • 17
  • 18
0

You can now get the certs as part of the OpenJDK package - see https://dzone.com/articles/openjdk-10-now-includes-root-ca-certificates

For a Docker install you can do something like this:

# Set glassfish env
ENV GLASSFISH_HOME /opt/glassfish5/glassfish

# Get latest cacerts from OpenJDK project
RUN wget https://hg.openjdk.java.net/jdk/jdk/raw-file/tip/src/java.base/share/lib/security/cacerts && \
    mv cacerts $GLASSFISH_HOME/domains/domain1/config/cacerts.jks
aaronvargas
  • 12,189
  • 3
  • 52
  • 52