Skip to content

[17.0-stable] Surface how the vault was unlocked and report the key derivation - #6491

Merged
rene merged 3 commits into
lf-edge:17.0-stablefrom
eriknordmark:vaultmgr-unseal-observability-17.0-stable
Sep 10, 2026
Merged

[17.0-stable] Surface how the vault was unlocked and report the key derivation#6491
rene merged 3 commits into
lf-edge:17.0-stablefrom
eriknordmark:vaultmgr-unseal-observability-17.0-stable

Conversation

@eriknordmark

@eriknordmark eriknordmark commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Description

Backport of #6058 and #6455 to 17.0-stable.

Whether the vault was unsealed by the locally TPM-sealed key or by the
controller's escrowed key after a failed local unseal is not visible after the
fact: both end with the vault enabled, both log "successfully unsealed", and the
boot-time vaultmgr logs rotate out of the in-memory ring. Nor does anything say
whether the key is the TPM key alone or is still merged with the fixed constant
kept for vaults created before EVE 7.10.0, where half the key material is not
TPM-held. Both facts are decided on the device and never leave it, so neither is
visible across a fleet.

vaultmgr now records the unlock method at each unlock site and the derivation
mode when the vault config is read, carries both out on VaultStatus, and
zedagent puts them in info.VaultInfo. diag appends the unlock method to its
vault line and raises the level to WARNING for a controller-key or
wipe-and-recreate unlock. Both enums are pillar-native values cast to their
eve-api counterparts, pinned by a unit test so renumbering either side fails
instead of mislabelling a fleet report.

Three commits: #6058 cherry-picked with -x, a re-pin of pkg/pillar to the
eve-api revision carrying the new VaultInfo fields, and #6455's pillar change
cherry-picked with -x.

PR dependencies

None. The eve-api side (lf-edge/eve-api#157) is already merged; eve-api has no
stable branches, so the pin can only move forward on main and the regenerated
bindings also carry the API additions merged since this branch's previous pin,
none of which pillar reads here. Only pkg/pillar is re-pinned — the other
modules on this branch reference none of the new fields, and no Dockerfile
FROM hash changes as a result (make check-docker-hashes-consistency passes).

Adaptations

  • This branch already carries the VaultTrimStatus work, which sits in exactly
    the places both commits touch. The two field sets are merged rather than one
    replacing the other, and ps/ucChan are not duplicated.
  • pkg/pillar/docs/vaultmgr.md: Report vault unlock method and key derivation #6455's two doc additions are dropped. This
    branch's vaultmgr.md predates master's rewrite of it and has neither the
    data-at-rest bullet nor the VaultStatus field list they attach to.

How to test and validate this PR

In pkg/pillar: go test ./types/ ./cmd/diag/, which includes
TestVaultUnlockMethodToProto and TestVaultKeyDerivationToProto — these fail
if either enum is renumbered on either side of the cast. go build ./...,
go vet ./types/ ./cmd/vaultmgr/ ./cmd/zedagent/ ./cmd/diag/ and gofmt -l are
clean on this branch, as is make check-docker-hashes-consistency.

On a device, diag gains unlock:<method>, with the mismatching PCRs on a controller-key unlock on its vault line, and vaultmgr logs
vault <name> unlocked: method=<method> at each unlock site. A device whose
local TPM unseal succeeds reports tpm-local-sealed at INFO; one that fell back
to the controller's escrowed key reports controller-key at WARNING; one whose
vault was wiped and recreated reports recreated at WARNING; one without a TPM
reports no-tpm. The same values, plus the key derivation, reach the controller
in VaultInfo, where crossing HSMStatus == ENABLED with
key_derivation == UNSPECIFIED identifies devices that do not yet report it.

Changelog notes

The controller is now told how each device's vault was unlocked this boot and
whether its key is derived from the TPM alone or still mixes in the fixed
constant used before EVE 7.10.0. diag shows the unlock method on the device
and flags a controller-key or wipe-and-recreate unlock as a warning.

PR Backports

Checklist

  • I've provided a proper description
  • I've added the proper documentation
  • I've tested my PR on amd64 device
  • I've tested my PR on arm64 device
  • I've written the test verification instructions
  • I've set the proper labels to this PR
  • I've added a reference link to the original PR
  • PR's title follows the template

Today an operator cannot easily tell whether the vault was unsealed by
the locally TPM-sealed key or by the controller-provided escrow key
after a failed local unseal -- both end with the vault enabled, the
"successfully unsealed" log line is emitted on both paths, and the
boot-time vaultmgr logs rotate out of the in-memory ring.

Record the unlock method explicitly on VaultStatus.UnlockMethod, set at
each unlock site in vaultmgr, and keep reporting the mismatching PCRs
from a failed local unseal even after the controller-key recovery
re-seals. The wipe-and-recreate recovery path -- local unseal failed and
the controller had no escrowed key -- is surfaced as its own method so a
lost-vault event is not mistaken for a healthy boot. The method is
tracked only for the default vault. diag subscribes to VaultStatus and
appends the method to its vault line, flagging a controller-key or
recreated unlock (with the mismatching PCRs) as a warning, so the
local-unseal health of a device is visible at a glance.

Signed-off-by: eriknordmark <erik@zededa.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit bea069f)
@codecov

codecov Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 4.00000% with 96 lines in your changes missing coverage. Please review.
✅ Project coverage is 21.76%. Comparing base (e69cda3) to head (aac7d15).

Files with missing lines Patch % Lines
pkg/pillar/cmd/diag/diag.go 0.00% 39 Missing ⚠️
pkg/pillar/cmd/vaultmgr/vaultmgr.go 0.00% 35 Missing ⚠️
pkg/pillar/types/vaultmgrtypes.go 16.66% 20 Missing ⚠️
pkg/pillar/cmd/zedagent/reportinfo.go 0.00% 2 Missing ⚠️
Additional details and impacted files
@@               Coverage Diff               @@
##           17.0-stable    #6491      +/-   ##
===============================================
+ Coverage        21.38%   21.76%   +0.37%     
===============================================
  Files              500      510      +10     
  Lines            92650    94443    +1793     
===============================================
+ Hits             19813    20555     +742     
- Misses           71191    72061     +870     
- Partials          1646     1827     +181     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

eriknordmark and others added 2 commits September 8, 2026 21:16
Re-pin pkg/pillar to the eve-api revision that carries VaultInfo's
unlock_method and key_derivation fields and re-vendor. eve-api has no
stable branches, so the pin can only move forward on main: the
regenerated bindings also carry the API additions merged between this
branch's previous pin and that revision, none of which pillar reads
here. The other modules on this branch keep their own pins, as none of
them reference the new fields.

Signed-off-by: eriknordmark <erik@zededa.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A vault that reports as enabled tells an operator nothing about how the
device got there. A clean local unseal, a recovery that fell back to the
controller's escrowed key, and a wipe-and-recreate that lost the vault's
contents are indistinguishable in the status alone, and nothing says
whether the key still mixes the TPM key with the fixed constant used by
vaults created before the TPM-only scheme, where half the key material is
not TPM-held. Both facts are decided on the device and never leave it, so
neither condition is visible across a fleet.

vaultmgr already tracks the unlock method for the default vault; record
the derivation mode alongside it when the vault config is read, and carry
both out through VaultStatus so zedagent can put them in VaultInfo. Both
are pillar-native enums cast to their eve-api counterparts, pinned by a
unit test so renumbering either side fails instead of mislabelling a
fleet report.

A device only derives a vault key when it has a TPM and a /persist
filesystem that sets a vault up, so the derivation stays unreported
elsewhere rather than claiming a mode no key was built with.

Signed-off-by: eriknordmark <erik@zededa.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit db5c0a7)
@eriknordmark eriknordmark changed the title [17.0-stable] vaultmgr,diag: surface how the vault was unlocked [17.0-stable] Surface how the vault was unlocked and report the key derivation Sep 8, 2026
@rene
rene merged commit a051bc1 into lf-edge:17.0-stable Sep 10, 2026
50 of 52 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants