Reputation: 375
I'm a bit of a beginner with this so I'm looking for more of an explanation rather than a quick fix.
I am trying to deploy a Spring Boot app over HTTPS (for fun/testing, will never make it into production). I first started by creating a Certificate Authority (root and intermediary) and then creating a certificate for my application (which will be accessed via localhost) and using the intermediate CA to sign this certificate. I used this tutorial to do this.
I then used this answer to import my newly created localhost certificate into a keystore and then deployed by application. When accessed through Chrome I was presented with two issues;
Subject Alternative Name missing. The certificate for this site does not contain a Subject Alternative Name extension containing a domain name or IP address.
Certificate error. There are issues with the site's certificate chain (net::ERR_CERT_AUTHORITY_INVALID).
Now if my understanding of the problems is correct, I would need to do the following;
The SAN is some sort of certificate extension which has succeeded the common name matching the domain name. I would need to inject this extension into my localhost certificate. My problem is that I am not sure where I have to do this. Is it upon creation of the certificate?
I'm not sure why this is happening. From one end I feel that this will always happen since my CA is one I created and not an established CA, but from what I see online this can be solved, but I don't understand how. I just injected my localhost certificate into the keystore. Would I need to inject the intermediate certificate too?
Also, I have a question regarding the tutorial above. What is the difference between server_cert and usr_cert (under the Sign server and client certificates section). The certificate is the server's certificate but it will handle user authentication. In that case I would need to use server_cert right?
Upvotes: 0
Views: 6427
Reputation: 375
Answering my own question since I appear to have figured it out.
So first up you need to create the root and intermediate CAs. As mentioned I followed this tutorial. It is very good but there are some things to highlight.
When creating the root openssl.cnf
make sure you set the directory to the location of your root/ca
folder. This was specified in the instructions but it is good to highlight it. Also change the defaults (line 81-86) so you will find them ready when you do your root CA.
When creating the root certificate chose a good Common Name
When creating your intermediate openssl.cnf
change the directory to root/ca/intermediate
and change the defaults defaults (line 81-86) to match those of your root openssl.cnf
.
Also as part of the openssl.cnf you need to add the subjectAltName as per this link. Under usr_cert
and server_cert
add subjectAltName = @alt_names
. This will add the required Subject Alternative Name when creating the certificate. I believe you only really need this for the server_cert
but I added it under both just to be safe (I didn't use user_cert
anyway). DNS.1
is correctly set to localhost.
When creating the intermediate cert your details should be the same as the ones for the root cert, hence why I said copy the org details in step 3. The common name MUST be different.
When creating the server cert your organisation details may very but be careful to set the common name to localhost
.
When you verify the signed server certificate check that the version is set to 3 (under data), the subject CN is set to localhost
, and the X509v3 Subject Alternative Name
is set to DNS:localhost
.
When you are done you need to create a trust store to provide to your Sring Boot application. I used parts of this resource. I created my cert-chain using the following command
cat ./intermediate/certs/localhost.cert.pem ./intermediate/certs/intermediate.cert.pem ./certs/ca.cert.pem > cert-chain.txt
Then I created my store using the following command
openssl pkcs12 -export -inkey ./intermediate/private/localhost.key.pem -in cert-chain.txt -out cert-chain.p12
I didn't bother converting it to JKS because pkcs12 is the new standard and Spring Boot works well with this format.
At this point I then used KeyStore Explorer to check whether my key store had the right hierarchy. It had one certificate (localhost) and when I looked at the certificate hierarchy I saw the root -> intermediate -> localhost.
Next thing I did was put the keystore under src/main/resources
and I added the following properties within my YAML properties file (a normal .properties file will also work)
server.port: 8443
server.ssl:
key-store: src/main/resources/cert-chain.p12
key-store-password: secretpassword
keyStoreType: PKCS12
If you are using Spring Security you might also need to use security.require-ssl: true
.
At this point you will we shown a ERR_CERT_AUTHORITY_INVALID
but you can proceed anyway. This is because your Root/Intermediate CA is not trusted by your browser. If you view your certificate through the browser you should once again see the root -> intermediate -> localhost hierarchy. Import your intermediate certificate into the browser and restart your browser. You should now see a green secure padlock. Success! You are now secure!
NOTE: Sometimes I saw an Active content with certificate errors
error. In this case delete the site storage as explained here.
Upvotes: 2