When using a chained store of Kubernetes -> Memory -> File, a file-backed cert with a valid ResourceVersion could not be updated when the Kubernetes store was offline, as the Memory store was skipping the update if the ResourceVersion was not changed.
The Kubernetes store passes through the secret update without a modified ResourceVersion if the Secret controller is not yet available to round-trip the secret through the apiserver, as the apiserver is what handles updating the ResourceVersion when the Secret changes.
In RKE2, this caused a deadlock on startup when the certificate is expired, as the apiserver cannot be started until the cert is updated, but the cert cannot be updated until the apiserver is up.
Fix this by also considering the certificate hash annotation when deciding if the update can be skipped.
Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
We had similar code to prevent blocking when calling Update(), but not in the init function.
Ref: https://github.com/rancher/rancher/issues/42278
Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
Updates to the secret that occurred before the controller was done
syncing were not being written to Kubernetes. Subsequent updates to the
secret would eventually get it written, but Rancher requires that the
cert be written immediately. This was probably an unnecessary
optimization anyway, so back it out in favor of just checking to see if
the secrets controller is available.
Also fixed improper handling of multiple goroutines attempting to create
the Kubernetes secret at the same time; this was also handled eventually
but caused an unnecessary round of extra writes to the secret.
Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
Refreshing the cert should force renewal as opposed to returning
early if the SANs aren't changing. This is currently breaking refresh
of expired certs as per:
https://github.com/rancher/k3s/issues/1621#issuecomment-669464318
Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
On the start of a new server we do not want to blindly save the
cert because that will change the TLS key. Instead only write
to k8s on start if there is no secret in k8s. On start of the
controller it will sync up if the local file and k8s secret aren't
the same