- 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.
77 lines
2.1 KiB
Go
77 lines
2.1 KiB
Go
// 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
|
|
}
|