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:
2026-08-14 11:09:03 +02:00
commit ae30ba1240
85 changed files with 9413 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
package auth
import (
"context"
"fmt"
"github.com/hashicorp/vault/api"
)
func init() { register(tokenMethod{}) }
// tokenMethod is the trivial "I already have a token" method: it validates
// the given token via lookup-self and returns a synthesized auth response so
// the normal Result/token-storage pipeline works unchanged. This is what
// backs `vault-tui login -method=token` and the VAULT_TOKEN/--token fast
// path that internal/token.Resolve prefers over any interactive login.
type tokenMethod struct{}
func (tokenMethod) Name() string { return "token" }
func (tokenMethod) DisplayName() string { return "Token" }
func (tokenMethod) DefaultMount() string { return "token" }
func (tokenMethod) Description() string {
return "Use an existing Vault token (from VAULT_TOKEN, --token, or a saved token file)."
}
func (tokenMethod) Fields() []Field {
return []Field{
{Name: "token", Label: "Token", Kind: FieldSecret, Required: true,
EnvFallback: []string{"VAULT_TOKEN"}},
}
}
func (tokenMethod) Login(ctx context.Context, c *api.Client, req Request) (*api.Secret, error) {
tok := req.Creds.Get("token")
if tok == "" {
return nil, fmt.Errorf("no token provided")
}
// lookup-self must run with the candidate token; c is otherwise
// unauthenticated at this point (see internal/vault.NewClient's
// ClearToken discipline), so this cannot affect any other caller.
c.SetToken(tok)
defer c.ClearToken()
sec, err := c.Logical().ReadWithContext(ctx, "auth/token/lookup-self")
if err != nil {
return nil, fmt.Errorf("validating token: %w", err)
}
if sec == nil || sec.Data == nil {
return nil, fmt.Errorf("token lookup returned no data")
}
renewable, _ := sec.TokenIsRenewable()
ttl, _ := sec.TokenTTL()
policies, _ := sec.TokenPolicies()
return &api.Secret{
Auth: &api.SecretAuth{
ClientToken: tok,
Renewable: renewable,
LeaseDuration: int(ttl.Seconds()),
Policies: policies,
},
}, nil
}