Add unlock --idle, and packaging/repo.sh for repo.dixon.cx

vault unlock --idle counts the duration from the last command that used
the key rather than from the unlock: the agent resets its timer each
time it hands the key out. The agent loop no longer needs its own
goroutine.

packaging/repo.sh builds the dixon-vault .deb, .rpm and Arch packages
from a release tag (a clean git archive) with nfpm for amd64, arm64,
armv7, 386 and riscv64, then publishes them to the apt, dnf and pacman
repositories at repo.dixon.cx: apt-ftparchive with a signed InRelease,
createrepo_c (in a Fedora container) with signed RPMs and repomd.xml,
and repo-add (in an Arch container) with signed packages and database.
Indexes cover every package in the repository, under a lock, so other
projects publishing with their copy of the script are kept. The package
is dixon-vault because vault is HashiCorp Vault in Arch's [extra] and
HashiCorp's own repositories; it conflicts with vault.

README, guide and CLAUDE.md point at the repository.
This commit is contained in:
Andy Dixon
2026-10-03 09:44:49 +01:00
parent ec204f0ea2
commit 4c1507c463
8 changed files with 334 additions and 47 deletions
+12 -6
View File
@@ -57,7 +57,8 @@ const usage = `Usage:
vault rm -r FOLDER [-f] delete a folder and everything under it;
asks first unless -f (or -rf) is given
vault unlock [--for DURATION] remember the passphrase for DURATION
(default 5m), so commands skip asking
[--idle] (default 5m), so commands skip asking;
with --idle, DURATION since last used
vault lock forget it now
Options (any command):
@@ -91,8 +92,8 @@ func main() {
os.Exit(2)
}
cmd, args := os.Args[1], os.Args[2:]
if cmd == agentCmd && len(args) == 2 {
runAgent(args[0], args[1], os.Stdin, os.Stdout)
if cmd == agentCmd && len(args) == 3 {
runAgent(args[0], args[1], args[2], os.Stdin, os.Stdout)
return
}
fset := flag.NewFlagSet("vault "+cmd, flag.ContinueOnError)
@@ -103,6 +104,7 @@ func main() {
filler := fset.String("filler", "0", "")
yes := fset.Bool("yes", false, "")
ttl := fset.Duration("for", 5*time.Minute, "")
idle := fset.Bool("idle", false, "")
// rm's -r and -f; Go's flag package has no combined short flags, so
// -rf and -fr are spelled out.
recurse, force := fset.Bool("r", false, ""), fset.Bool("f", false, "")
@@ -295,10 +297,14 @@ func main() {
check(err)
id, err := unlockKeyFile(*keyPath, pass)
check(err)
check(agentStart(*keyPath, id, *ttl))
check(agentStart(*keyPath, id, *ttl, *idle))
id.Close()
fmt.Fprintf(os.Stderr, "unlocked until %s; vault lock forgets the key sooner\n",
time.Now().Add(*ttl).Format("15:04:05"))
if *idle {
fmt.Fprintf(os.Stderr, "unlocked until unused for %s; vault lock forgets the key sooner\n", *ttl)
} else {
fmt.Fprintf(os.Stderr, "unlocked until %s; vault lock forgets the key sooner\n",
time.Now().Add(*ttl).Format("15:04:05"))
}
case "lock":
want(0, 0)
if agentStop(*keyPath) {