Stop vault safety checks from reading unreadable state as empty (closes #51)
check / check (push) Successful in 1m8s
check / check (push) Successful in 1m8s
Adding a PGP unlocker checked unlockers.d for a duplicate and, when the directory could not be read, reported no duplicate and went on. The check now returns an error naming the directory and cause, and the add stops; a duplicate found is still reported as one. The same flaw guarded removing the last unlocker and removing a vault (an unreadable secrets directory counted as no secrets) and vault import (an unreadable pub.age counted as no long-term key). Those now stop with an error too. `unlocker list` keeps skipping entries it cannot read; a comment at the duplicate check says why the two differ. Model: opus-5-5
This commit is contained in:
+26
-26
@@ -49,7 +49,6 @@ var (
|
||||
"is already added as an unlocker")
|
||||
errUnsupportedUnlockerType = errors.New("unsupported unlocker type")
|
||||
errLastUnlocker = errors.New("refusing to remove last unlocker")
|
||||
errUnlockerExists = errors.New("unlocker already exists")
|
||||
)
|
||||
|
||||
// UnlockerInfo represents unlocker information for display
|
||||
@@ -691,8 +690,15 @@ func (cli *Instance) addPGPUnlocker(cmd *cobra.Command) error {
|
||||
// Check if this GPG key is already added
|
||||
expectedID := "pgp-" + fingerprint
|
||||
|
||||
err = cli.checkUnlockerExists(vlt, expectedID)
|
||||
exists, err := cli.checkUnlockerExists(vlt, expectedID)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"could not check whether GPG key %s is already an unlocker: %w",
|
||||
gpgKeyID, err,
|
||||
)
|
||||
}
|
||||
|
||||
if exists {
|
||||
return fmt.Errorf("GPG key %s %w", gpgKeyID, errGPGKeyAlreadyUnlocker)
|
||||
}
|
||||
|
||||
@@ -772,44 +778,38 @@ func (cli *Instance) UnlockerSelect(unlockerID string) error {
|
||||
return vlt.SelectUnlocker(unlockerID)
|
||||
}
|
||||
|
||||
// checkUnlockerExists checks if an unlocker with the given ID exists
|
||||
func (cli *Instance) checkUnlockerExists(vlt *vault.Vault, unlockerID string) error {
|
||||
// Get the list of unlockers and check if any match the ID
|
||||
unlockers, err := vlt.ListUnlockers()
|
||||
if err != nil {
|
||||
secret.Warn("Could not list unlockers during duplicate check", "error", err)
|
||||
|
||||
return nil // If we can't list unlockers, assume it doesn't exist
|
||||
}
|
||||
|
||||
// Get vault directory to construct unlocker instances
|
||||
// checkUnlockerExists reports whether the vault already has an unlocker
|
||||
// with the given ID. It returns an error, and no answer, when unlockers.d
|
||||
// cannot be read; the caller must then not create the unlocker.
|
||||
func (cli *Instance) checkUnlockerExists(
|
||||
vlt *vault.Vault, unlockerID string,
|
||||
) (bool, error) {
|
||||
vaultDir, err := vlt.GetDirectory()
|
||||
if err != nil {
|
||||
secret.Warn("Could not get vault directory during duplicate check",
|
||||
"error", err)
|
||||
|
||||
return nil
|
||||
return false, fmt.Errorf("failed to get vault directory: %w", err)
|
||||
}
|
||||
|
||||
// Check each unlocker's ID
|
||||
unlockersDir := filepath.Join(vaultDir, "unlockers.d")
|
||||
|
||||
unlockers, err := vlt.ListUnlockers()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf(
|
||||
"failed to list unlockers in %s: %w", unlockersDir, err,
|
||||
)
|
||||
}
|
||||
|
||||
for _, metadata := range unlockers {
|
||||
// Construct the unlocker matching this metadata to get its ID
|
||||
id, err := findUnlockerIDByMetadata(cli.fs, unlockersDir, metadata, true)
|
||||
if err != nil {
|
||||
secret.Warn(
|
||||
"Could not read unlockers directory during duplicate check, "+
|
||||
"skipping unlocker",
|
||||
"unlockers_dir", unlockersDir, "error", err)
|
||||
|
||||
continue
|
||||
// Unlike `unlocker list`, never skip here: a skipped entry may be the duplicate.
|
||||
return false, err
|
||||
}
|
||||
|
||||
if id != "" && id == unlockerID {
|
||||
return errUnlockerExists
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return false, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user