gokrazy / gokrazy

turn your Go program(s) into an appliance running on the Raspberry Pi 3, Pi 4, Pi 5, Pi Zero 2 W, or amd64 PCs!
https://gokrazy.org
BSD 3-Clause "New" or "Revised" License
3.28k stars 121 forks source link

Replacing TLS certificate with trusted certificate #163

Open joneskoo opened 1 year ago

joneskoo commented 1 year ago

Platform

I’m using:

Observed behavior

I want to use a TLS certificate I get from mkcert. I overwrote the self-signed cert:

hostname=my.host.example.com
mkcert -key-file "/Users/$USER/Library/Application Support/gokrazy/hosts/${hostname}/key.pem" -cert-file "/Users/$USER/Library/Application Support/gokrazy/hosts/${hostname}/cert.pem" ${hostname}

Unfortunately after this gok update will no longer update because it won't trust the TLS certificate.

I would use --insecure but it then would use http:// and that will not be able to connect when the appliance already has TLS enabled. Probing will not use https with insecure.

Previously I was able to work around this with --update=https://gokrazy:password@my.host.example.com but gok update no longer supports this, only "", "off", "self-signed".

Luckily I was able to use InternalCompatibilityFlags -> Update to do it like before, but that shouldn't be the way to do it.

Expected behavior

Using mkcert CA which is trusted by local system would be nice to support as standard.

I would expect it to be possible with gok to specify a custom TLS key and cert that I get from mkcert. It would be ok if it is documented where to provide the cert and how to replace already-in-use certificate with gok as normally it'd only verify the same cert it provisions which doesn't help when we need to replace the certificate.

stapelberg commented 1 year ago

Thanks for filing this. I’m not currently using TLS myself on my gokrazy instances, so feedback about it is valuable :)

Unfortunately after this gok update will no longer update because it won't trust the TLS certificate.

Hmm, why not?

Can you share the config.json you’re using? In particular, what do you set in the CertPEM and KeyPEM fields of the Update struct? https://gokrazy.org/userguide/instance-config/#updatecertpem

joneskoo commented 1 year ago

I tried to put the cert to use in CertPEM and KeyPEM first as cert.pem and key.pem assuming they would be picked up from instance directory. I think what happened with this was that it created still self-signed cert and tried to validate against the CertPEM; would need to try again to understand what actually happened. I now omit both in config and wrote the cert over the path where gok puts the self signed cert, as per mkcert command I gave.

So config.json now only has UseTLS self-signed.

Please be explicit in doc whether KeyPEM and CertPEM are deployed into the image or used for validation. I think it's logical CertPEM is used for both but then it's not possible to replace cert without --insecure. Maybe this is acceptable but better would be document how to provide a certificate bundle of trusted CAs or certificates for validation. I would call it CABundle and document it is not used for deployment and it's optional and CertPEM is implicitly trusted.

Rotating the self-signed cert will also eventually be required so how to do that (particularly when the cert already expired) is needed. Most obvious is to make --insecure work when the cert is not valid. Now --insecure only works when appliance doesn't yet use https.

TL;DR

  1. Replacing cert has to be possible when https is already deployed with --insecure (now tries to use http and fails)
  2. Document CertPEM and KeyPEM better - deployment or validation?
  3. Document replacing certificate (rm certs and --insecure?)
  4. Nice to have: add CABundle for trusted certificates and CAs validation only in gok so cert can be also replaced without insecure.