You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(config): switch ACME and EST on and off through machine config #284
CryptOS-PKI/api#115 (for CryptOS-PKI/api#114) adds Pki.acme and Pki.est to MachineConfig, and per-protocol state to NodeStatus. The node still ignores both: config.FromProto and ToProto don't map the blocks, and CarryForwardProtoGaps keeps whatever the stored YAML had. So neither config apply, the maintenance install nor the Fleet Manager can switch ACME or EST on, change it or switch it off, and GetStatus can't say what a node serves.
This builds the node side of that contract. A protocol switch is a reboot-required change: config apply stores it, and the listener starts, stops or changes only at the next boot.
Acceptance criteria
FromProto/ToProto map pki.acme and pki.est; CarryForwardProtoGaps is gone.
An absent block keeps the stored block; enabled: false switches the protocol off; enabled: true switches it on and is validated.
Secrets are write-only: GetConfig returns hmac_key_base64 and password_sha256 empty; an apply with an empty secret keeps the stored value for the same key_id or username; an empty secret for an unknown identifier is rejected.
A Root rejects an enabled protocol, in config validation and in the ceremony path (ceremony start --config).
The maintenance install and re-provision carry the blocks.
Listeners start only at boot from the stored config, and every protocol change answers requires_reboot: true.
NodeStatus.protocols reports configured, running and reboot_pending per protocol, and config_reboot_pending flags any stored reboot-required change.
cryptosctl status prints a Protocols line and flags a pending reboot.
Tests cover each point, including an apply round trip that turns ACME on and then off, and the Root rejection in both paths.
Tasks
Task 1: map the blocks, apply rules and write-only secrets
Task 2: Root rejection in validation and the ceremony
Fixed inside #286: an unchanged re-apply over the wire always answered requires_reboot=true, even with the same digest, because gRPC delivers an empty list as nil while the stored YAML parses it as an empty slice, and NeedsReboot compared with reflect.DeepEqual. NeedsReboot now compares the stored YAML form (config.Equivalent), covered by TestNeedsRebootIgnoresNilVersusEmpty.
Activity
Bugs5382 commentedon Sep 30, 2026
Fixed inside #286: an unchanged re-apply over the wire always answered requires_reboot=true, even with the same digest, because gRPC delivers an empty list as nil while the stored YAML parses it as an empty slice, and NeedsReboot compared with reflect.DeepEqual. NeedsReboot now compares the stored YAML form (config.Equivalent), covered by TestNeedsRebootIgnoresNilVersusEmpty.