feat(vault-tui): implement KV client and service for managing secrets
- Added internal/vault/client.go for creating a Vault client with configuration settings. - Introduced internal/vault/errors.go to classify Vault API errors for better UI handling. - Created internal/vault/kv.go to manage KV secrets, including listing, reading, writing, and deleting operations. - Implemented internal/vault/mounts.go to list and describe secret engine mounts. - Developed internal/vault/service.go to provide a unified entry point for Vault operations. - Added internal/vault/kv_test.go for comprehensive testing of KV operations. - Introduced internal/ui/toast.go for transient notifications in the UI. - Added renovate.json for dependency management and updates.
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
package token
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"git.morlana.online/f.weber/vault-tui/internal/config"
|
||||
)
|
||||
|
||||
// Source identifies which layer a resolved token came from.
|
||||
type Source uint8
|
||||
|
||||
const (
|
||||
SourceNone Source = iota
|
||||
SourceFlag
|
||||
SourceEnv
|
||||
SourceConfig
|
||||
SourceStore
|
||||
)
|
||||
|
||||
func (s Source) String() string {
|
||||
switch s {
|
||||
case SourceFlag:
|
||||
return "flag"
|
||||
case SourceEnv:
|
||||
return "env"
|
||||
case SourceConfig:
|
||||
return "config"
|
||||
case SourceStore:
|
||||
return "store"
|
||||
default:
|
||||
return "none"
|
||||
}
|
||||
}
|
||||
|
||||
// Resolved is the outcome of Resolve: the token plus enough provenance for
|
||||
// the status bar to explain itself (a common source of confusion for any
|
||||
// tool that shadows the Vault CLI's own ~/.vault-token).
|
||||
//
|
||||
// String/GoString are overridden so an accidental %v/%+v never leaks the
|
||||
// token value into a log line.
|
||||
type Resolved struct {
|
||||
Token string
|
||||
Source Source
|
||||
Origin string // e.g. "VAULT_TOKEN", "~/.vault-token", "/usr/local/bin/vault-token-helper"
|
||||
}
|
||||
|
||||
func (r Resolved) String() string {
|
||||
if r.Token == "" {
|
||||
return "<no token>"
|
||||
}
|
||||
return "<token via " + r.Origin + ">"
|
||||
}
|
||||
|
||||
func (r Resolved) GoString() string { return r.String() }
|
||||
|
||||
// Options is the input to Resolve.
|
||||
type Options struct {
|
||||
Flag string // --token
|
||||
Env string // VAULT_TOKEN, pre-read by the caller
|
||||
Profile *config.Profile
|
||||
Store Store // resolved by internal/cli from profile.token.storage
|
||||
Getenv func(string) (string, bool)
|
||||
}
|
||||
|
||||
// Resolve applies the precedence: --token flag > VAULT_TOKEN env >
|
||||
// profile.token.value (discouraged) > the configured Store.
|
||||
func Resolve(ctx context.Context, o Options) (Resolved, error) {
|
||||
if v := strings.TrimSpace(o.Flag); v != "" {
|
||||
return Resolved{Token: v, Source: SourceFlag, Origin: "--token"}, nil
|
||||
}
|
||||
if v := strings.TrimSpace(o.Env); v != "" {
|
||||
return Resolved{Token: v, Source: SourceEnv, Origin: "VAULT_TOKEN"}, nil
|
||||
}
|
||||
if o.Profile != nil && o.Profile.Token.Value != "" {
|
||||
return Resolved{Token: o.Profile.Token.Value, Source: SourceConfig, Origin: "config token.value"}, nil
|
||||
}
|
||||
if o.Store != nil {
|
||||
tok, err := o.Store.Get(ctx)
|
||||
if err != nil {
|
||||
return Resolved{}, err
|
||||
}
|
||||
if tok != "" {
|
||||
return Resolved{Token: tok, Source: SourceStore, Origin: o.Store.Location()}, nil
|
||||
}
|
||||
}
|
||||
return Resolved{Source: SourceNone}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user