Trusted certificate authorities

Status: Implemented Issue: https://gitlab.com/gitlab-org/cloud-native/gitlab-operator/-/work_items/2262 Parent: GitLabCore reconciler

Goal

GitLab trusts the certificate of every TLS endpoint the Operator connects it to, such as an Orbit, without the administrator copying a CA into the chart values. The administrator still adds certificate authorities of their own, such as a corporate CA, through a typed field.

Requirements

  • spec.certificates.customCAs lists certificate authorities of the administrator’s own. Each entry names a Secret or a ConfigMap in the namespace, and optionally the keys to read. It sets global.certificates.customCAs of the chart. The API server rejects an entry that names both a Secret and a ConfigMap, or neither.
  • global.certificates.customCAs in spec.chart.values replaces that list, as every free-form value wins over the structured fields.
  • An Orbit that serves TLS reports in status.caSecretRef the Secret and key that hold the CA of its certificate: the TLS Secret the webserver mounts, which is spec.tls.secretName unless spec.chart.values set tls.existingSecret, and ca.crt. It reports it exactly while it reports status.grpcEndpoint. The Orbit reconciler reads no Secret to do so.
  • While spec.orbitRef is configured, and the Secret the Orbit reports holds at least one PEM certificate under its key, GitLab trusts that CA. The Operator copies it into a ConfigMap it owns, <instance>-operator-cas, under the key orbit-<orbit>.crt, and adds the ConfigMap to global.certificates.customCAs after the free-form values, so neither list drops the other.
  • An entry that already names that ConfigMap is not added twice.
  • When spec.chart.values set global.certificates.customCAs to a value that is not a list, the value is left as it is and no CA is added. GitLab still connects to the Orbit, and the message of OrbitConnected says why no CA was added.
  • status.managedCAs lists each CA the Operator adds: its source, such as Orbit and its name, the ConfigMap and key, the subject, and the expiry of the first certificate.
  • A missing Secret, a missing key, or a key that holds no PEM certificate adds nothing, and fails nothing: GitLab still connects to the Orbit and trusts only its system certificate authorities. OrbitConnected stays True, and its message says why no CA was added.
  • Without a CA to add, the Operator renders no ConfigMap, and removes one it applied before once the release has rolled out without it.
  • A changed CA reaches the ConfigMap within 30 seconds, on a pass that requeues.
  • A changed CA rolls the webservice, Sidekiq, and Toolbox pods, which call the Orbit, without running the migrations again: their pod templates carry a checksum of the certificate authorities the Operator manages. Pods of the other components keep the certificate authorities they started with until they restart.

Out of scope

  • Issuing certificates for components, for example through a cert-manager issuer reference.
  • Restarting pods when the content of a CA of the administrator’s own changes.
  • Checking that the keys of two entries do not collide. Each key becomes a file name in one directory, so two entries must not share one.

FAQ

  • Why a ConfigMap of the Operator, and not the Secret of the Orbit? The chart names each projected file after its key. An entry that read ca.crt from the Secret would collide with any entry of the administrator’s own that also reads ca.crt, and the API server would refuse the pods. A missing key would also leave every new GitLab pod unable to start. See ADR 43.
  • Why do the certificate authorities of the Operator survive the free-form values? Dropping them would silently break the connection to the Orbit for any administrator who also trusts a corporate CA.
  • What if spec.chart.values set customCAs to null or []? Either one replaces spec.certificates.customCAs, like any other list there, so only the certificate authorities of the Operator remain. Nothing on the resource reports that the structured entries were replaced; the Bridge form warns.
  • What if two entries of spec.chart.values share a key? Both become the same file, so the API server refuses the GitLab workloads and the apply fails. The Bridge form checks the keys of spec.certificates.customCAs, not the free-form values.
  • Why does the ConfigMap stay until the rollout ends? A pod that an old ReplicaSet recreates mid-rollout still mounts it, and would not start without it.
  • Does adding or removing a CA roll GitLab out? Yes. It changes the chart values, so the GitLab pods roll, and the migrations Job runs under a new name. A new Orbit connection and its CA arrive in the same pass, so they roll it out once.