Craig T.'s picture

Found a good post on replacing SSL certs on the forum here: https://www.turnkeylinux.org/forum/support/thu-20200618-1542/replacing-n...

 

However, I had a question about when those are created. I actually need to create a PFX file using the PEM and CER files located at /etc/ssl/private. Can I do this at build time or do I need to do it with an inithook?

 

Thanks!

Forum: 
Craig T.'s picture

Looks like they are created during build, so in my conf.d/main file, I am able to use them. For anyone that needs to create a PFX from these (using for ASPNET Kestrel in a container), here is the command (using a blank password for the PFX file):

 

openssl pkcs12 -export -out /your/director/https.pfx -inkey /etc/ssl/private/cert.key -in /etc/ssl/private/cert.pem -password pass:

Jeremy Davis's picture

Hey Craig! :)

You are somewhat right, those certs are created at appliance build time. However, unique certs are regenerated on firstboot. It's part of the inithooks package and on a built server, the specific script is /usr/lib/inithooks/firstboot.d/15regen-sslcert.

There are a few ways that you could tweak that to also build the https.pfx file that you need.


The quickest (and dirtiest IMO) way would be to simply put a tweaked 15regen-sslcert file in your app build code overlay (i.e. overlay/usr/lib/inithooks/firstboot.d/15regen-sslcert). However, as that's a packaged file, that's a really bad idea IMO as that file would be overwritten by a intihooks package update.

A somewhat similar, but not quite so dirty way of doing it would be to add a new firstboot script (again to your overlay). Perhaps call it '16regen-pfx-file'? The files are run in alphanumeric order, so if the first part of the name is '16...' it should run soon after '15-sslcert'. Whilst technically it could still be overwritten by an inithooks package update, it's unlikely (I don't have any plan to include a '16regen-pfx-file' script in the intihooks package.

Another way (perhaps the cleanest? although probably the most involved) would be to tweak our turnkey-make-ssl-cert script. Your tweaked copy could then be placed in the overlay of your appliance build code (i.e. overlay/usr/local/bin/turnkey-make-ssl-cert). As this script is a common overlay by default and not packaged, your tweaked copy wouldn't be at any risk of being overwritten. On the downside, any future tweaks/improvements that we make to 'turnkey-make-ssl-cert' wouldn't propagate either. That's probably unlikely to be an issue for v16.x, but may be an issue for v17.x.


A final note is that you might also want to consider the case where a user gets a free Let's Encrypt certificate via our Let's Encrypt Confconsole plugin. The code that does that behind the scenes is a little messy. The original intention was for it to also leverage 'turnkey-make-ssl-cert' (and just have a locally generated cert signed by Let's Encrypt) but the dev that was working on it got pulled off onto something else before he'd complete. I took over and wasn't as familiar with SSL certs as he was so took the easy route and just pulled the complete cert from Let's Encrypt.

Anyway, I think that there's really only one way to reliably adjust that, at least for now. As background and context; the Let's Encrypt plugin is packaged as part of Confconsole. The Let's Encrypt plugin specific source is within the plugins/Lets_Encrypt dir with the other files required within the share/letsencrypt directory. Despite it being packaged, the files in the share directory are only copied into the relevant config location on first run. So if you place your tweaked config into the relevant location in your overlay, then it won't be overwritten by the package.

The file that you'll need to tweak and place in your overlay is the Dehydrated hook script. The lines that write teh default TurnKey SSL files are (currently) lines 42-44. So you'll probably want to insert a new line (i.e. the openssl command you note above) after those lines (and before the "success" message is logged). You'll want to add your tweaked script as 'overlay/etc/dehydrated/etc/dehydrated/confconsole.hook.sh'.

Hopefully that should be all of it...


PS I've never come across .pfx files before, but as I understand them, they're a PKCS#12 that seem to be common/default format for the MS IIS webserver. They appear to be an encrypted container that includes both the (public) certificate and the (private) key. I'm curious what they're required by? Is it something custom, or something generic? The reason why I ask is that we have an upcoming "ASP .Net Core" appliance (served by Apache) and it seems to work ok fine with the default self signed cert (I assume because it's being served by Apache) but I'm wondering if there is something that we've missed or not considered?

Craig T.'s picture

Thanks, Jeremy. That's good to know. I'll look at tweaking them with one of the above options to make sure all is working well.

So, if I do it at build time are you saying the inithook wipes out the cert and key?

 

We are running an ASP .Net Core application in a Docker container. It essentially has a webserver built in, Kestrel. You can hard code some of this in your .NET code or you can pass environment variables to the container to switch it from HTTP to HTTPS, mapping the cert into the container. All the documentation for this references the PFX, so that the container/web server have the private key and the whole chain. Like you said, I think it is just a binary representation of the the public cert chain plus the private key.

If you are using .NET Core on Apache, Apache is likely handling all of the SSL stuff for you vs. the built in Kestrel.

Some documentation here:

Implementation depends a little on if you are on Windows using Windows containers or on Linux/Mac using Linux containers, but it is close. Basically, you turn on HTTPS, tell it the port, map to the PFX file, and give it the password (if you used one).

Jeremy Davis's picture

Thanks tons for the additional info re Kestrel. Your note re .NET Core on Apache makes tons of sense... It never occurred to me that your container might include a full "proper" webserver (i.e. one that can host directly to the internet).

Re your usage, why not reverse proxy your container with Nginx installed on the host? Whilst we don't have any appliances that have software installed via Docker, we do have apps that "self host" and use a webserver as a reverse proxy (usually Nginx because it's lightweight and does reverse proxying and static content hosting extremely efficiently). Two that come to mind (and links to the nginx conf) are Mayan-EDMS and Syncthing.

Then you won't need to do anything with certs. Nginx can then connect to your container via https with your own default internal certs, or could just use vanilla http. If you wanted to make it super polished, you could even provide a default Nginx error page if it can't connect to your container with a note to wait and/or some troubleshooting steps or something?!

Just a thought though... OTOH that might just be a whole other can of worms?!

Also, one other afterthought re the default SSL inithook (15regen-sslcert), whilst as per my previous note, it's not ideal to overwrite it with your own hook. The actual risk of it causing issues in practice are extremely low. Under most circumstance they will only run on firstboot, so even if it does get overwritten it's probably unlikely to cause issues in practicce. I.e. to trigger the problem user would need to install an updated inithook package and re-run the firstboot scripts...

Regardless, good luck and I look forward to hearing how you go.

Add new comment