1
0

checking in

This commit is contained in:
brent saner
2025-12-23 20:58:56 -05:00
parent d94a46af0b
commit 84845f9fe5
37 changed files with 3117 additions and 642 deletions

18
cmd/kill/args.go Normal file
View File

@@ -0,0 +1,18 @@
package main
import (
`r00t2.io/vault_totp/internal`
)
type (
Args struct {
internal.CommonArgs
KillArgs
}
KillArgs struct {
VaultTotpMnt string `env:"VTOTP_MNT" short:"m" long:"mount" default:"totp" description:"The Vault TOTP generator mount (a 'TOTP secrets' mount) to remove from."`
KeyNms []string `env:"VTOTP_DELKEYS" short:"k" long:"key" description:"Key name(s) to delete. If not specified, you will be prompted to delete all existing (see -f/--force)."`
Force bool `env:"VTOTP_FORCE" short:"f" long:"force" description:"Force the deletion of keys (don't prompt for confirmation). If explicit -k/--key key name(s) are provided, specifying this will consolidate all individual prompts into a single one (see -F/--force2). If deleting all keys (no -k/--keys specified), specifying this will bypass the confirmation."`
Force2 bool `env:"VTOTP_FORCE2" short:"F" long:"force2" description:"If -k/--key names were specified and -f/--force was specified, specifying this option in *addition* to -f/--force bypasses the consolidated confirmation as well. Has no effect if no -k/--key is specified or if -f/--force was not specified."`
}
)

23
cmd/kill/consts.go Normal file
View File

@@ -0,0 +1,23 @@
package main
import (
`context`
`sync`
`github.com/hashicorp/vault-client-go`
`github.com/jessevdk/go-flags`
`r00t2.io/goutils/logging`
)
var (
logger logging.Logger
args *Args = new(Args)
parser *flags.Parser = flags.NewParser(args, flags.Default)
)
var (
vc *vault.Client
wg sync.WaitGroup
ctx context.Context = context.Background()
existingOtp map[string]struct{} = make(map[string]struct{})
)

4
cmd/kill/doc.go Normal file
View File

@@ -0,0 +1,4 @@
/*
vault_totp_kill: Remove configured TOTP generators.
*/
package main

30
cmd/kill/funcs.go Normal file
View File

@@ -0,0 +1,30 @@
package main
import (
`github.com/hashicorp/vault-client-go`
)
// killKeyAsync kills key keyNm if found in the Vault mount.
func killKeyAsync(keyNm string) {
var err error
var ok bool
defer wg.Done()
if _, ok = existingOtp[keyNm]; !ok {
logger.Warning("Key '%s' does not exist on '%s'; skipping.", keyNm, args.KillArgs.VaultTotpMnt)
return
}
if _, err = vc.Secrets.TotpDeleteKey(
ctx,
keyNm,
vault.WithMountPath(args.KillArgs.VaultTotpMnt),
); err != nil {
logger.Err("killKeyAsync: Failed to delete key '%s' on '%s': %v", keyNm, args.KillArgs.VaultTotpMnt, err)
return
}
return
}

121
cmd/kill/main.go Normal file
View File

@@ -0,0 +1,121 @@
package main
import (
`bufio`
`fmt`
`log`
`maps`
`os`
`slices`
`strings`
`r00t2.io/vault_totp/internal`
)
func main() {
var err error
var p string
var doExit bool
var keyNm string
var doGlobal bool
var keyNms []string
var rdr *bufio.Reader = bufio.NewReader(os.Stdin)
var keys map[string]struct{} = make(map[string]struct{})
log.SetOutput(os.Stdout)
if doExit, err = internal.PrepParser("kill", args.CommonArgs, parser); err != nil {
log.Panicln(err)
}
if doExit {
return
}
logger = internal.Logger
if err = internal.Validate(args); err != nil {
log.Panicln(err)
}
if vc, err = internal.GetVaultClient(&args.VaultArgs); err != nil {
log.Panicln(err)
}
if existingOtp, err = internal.ListTotpKeys(ctx, vc, args.KillArgs.VaultTotpMnt); err != nil {
log.Panicln(err)
}
if len(existingOtp) == 0 {
fmt.Printf("No existing TOTP keys found at '%s'.\n", args.KillArgs.VaultTotpMnt)
os.Exit(0)
}
if args.KillArgs.KeyNms == nil || len(args.KillArgs.KeyNms) == 0 {
for keyNm = range maps.Keys(existingOtp) {
keys[keyNm] = struct{}{}
keyNms = append(keyNms, keyNm)
}
doGlobal = !args.KillArgs.Force
} else {
if args.KillArgs.Force {
doGlobal = !args.KillArgs.Force2
}
for _, keyNm = range args.KillArgs.KeyNms {
if !args.KillArgs.Force {
p = ""
fmt.Printf("Delete TOTP '[%s]/%s'? (y/N)\n", args.KillArgs.VaultTotpMnt, keyNm)
if p, err = rdr.ReadString('\n'); err != nil {
log.Panicln(err)
}
if strings.HasPrefix(
strings.ToLower(
strings.TrimSpace(
p,
),
),
"y",
) {
keys[keyNm] = struct{}{}
keyNms = append(keyNms, keyNm)
}
}
}
}
fmt.Println()
if keyNms == nil || len(keyNms) == 0 {
fmt.Printf("No keys selected for deletion on '%s'.\n", args.KillArgs.VaultTotpMnt)
os.Exit(0)
}
slices.Sort(keyNms)
if doGlobal {
fmt.Printf(
"Will delete the following TOTP keys on mount '%s':\n"+
"\t* %s"+
"\n",
args.KillArgs.VaultTotpMnt,
strings.Join(keyNms, "\n\t*"),
)
fmt.Println("Is this OK? (y/N)")
p = ""
if p, err = rdr.ReadString('\n'); err != nil {
log.Panicln(err)
}
fmt.Println()
if !strings.HasPrefix(
strings.ToLower(
strings.TrimSpace(
p,
),
),
"y",
) {
fmt.Println("Exiting.")
os.Exit(0)
}
}
for _, keyNm = range keys {
wg.Add(1)
go killKeyAsync(keyNm)
}
log.Println("Done.")
}