Bug 61450 - issue when certificateKeyAlias is not set
Summary: issue when certificateKeyAlias is not set
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 8
Classification: Unclassified
Component: Util (show other bugs)
Version: 8.5.20
Hardware: PC Linux
: P2 normal (vote)
Target Milestone: ----
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-08-22 17:03 UTC by Jesse
Modified: 2017-08-28 12:47 UTC (History)
1 user (show)



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jesse 2017-08-22 17:03:08 UTC
We use tomcat-embed and we have a test that is breaking with an upgrade from 8.5.12 to 8.5.20, it seems due to the fact that we do not set the certificateKeyAlias when we configure an SSLHostConfigCertificate.

The documentation for certificateKeyAlias states "If not specified, the first key read from the keystore will be used."  

It seems that the first alias is being used and there is no check that it references a key.

The result is that in JSSEUtil.getKeyManagers there is a call to KeyStore.getKey(keyAlias, keyPassArray) where keyAlias is actually an alias for a certificate, which leads to inMemoryKeyStore.setKeyEntry being passed null for the Key argument and eventually a KeyStoreException("Cannot store non-PrivateKeys").

This worked previously with certificatekeyAlias being null.  I can confirm that this works just fine if I set that with the alias used when creating the KeyStore but I would rather not pass that alias around our code when I did not previously need to.

We have worked around the issue with a "getFirstKeyAlias" method that we use to set the certificateKeyAlias in our SSLHostConfigCertificate:

   private String getFirstKeyAlias(KeyStore keyStore) {
      try {
         Enumeration<String> aliases = keyStore.aliases();
         while(aliases.hasMoreElements()) {
            String alias = aliases.nextElement();
            if (keyStore.isKeyEntry(alias))
               return alias;
            }
      } catch (KeyStoreException e) {
          LOGGER.error("Failed to find first key alias in keystore", e);
      }

      return null;
   }

I think that something like this should around line 219 of JSSEUtil, where currently it looks like this:

                Enumeration<String> aliases = ks.aliases();
                if (!aliases.hasMoreElements()) {
                    throw new IOException(sm.getString("jsse.noKeys"));
                }
                keyAlias = aliases.nextElement();
Comment 1 Jesse 2017-08-22 17:04:10 UTC
Created this bug per Mark Thomas on the tomcat users mailing list.

Thanks!
Comment 2 Remy Maucherat 2017-08-28 12:47:17 UTC
I get it, the switch was made from trying "tomcat" to using an actual alias from the keystore, but it still needs an additional update to be accurate.
Improved in 9M27 and 8.5.21.