GitLab secrets
Status: Implemented Issue: https://gitlab.com/gitlab-org/cloud-native/gitlab-operator/-/work_items/2249 Parent: none
Goal
A GitLabCore gets the secrets its chart generates without a hook Job. No existing value is
regenerated, lost, or reshaped.
Requirements
- The definition accepts every
GitLabSecretsthe chart renders, except aned25519certificatealgorithmor an odd RSAkeySize, and rejects any other enum value. - A missing Secret or key is generated unless a rule below reports it. A present key keeps its
value, even empty, except that
secrets.ymlgains fields as below. No key is removed, and no type changes. - An
x509pair, an SSH host key pair, and the certificate set of CA, TLS, and chain Secrets are each generated whole. A missing.pub, chain, orx509certificate is derived. Other partial units are reported. - A data-bearing unit that
statusrecorded as ready is reported instead of regenerated: a key when it is missing, and arailsSecretsfield when it is absent, null, or empty. Data-bearing units are therailsSecretsfields, the SSH host key pairs, the certificate set, and the generators the chart markspersistent. railsSecretsfills its other absent, null, and empty fields, keeps every other field, environment, and list, and reports asecrets.ymlthat does not parse.- Values match the Job’s recipes: character set, length, encoding, wrap, key type and size, PEM
type, and certificate structure. Certificate validity follows
caDaysandcertDays. - Entries that name one Secret merge. A key with two different generators, and an immutable Secret that lacks a key, are reported.
- Secrets carry no owner reference, and get every label of the
GitLabSecretsbutoperator.gitlab.com/release-*. A Secret that twoGitLabSecretsdeclare gets a warning event and keeps its labels. - Deleting a
GitLabCoredeletes itsGitLabSecretsand leaves every Secret it generated. - The
Readycondition covers the current generation, andstatuseach Secret. A reported Secret is not ready, andReadysays why. - A
GitLabCorerenders withprovider: controllerunlessspec.chart.valuessets another. - A
GitLabCoreapplies theGitLabSecretsits chart renders first, owned by theGitLabCore. On every pass, and before every upgrade step, it applies nothing else and runs no hook until thatGitLabSecretsisReadyfor its current generation. - While it waits,
InitializedisFalsewith reasonWaitingForSecretsand a message that holds the reason and message ofReady, and the phase isPreparing. - A
GitLabSecretsthe API server refuses, such as one with aned25519certificate or an odd RSAkeySize, fails the pass before anything else is applied.InitializedisFalsewith reasonApplyFailedand the message of the API server. - On chart 10.5 or later, a
GitLabCorereachesAvailablein any watched namespace with no ServiceAccount or RBAC provisioned beforehand. - A render without a
GitLabSecrets, as from chart 10.4 and earlier, is applied without the wait, and the shared secrets Job of the chart runs as apre-installhook.
Out of scope
- The CNG binary (chart issue 6658),
a shared library, rotating values, certificate renewal, the
v1beta1GitLabresource, and FIPS. shared-secrets.enabled: false, where the administrator supplies every Secret.- Adopting the Secrets the Job created, for example on an upgrade from chart 10.4 or for a GitLab installed with Helm, with every key and field value byte for byte.
- Refusing another
shared-secrets.providerinspec.chart.values, or a chart that renders noGitLabSecrets.
FAQ
- Where does the controller depart from the Job or the chart contract?
- A partial unit is reported, not completed. Only a
.pub, a chain, and anx509certificate for an existing key are derived. Anx509certificate without its key is reported. - A data-bearing unit that was ready and is missing now is reported. The Job and the contract generate it again.
- A missing Secret with a reported unit is not created, not even with its other keys. The Job and the contract create it.
- A whole missing
rsa, rawbytes, orx509unit is added to an existing Secret. The Job adds only--from-literalkeys. - A missing SSH host key pair is generated in an existing Secret if that pair was never ready. The Job never changes an existing host-key Secret.
- A certificate set that holds some of its keys is completed only by deriving its chain. The Job issues a new CA and wildcard certificate on every run, and creates each missing Secret on its own, so it completes a partial set from a mismatched CA.
- A certificate set that has none of its keys is issued into its existing Secrets. The Job creates only the Secrets that are missing.
- A missing value is generated whenever a Secret changes, not once per hook run.
secrets.ymlis rewritten only when a field is added. The Job rewrites it on every run, and drops undeclared fields and other environments, which the controller keeps.- An empty-string
secrets.ymlfield that was never ready is regenerated, as the Job does. The contract fills absent or null fields only. - A
randomvalue has exactlylengthcharacters. The Job’sgen_randomcan come up short. - An SSH host key carries no comment, in its
.pubor in its private key.ssh-keygenwrites one into both. - A rewritten
secrets.ymlis indented by 2, drops---and..., joins the lines of folded scalars, tags merge keys as!!merge <<:, and ends with a newline. The Job writes no trailing newline. - A generated
secrets.ymlvalue that YAML would read as another type, such as all digits, is quoted. The Job leaves it bare. An existing bare value stays bare. - A
secrets.ymlwhose root or environment is null, or not a mapping, is reported. So is one that is not UTF-8, holds a duplicate key or a second document, or has a declared field that an alias or a tag makes null or empty, or that a merge key provides. The Job writes the declared fields back over it. - An
ed25519certificate algorithm is refused. The Job of chart 10.4 and later issues it. - An odd RSA
keySizeis refused. The Job’scfsslaccepts it. - The
operator.gitlab.com/release-*labels are left off, although the contract copies every label. The application labels stay whenglobal.application.createisfalse, although the Job removes them. - A key declared with two different generators is reported, and neither generates it. The Job keeps the first.
- A Secret that two
GitLabSecretsdeclare keeps its labels. The Job overwrites them.
- A partial unit is reported, not completed. Only a
- What happens to an existing Secret of another type? It keeps its type and stays ready. The
controller emits a
Normalevent that names both types. - Is a ready key that is present but empty reported? No. A present key keeps its value, even
empty, as in the Job. Only a
secrets.ymlfield is filled, or reported, when it is empty. A part that would be derived from an empty key, such as a.pubor anx509certificate, is reported instead. - Which sizes does the definition accept? A
lengthfrom 1 to 4096. An evenbitsfrom 2048 to 8192 forrsa,x509, and apemfield. Adays,caDays, andcertDaysfrom 1 to 106751, withcertDaysat mostcaDays. Anx509commonNameof at most 64 characters. At most 128secrets, 16generatorsper entry, 64fields, and onecertificatesentry, and a maximum length on every string, to bound the cost of the validation rules. The chart renders at most 28 entries, 2 generators per entry, and 8 fields. The Job takes other sizes, such asbits: 1024, which the chart does not render. - What else does the definition refuse? A Secret name that is not a DNS subdomain, and a key
outside
[-._a-zA-Z0-9]. A.inenvor a fieldpath, which never worked in the Job, because it reads them as a path. ArailsSecretsgenerator beside another one in its entry, as the chart does. Two fields with onepath, anx509certKeyequal to itskeyKey, and certificate Secrets that repeat each other or a name inspec.secrets. - Why is a data-bearing value not regenerated after it was ready? Fresh values would lose data
without a sign:
db_key_baseencrypts database columns, the host keys identify the instance to every Git client, and the database or OpenBao keeps the values of the generators the chart markspersistent. Token Secrets and signing keys are regenerated. - When is a missing data-bearing Secret generated anyway? The guard lives in
status, so it is generated when theGitLabSecretsis recreated, also by deleting itsGitLabCore, or restored without status, as Velero does by default. It is also generated when aGitLabSecretsthat never saw it ready declares it, or after its entry leftspec.secrets, for example while its component was off. Back those Secrets up. - Which chart does a
GitLabCoreneed? 10.5 or later, the first release expected with chart merge requests 5277, 5420, and 5433. The Operator does not enforce it. An earlier chart runs the Job, which needs a ServiceAccount and RBAC that the Operator does not create. For more information, see ADR 31. - What happens with another
shared-secrets.provider? The behavior is undefined. TheGitLabCoredoes not refuse it. - Why wait for the
GitLabSecrets? Every GitLab pod mounts Secrets it declares. A pod created before them fails to mount, and retries until they exist. - What happens when a running
GitLabSecretsstops being ready? TheGitLabCoreapplies nothing and reportsPreparinguntil it is ready again, for example after an administrator fixes a reported unit. The running workloads keep running, but no drift is repaired, and a version that follows the chart repository keeps its target. - How do I force fresh values? Delete the Secret, then delete the
GitLabSecrets. TheGitLabCorerecreates it with an empty status, and the controller generates what is missing. Checkstatusfor other reported units first: every missing data-bearing unit of the release regenerates too. - How do I fix a partial unit? Delete the part that remains. A unit that was never ready then
regenerates. For a unit that was ready, such as an SSH pair that lost its private key, delete the
lone
.pub, then theGitLabSecrets, as for fresh values. A non-empty private key without its.pubneeds no fix. - Why do the Secrets carry no owner reference? Garbage collection would delete them with their
owner. Like after
helm uninstall, an administrator removes them by hand. - Does
encoding: base64wrap? No. It stores standard base64 with no wrapping and no trailing newline, as the Job did.wrap: jsonArraywraps the encoded value. - Which SSH host keys are generated? RSA 3072, ECDSA P-256, and Ed25519, the set
ssh-keygen -Amakes in the Job’s image. An existing Secret keeps any other type. - Where does certificate validity come from? From
caDaysandcertDays. The chart sets them to what the Job issues, 1825 and 365, becauseselfsign.expiryapplies to neither backend. For more information, see chart issue 6693. - Why are Ed25519 certificates refused? Chrome and Firefox do not support an Ed25519 TLS server
certificate. A set the Job already issued with Ed25519 is kept, because an existing certificate
is never reissued. To replace it, set
rsaorecdsa, delete the three certificate Secrets, then theGitLabSecrets, as for forcing fresh values above. SSH host keys still include Ed25519.