feat(pki): check the PKI folder before an apply - #741
Open
ralgozino wants to merge 3 commits into
Open
Conversation
furyctl did not check the folder in .spec.kubernetes.pkiPath (Immutable)
or .spec.kubernetes.pkiFolder (OnPremises) before an apply. When the
folder or one of its files was absent, the apply failed in the middle,
inside an Ansible task. The message did not say how to correct the
fault.
`furyctl apply` and `furyctl validate config` now check that the folder
holds the files that the installer roles copy to the nodes:
- under master/: ca.crt, ca.key, front-proxy-ca.crt, front-proxy-ca.key,
sa.key
and sa.pub
- under etcd/: ca.crt and ca.key
An absent folder names the `furyctl create pki` command to run. An
incomplete folder names the files that are absent or empty. A file that
furyctl cannot read gives a read error, and not a name in that list. The
message for an incomplete folder tells the user to delete the folder,
and that step destroys the CA of a cluster that exists.
The check is a separate function, and not a rule of config.Validate,
because 6 more commands call config.Validate and read no local PKI.
`furyctl create config` writes a configuration whose PKI folder cannot
exist yet, and it deletes the file when validation fails.
`furyctl apply` skips the check when the selected phases read no local
PKI. As a result, an apply of the distribution or the plugins phase
alone does not ask for the CA keys. A dry run also skips the check, with
a warning, because it stops before Ansible.
The path resolution repeats what the template mapper does with the same
value before it renders the playbooks. First it expands the dynamic
values, for example "{env://PKI_DIR}" and "{path://pki}". Then it
resolves a relative path against the folder of the configuration file. A
relative path without a "./" prefix is an error, because the mapper does
not make such a value absolute.
The result is always absolute, because `furyctl validate config` does
not make the path of the configuration file absolute. A relative path in
a message is correct in one working folder only.
ralgozino
marked this pull request as ready for review
August 5, 2026 16:45
ralgozino
requested review from
marcopaggioro,
nutellinoit,
smerlos and
stefanoghinelli
August 5, 2026 16:45
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary 💡
furyctl did not check the folder in
.spec.kubernetes.pkiPath(Immutable) or.spec.kubernetes.pkiFolder(OnPremises) before an apply.When the folder or one of its files was absent, the apply failed in the middle with an Ansible error hard to understand.
Closes sighupio/distribution#584
Relates:
Description 📝
furyctl did not check the folder in
.spec.kubernetes.pkiPath(Immutable) or.spec.kubernetes.pkiFolder(OnPremises) before an apply. When the folder or one of its files was absent, the apply failed in the middle, inside an Ansible task. The message did not say how to correct the fault.furyctl applyandfuryctl validate confignow check that the folder holds the files that the installer roles copy to the nodes:furyctl applyskips the check when the selected phases don't need the PKI. As a result, an apply of the distribution or the plugins phase alone does not ask for the CA keys. A dry run also skips the check, with a warning, because it stops before Ansible.Failure modes
An absent folder names the
furyctl create pkicommand to run.An incomplete folder, names the files that are absent or empty.
A file that furyctl cannot read gives a read error, and not a name in that list. The message for an incomplete folder tells the user to delete the folder, and that step destroys the CA of a cluster that exists.
The table below gives the commands and the phases that do the check:
apply,apply --phase infrastructure|kubernetesapply --phase distribution|pluginsapply --start-froma distribution or plugins sub-phaseapply --start-from post-kubernetescoreKubernetesskipsapply.yamlapply --post-apply-phases kubernetesextraPhasesrepeats that phaseapply --dry-runvalidate configconfig.ValidateWorth noting that during the resume of an upgrade the PKI check will be done because the start phase comes from the saved state in the configmap and is not known at validate config time. If the user specifies
--upgradeand--start-fromthe starting phase will be known and the check will be skipped if not needed.Breaking Changes 💔
None. Each new check is preventive. The blocked cases make the apply fail later, inside an Ansible task.
A test in CI can fail if it does not create the PKI folder before it uses it. The correction is simple: create the pki first. From what I checked, distribution and furyctl tests are not affected.
Tests performed 🧪
furyctl create config --kind Immutableand--kind OnPremises, against a local distribution: the file is written, and it is not deleted.validate configwith the folder absent, with a complete folder, and with 2 files removed.validate configwithpkiPath: pki(a relative value without a prefix), with{path://realpki}and with{env://PKI_DIR}.validate configwith a relative--configvalue from 2 different working folders: the message gives the same absolute path.validate configwith an Immutable configuration withoutpkiPath, against the schema of distribution#585: the schema reports the absent field first.apply --phase distributionwith an incomplete folder: the check does not run.apply --phase kuberneteswith an incomplete folder: exit code 1, with the message for an incomplete folder.apply --dry-runwith the folder absent: a warning, and the apply continues.0o000): a read error, and not a message for absent files.furyctl dump templateindistribution/tests/templates/immutable/01-full-calico-nginx, which holdspkiPath: ./pkiand nopkifolder: exit code 0, and the result is the same as the baseline. This is the command thattest:templates:regressionsruns.Future work 🔧
furyctl.yaml.Self-assessment checklist 🏁
Important
Make sure that you completed this checklist before asking for review.
PRs that do not have this checklist ready won't be reviewed.
docs/releases/unreleased.mdfile (or equivalent)NewPKIValidatorFactoryreturns nil forEKSClusterandKFDDistribution, so their behavior does not change