Using Self Signed Certificates in Java Applications

Oct. 27, 2022

Authentication and authorization in backend application is a very common phenomenon. We are using Cloudfoundry uaa to handle authentication and authorization. Now as part of our migration we had to create an internal uaa instance for dev use. Now we need to use the uaa server with our spring applications along with other uaa servers. This should be easy!

First one is easy we can use and Application load balancer in public subnet and route the requests to our UAA instance. AWS does have Account certificate manager which issues we can register a domain and get a certificate which we can use in load balancer. However this requires a domain name to generate a working public ssl cert. This is not a acceptable approach for us for internal policy reasons. So the only approach remaining is to use a self signed certificate. ACM allows to import self signed certificates but it needs to meet following requirements. While generating ssl certificate please be careful to generate a X.509 V3 certificate and not a X.509 V1 certificate with v3 extensions. This has wasted lot of my time. I have used openssl to generate ssl certificate. However macos uses libressl instead of standard openssl which generates v1 certificates. You can generate ssl certificate with following command and enter necessary details as below

user@host directory % openssl req -newkey rsa:2048 -keyout domain.key -x509 -days 365 -out domain.crt
Enter pass phrase for domain.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:IN
State or Province Name (full name) []:TE
Locality Name (eg, city) []:CITY
Organization Name (eg, company) []:Example
Organizational Unit Name (eg, section) []:Digital
Common Name (eg, fully qualified host name) []:example.com
Email Address []:[email protected]

Please make sure to remove the password from key before uploading to aws acm

user@host directory %  openssl rsa -in domain.key -out domain_nopas.key 
Enter pass phrase for domain.key:
writing RSA key
user@host directory % ls
domain.crt		domain.key		domain_nopas.key

you can check the generated version using following

ubuntu@ubuntu-arm-light:~/rootCA/tmp$ openssl x509 -text -noout -in domain.crt 
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            1e:f2:63:e3:a5:e3:a3:ea:98:ac:51:64:e7:b9:58:9a:41:98:af:d4
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = example.com, emailAddress = [email protected]
        Validity
            Not Before: Oct 30 20:00:54 2022 GMT
            Not After : Oct 30 20:00:54 2023 GMT
        Subject: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = example.com, emailAddress = [email protected]
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:d6:02:ce:32:16:14:6d:b3:b6:2c:11:52:ba:6c:
                    0a:b4:7b:78:f9:9e:c2:21:86:c8:fa:f8:76:27:9d:
                    1f:ae:74:7b:75:8d:4f:28:f5:db:96:9c:b2:13:f2:
                    fc:fa:c7:94:c1:71:2f:b8:a1:99:d2:25:1d:65:4c:
                    ab:17:15:e0:06:3e:b1:f9:bf:f6:6f:0d:1a:be:24:
                    6e:90:c7:25:dd:61:43:7d:7b:30:f1:38:c7:b9:32:
                    68:cc:53:4d:f8:b1:32:1b:ba:be:75:a5:21:50:f5:
                    54:77:a7:92:2b:3a:f3:24:1c:3f:d6:00:97:14:9e:
                    d7:c5:a8:8d:1a:5e:41:a8:e0:a1:06:6b:7f:47:fe:
                    cf:d5:8a:8d:32:3e:bf:e6:8e:27:02:ef:be:fb:be:
                    a7:01:ab:a7:f7🆎d5:41:a0:08:e4:bc:61:64:1b:
                    5b:c5:ec:31:10:c3:fa:92:f6:7a:26:4e:e7:35:f5:
                    73:32:8d:53:da:ff:ae:f9:0c:f8:ee:d7:44:f2:f1:
                    60:df:77:70:61:8e:fe:27:d7:0b:bc:34:c5:a4:99:
                    41:be:d9🇩🇪8a:c8:57:84:e3:7a:ae:a8:f8:7c:d0:
                    ed:d2:a9:73:d1:99:b0:2e:56:33:00:6c:c0:53:8d:
                    23:f0:33:12:11:29:15:16:3e:59:0e:aa:27:15:98:
                    3e:4b
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                D1:9E:C9:D9:A7:A5:0C:92:E6:0C:34:80:A0:FD:E9:E9:CD:6D:31:6C
            X509v3 Authority Key Identifier: 
                keyid:D1:9E:C9:D9:A7:A5:0C:92:E6:0C:34:80:A0:FD:E9:E9:CD:6D:31:6C

            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: sha256WithRSAEncryption
         37:d5:df:4a:ee:d4:1b:df:90:fb:78:9f:c8:3d:b8:4b:3f:d1:
         3d:0b:9c:ad:80:1f:26:20:c4:0e:cd:cb:22:32:46:39:e1:bf:
         bc:7b:65:22:b5:72:80:78:78:6a:3d:d6:1a:da:7c:c2:02:03:
         65:cb:0d:c9:01:cf:1c:ae:0a:a5:ca:5b:36:21:ea:c4:80:bc:
         01:fc:ef:b0:43:81:57:bc:7c:29:f6:17:87:3a:46:c3:2c:7d:
         f8:43:ab:d2:26:17:d4:8a:81:d4:77:cb:99:d0:e4:77:62:5e:
         22:32:7f:e8:d1:08:2c:c4:0d:2e:f3:9f:24:cf:ab:88:11:f3:
         97:d6:32:1e:46:b6:c7:1c:ce:a9:83:99:bc:c4:15:d9:32:19:
         92:eb:74:25:db:0c:38:b5:15:51:8c:d5:21:2b:c9:c4:e9:79:
         d4:2d:d1:fb:53:82:fb:aa:32:2f:b8:2e:64:2b:9e:dd:df:87:
         50:95:ea:ec:7c:b4:92:29:40:63:6f:f0:2a:fe:f8:94:11:67:
         60:18:28:c9:c0:ee:c8:f0:6f:c2:bb:56:47:72:fc:9c:6c:36:
         04:0f:39:a4:68:b6:22:f3:07:ef:d0:ec:c8:4b:80:22:c2:af:
         9f:6f:ea:67:28:b2:85:53:2f:7a:92:76:8b:a1:59:75:c9:19:
         84:a9:8c:d2

Now we have to package the certificate with the application. We are using docker containers to deploy applications so we can package the cert during docker build process.

FROM docker.io/amazoncorretto:17
COPY build/libs/application-${mdcVersion}.jar /app/application.jar
COPY src/main/resources/certs/dev-uaa/domain.cer /certs/dev-uaa.cer
RUN keytool -import -alias SelfCert -file /certs/dev-uaa.cer -keystore /usr/lib/jvm/java-17-amazon-corretto/lib/security/cacerts -storepass changeit -noprompt
CMD ["java", "-jar", "/app/application.jar"]

This will ensure that the certificate is injected during build process and the application will recognize our self signed certificate.