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,76 @@
|
||||
// Package vault wraps github.com/hashicorp/vault/api behind a small
|
||||
// Service that the UI and CLI layers talk to. Nothing in this package
|
||||
// imports a TUI toolkit, so it is fully unit-testable with httptest and
|
||||
// reusable by the headless commands in internal/cli.
|
||||
package vault
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/vault/api"
|
||||
|
||||
"git.morlana.online/f.weber/vault-tui/internal/config"
|
||||
)
|
||||
|
||||
// NewClient builds an *api.Client from a fully resolved config.Settings.
|
||||
//
|
||||
// api.DefaultConfig() already calls ReadEnvironment(), and api.NewClient
|
||||
// additionally picks up VAULT_TOKEN/VAULT_NAMESPACE/VAULT_HEADERS as soon as
|
||||
// it sees a *api.Config — all of which would bypass the flag>env>profile>
|
||||
// defaults precedence that config.Resolve already computed into s. So this
|
||||
// function overwrites every field env may have set, then explicitly clears
|
||||
// the token and re-sets the namespace from s: ClearToken()+SetNamespace()
|
||||
// right after NewClient is the load-bearing pair of calls here.
|
||||
func NewClient(s *config.Settings) (*api.Client, error) {
|
||||
cfg := api.DefaultConfig()
|
||||
if cfg.Error != nil {
|
||||
return nil, fmt.Errorf("building base client config: %w", cfg.Error)
|
||||
}
|
||||
|
||||
cfg.Address = s.Address
|
||||
cfg.Timeout = s.Timeout
|
||||
cfg.MaxRetries = s.MaxRetries
|
||||
if s.MinRetryWait > 0 {
|
||||
cfg.MinRetryWait = s.MinRetryWait
|
||||
}
|
||||
if s.MaxRetryWait > 0 {
|
||||
cfg.MaxRetryWait = s.MaxRetryWait
|
||||
}
|
||||
cfg.SRVLookup = s.SRVLookup
|
||||
cfg.DisableRedirects = s.DisableRedirects
|
||||
cfg.CloneHeaders = true
|
||||
|
||||
tls := &api.TLSConfig{
|
||||
CACert: s.CACert,
|
||||
CACertBytes: s.CACertPEM,
|
||||
CAPath: s.CAPath,
|
||||
ClientCert: s.ClientCert,
|
||||
ClientKey: s.ClientKey,
|
||||
TLSServerName: s.ServerName,
|
||||
Insecure: s.SkipVerify,
|
||||
}
|
||||
if err := cfg.ConfigureTLS(tls); err != nil {
|
||||
return nil, fmt.Errorf("configuring TLS: %w", err)
|
||||
}
|
||||
|
||||
c, err := api.NewClient(cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating vault client: %w", err)
|
||||
}
|
||||
|
||||
c.ClearToken()
|
||||
c.SetNamespace(s.Namespace)
|
||||
c.SetCloneHeaders(true)
|
||||
if len(s.Headers) > 0 {
|
||||
h := c.Headers()
|
||||
if h == nil {
|
||||
h = make(map[string][]string)
|
||||
}
|
||||
for k, v := range s.Headers {
|
||||
h.Set(k, v)
|
||||
}
|
||||
c.SetHeaders(h)
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
Reference in New Issue
Block a user