Java and Certmonger

Earlier this week, I got some advice from John Dennis on how to set up the certificates for a Java based web application. The certificates were to be issued by the Dogtag instance in a Red Hat Identity Mangement (RH IdM) install. However, unlike the previous examples I’ve seen, this one did some transforms from the certificate files, into PKCS12 and then finally into the keystore. It Looks like this:

ipa-getcert request -f /etc/pki/tls/certs/rhsso-cert.pem -k /etc/pki/tls/private/rhsso-key.pem -I rhsso -K RHSSO/`hostname` -D `hostname`
 
openssl pkcs12 -export -name rhsso -passout pass:FreeIPA4All -in /etc/pki/tls/certs/rhsso-cert.pem -inkey /etc/pki/tls/private/rhsso-key.pem -out rhsso.p12
 
keytool -importkeystore -srckeystore rhsso.p12 -srcstoretype PKCS12 -srcstorepass FreeIPA4All -destkeystore keycloak.jks -deststorepass FreeIPA4All -alias rhsso
 
keytool -keystore keycloak.jks -import -file /etc/ipa/ca.crt -alias ipa-ca
 
cp keycloak.jks /etc/opt/rh/rh-sso7/keycloak/standalone/

Aside from the complications of this process, it also means that the application will not be updated when Certmonger automatically renews the certificate, leading to potential down time. I wonder if there is a better option.

Keystore Formats

The latest couple releases of Java have supported a wider array of Keystore formats.

from /usr/lib/jvm/java-1.8.0-openjdk-$VERSION.b14.fc27.x86_64/jre/lib/security/java.security

#
# Default keystore type.
#
keystore.type=jks
 
#
# Controls compatibility mode for the JKS keystore type.
#
# When set to 'true', the JKS keystore type supports loading
# keystore files in either JKS or PKCS12 format. When set to 'false'
# it supports loading only JKS keystore files.
#
keystore.type.compat=true

So it appears that one step above is unnecssary: we could use a PKCS-12 file instead of the Native Java KeyStore. However, Certmonger does not mange PKCS-12 files either, so that is not a complete solution.

PKCS-11

But what about PKCS-11?

One thing that is tricky is that you are rarely going to find much about creating PKCS-11 files: instead, you find wasy to work with them via various tools. Why is that? PKCS-11 is not a file format per set, it is a standard.

The PKCS#11 standard specifies an application programming interface (API), called “Cryptoki,” for devices that hold cryptographic information and perform cryptographic functions. Cryptoki follows a simple object based approach, addressing the goals of technology independence (any kind of device) and resource sharing (multiple applications accessing multiple devices), presenting to applications a common, logical view of the device called a “cryptographic token”.

From the standard.

In other words, PKCS-11 is an API for talking to various forms of storage for cryptographic information, specifically asymmetric keys.

Asymmetric keys is that they come in pairs. One is public, the other is kept private. The PKCS-11 API helps enforce that. Instead of extracting a Private Key from a database in order to encrypt or decrypt data the data is moved into the container and signed internally. The private key never leaves the container.

That is why we have two standards: PKCS-11 and PKCS-12. PKCS-12 Is the standard the way you safely extract a key and transport it to another location.

Ideally, the PKCS-11 token is a hardware device. For example, a Yubikey device. Many computers come with Hardware Security Modules (HSMs) built in for just this purpose.

The Mozilla project developed cryptography to with with these standards. It used to be called Netscape Security Services, but since has been retconned to be Network Security Services. Both, you notice, are the acronym NSS. To be clear, this is separate from the Name Server Switch API, which is also called NSS. I seem to recall having written this all before.

The Firefox Browser, and related programs like Thunderbird, can fetch and store cryptographic certificates and keys in a managed database. This is usually called an NSS database, and it is accessed via PKCS-11, specifically so they have a singe API to use if the site want to do something more locked down, like use an HSM.

OK, so this is a long way of saying that, maybe it is possible to use an NSS database as the Java Keystore.

NSS Database

First, lets create a scratch NSS Database:

[root@sso ~]# cd /etc/opt/rh/rh-sso7/keycloak/standalone/
[root@sso standalone]# mkdir keystore
[root@sso standalone]# certutil -d dbm:$PWD/keystore -N
Enter a password which will be used to encrypt your keys.
The password should be at least 8 characters long,
and should contain at least one non-alphabetic character.
 
Enter new password: 
Re-enter password:

Now lets request a cert. Because this NSS database is in a custom location, SELinx is going to block Certmonger from talking to it. For now, I’ll set the machine in permissive mode to let the request go in.

[root@sso standalone]# setenforce permissive
root@sso standalone]# ipa-getcert  request  -w -d dbm:$PWD/keystore -D $HOSTNAME -K RHSSO/$HOSTNAME -n RHSSO
New signing request "20180215041951" added.
[root@sso standalone]# getcert list
Number of certificates and requests being tracked: 1.
Request ID '20180215041951':
	status: MONITORING
	stuck: no
	key pair storage: type=NSSDB,location='dbm:/etc/opt/rh/rh-sso7/keycloak/standalone/keystore',nickname='RHSSO',token='NSS Certificate DB'
	certificate: type=NSSDB,location='dbm:/etc/opt/rh/rh-sso7/keycloak/standalone/keystore',nickname='RHSSO',token='NSS Certificate DB'
	CA: IPA
	issuer: CN=Certificate Authority,O=AYOUNG.RDUSALAB
	subject: CN=sso.ayoung.rdusalab,O=AYOUNG.RDUSALAB
	expires: 2020-02-16 04:19:46 UTC
	dns: sso.ayoung.rdusalab
	principal name: RHSSO/sso.ayoung.rdusalab@AYOUNG.RDUSALAB
	key usage: digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment
	eku: id-kp-serverAuth,id-kp-clientAuth
	pre-save command: 
	post-save command: 
	track: yes
	auto-renew: yes

SELinux reworking will come at the end.

OK, we should be able to list the certs in the database:

[root@sso standalone]# certutil -L -d dbm:$PWD/keystore 
 
Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI
 
RHSSO                                                        ,,   
[root@sso standalone]#

Lets try it in Java. First, I need the Compiler

sudo yum install java-1.8.0-openjdk-devel

Now… the Java libraries it turns out are not default allowed to deal with NSS. We need a configuration file and we can create the provider dynamically. For NSS we need: security.provider.10=sun.security.pkcs11.SunPKCS11. The following code seems to succeed:

import java.security.KeyStore;
import java.security.Provider;
import java.security.Security;
 
import sun.security.pkcs11.SunPKCS11;
 
public class ReadNSS{
 
    public static char[] password = new char[0];
 
    public static void main(String[] args) throws Exception{
        String configName = "/etc/opt/rh/rh-sso7/keycloak/standalone/pkcs11.cfg";
        Provider p = new sun.security.pkcs11.SunPKCS11(configName);
        Security.addProvider(p);
        KeyStore ks = KeyStore.getInstance("PKCS11", p); //p is the provider created above
        ks.load(null, password);
        for (Enumeration<String> aliases = ks.aliases(); aliases.hasMoreElements();){
             System.out.println(aliases.nextElement());
        }
    }
}

With the corresponding config file:

name = NSScrypto
nssModule = keystore
nssDbMode = readOnly
nssLibraryDirectory = /lib64/
nssSecmodDirectory = /etc/opt/rh/rh-sso7/keycloak/standalone/keystore

Compile and run

[root@sso standalone]# javac ReadNSS.java 
[root@sso standalone]# java ReadNSS
RHSSO

We can list the keys. Ideally, I would pass that provider information on the command line, though.

Conclusion

It does look like there is a way to create a database that Java can use as a KeyStore. The question, now, is whether TOmcat and JBoss based web apps can use this mechanism to manage their HTTPS certificates.

SE Linux

What should the SELinux rule be:

 
type=AVC msg=audit(1518668385.358:6514): avc:  denied  { unlink } for  pid=15316 comm="certmonger" name="key4.db-journal" dev="vda1" ino=17484326 scontext=system_u:system_r:certmonger_t:s0 tcontext=system_u:object_r:etc_t:s0 tclass=file
	Was caused by:
		Missing type enforcement (TE) allow rule.
 
		You can use audit2allow to generate a loadable module to allow this access.

But that Generates

#============= certmonger_t ==============
 
#!!!! WARNING: 'etc_t' is a base type.
allow certmonger_t etc_t:file { create setattr unlink write };

Which, if I read it right, allows Certmonger to unlink and write and etc file. We want something more targeted.

How to deal with this is in the next post.

3 thoughts on “Java and Certmonger

  1. Ah excellent. I think I was about 2/3rds through the steps of reproducing that. I don’t need or want full FIPS compliance, just to get a format for the Keystore that Cermonger can support. I think there might be a few additions to those commands to use the sql backend instead of dbm, as SQL is now the default.

    Thanks for the link. Course, it only helps those of us that can get behind the Red Hat portal authentication.

  2. jar} +# Space-separated list of extra javac options +javac. compilerargs= +javac. deprecation=false +javac. processorpath= + ${javac. classpath} +javac.

Leave a Reply

Your email address will not be published. Required fields are marked *