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,110 @@
|
||||
//go:build cloud
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/vault/api"
|
||||
awsauth "github.com/hashicorp/vault/api/auth/aws"
|
||||
azureauth "github.com/hashicorp/vault/api/auth/azure"
|
||||
gcpauth "github.com/hashicorp/vault/api/auth/gcp"
|
||||
)
|
||||
|
||||
// Cloud auth methods (AWS/Azure/GCP) are gated behind the `cloud` build
|
||||
// tag: their SDKs transitively pull in tens of MB of dependencies
|
||||
// (aws-sdk-go, google.golang.org/api, the Azure SDK) that a typical
|
||||
// OIDC/userpass/LDAP-only deployment never needs. Build with `-tags cloud`
|
||||
// to include them; see m_cloud_stub.go for the default (excluded) build,
|
||||
// which lists these names in the picker greyed out with a reason instead
|
||||
// of letting them silently vanish.
|
||||
func init() {
|
||||
register(awsMethod{}, azureMethod{}, gcpMethod{})
|
||||
}
|
||||
|
||||
type awsMethod struct{}
|
||||
|
||||
func (awsMethod) Name() string { return "aws" }
|
||||
func (awsMethod) DisplayName() string { return "AWS" }
|
||||
func (awsMethod) DefaultMount() string { return "aws" }
|
||||
|
||||
func (awsMethod) Fields() []Field {
|
||||
return []Field{
|
||||
{Name: "role", Label: "Role", Kind: FieldText, Required: true, EnvFallback: []string{"VAULT_AUTH_AWS_ROLE"}},
|
||||
{Name: "type", Label: "Auth type", Kind: FieldSelect, Options: []string{"iam", "ec2"}, Default: "iam"},
|
||||
{Name: "region", Label: "AWS region (optional)", Kind: FieldText},
|
||||
}
|
||||
}
|
||||
|
||||
func (awsMethod) Login(ctx context.Context, c *api.Client, req Request) (*api.Secret, error) {
|
||||
opts := []awsauth.LoginOption{awsauth.WithMountPath(mountOf(req, "aws"))}
|
||||
if r := req.Creds.Get("role"); r != "" {
|
||||
opts = append(opts, awsauth.WithRole(r))
|
||||
}
|
||||
if r := req.Creds.Get("region"); r != "" {
|
||||
opts = append(opts, awsauth.WithRegion(r))
|
||||
}
|
||||
if req.Creds.Get("type") == "ec2" {
|
||||
opts = append(opts, awsauth.WithEC2Auth())
|
||||
} else {
|
||||
opts = append(opts, awsauth.WithIAMAuth())
|
||||
}
|
||||
a, err := awsauth.NewAWSAuth(opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return a.Login(ctx, c)
|
||||
}
|
||||
|
||||
type azureMethod struct{}
|
||||
|
||||
func (azureMethod) Name() string { return "azure" }
|
||||
func (azureMethod) DisplayName() string { return "Azure" }
|
||||
func (azureMethod) DefaultMount() string { return "azure" }
|
||||
|
||||
func (azureMethod) Fields() []Field {
|
||||
return []Field{
|
||||
{Name: "role", Label: "Role", Kind: FieldText, Required: true, EnvFallback: []string{"VAULT_AUTH_AZURE_ROLE"}},
|
||||
{Name: "resource", Label: "Resource URL (optional)", Kind: FieldText},
|
||||
}
|
||||
}
|
||||
|
||||
func (azureMethod) Login(ctx context.Context, c *api.Client, req Request) (*api.Secret, error) {
|
||||
opts := []azureauth.LoginOption{azureauth.WithMountPath(mountOf(req, "azure"))}
|
||||
if r := req.Creds.Get("resource"); r != "" {
|
||||
opts = append(opts, azureauth.WithResource(r))
|
||||
}
|
||||
a, err := azureauth.NewAzureAuth(req.Creds.Get("role"), opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return a.Login(ctx, c)
|
||||
}
|
||||
|
||||
type gcpMethod struct{}
|
||||
|
||||
func (gcpMethod) Name() string { return "gcp" }
|
||||
func (gcpMethod) DisplayName() string { return "GCP" }
|
||||
func (gcpMethod) DefaultMount() string { return "gcp" }
|
||||
|
||||
func (gcpMethod) Fields() []Field {
|
||||
return []Field{
|
||||
{Name: "role", Label: "Role", Kind: FieldText, Required: true, EnvFallback: []string{"VAULT_AUTH_GCP_ROLE"}},
|
||||
{Name: "type", Label: "Auth type", Kind: FieldSelect, Options: []string{"iam", "gce"}, Default: "iam"},
|
||||
{Name: "service_account", Label: "Service account email (iam only)", Kind: FieldText},
|
||||
}
|
||||
}
|
||||
|
||||
func (gcpMethod) Login(ctx context.Context, c *api.Client, req Request) (*api.Secret, error) {
|
||||
opts := []gcpauth.LoginOption{gcpauth.WithMountPath(mountOf(req, "gcp"))}
|
||||
if req.Creds.Get("type") == "gce" {
|
||||
opts = append(opts, gcpauth.WithGCEAuth())
|
||||
} else {
|
||||
opts = append(opts, gcpauth.WithIAMAuth(req.Creds.Get("service_account")))
|
||||
}
|
||||
a, err := gcpauth.NewGCPAuth(req.Creds.Get("role"), opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return a.Login(ctx, c)
|
||||
}
|
||||
Reference in New Issue
Block a user