README
¶
Teamvault Utils
A Go library and CLI tools for interacting with TeamVault secret management system. Provides type-safe access to passwords, usernames, URLs, and files stored in TeamVault, with support for template parsing and configuration generation.
Features
- Type-Safe API: Strongly typed interfaces for accessing TeamVault secrets
- Multiple Connectors: Remote, cache, disk fallback, and dummy connectors
- Template Parsing: Parse configuration templates with TeamVault placeholders
- Config Generation: Generate configuration files from templates
- CLI Tools: Command-line utilities for quick secret access
- Dependency Injection: Clean architecture with testable components
- Setup (macOS, recommended)
- Installation
- Quick Start
- Library Usage
- API Documentation
- CLI Tools
- Development
- Testing
- License
Setup (macOS, recommended)
On macOS, store your TeamVault password in the login Keychain so it never needs to appear in a plaintext config file:
-
Create a config file with only
urlanduser— leave outpass:{ "url": "https://teamvault.example.com", "user": "my-user" } -
Run
teamvault loginonce to verify your credentials and store the password in the Keychain:teamvault login --teamvault-config ~/.teamvault.jsonThe command prompts for your TeamVault password (hidden), verifies it against the API, and writes it to the macOS login Keychain on success.
Multi-vault setup: repeat for each config file:
teamvault login --teamvault-config ~/.teamvault.json
teamvault login --teamvault-config ~/.teamvault-sm.json
Removing a stored password:
security delete-generic-password -s teamvault-utils -a https://teamvault.example.com
Note: Putting
passdirectly in the config file still works (the legacy path), but the password is stored in plaintext on disk. The Keychain path is strongly preferred on macOS.
Non-macOS:
teamvault loginverifies credentials but does not persist them. Users on Linux/Windows should continue to supply the password via flag, environment variable, or config file for now.
Installation
Install the teamvault CLI:
go install github.com/bborbe/teamvault-utils/v5@latest
Add the library to a Go project:
go get github.com/bborbe/teamvault-utils/v5/pkg/teamvault
Quick Start
package main
import (
"context"
"fmt"
"net/http"
teamvault "github.com/bborbe/teamvault-utils/v5/pkg/teamvault"
libtime "github.com/bborbe/time"
)
func main() {
ctx := context.Background()
// Create a connector
connector := teamvault.NewRemoteConnector(
http.DefaultClient,
teamvault.Url("https://teamvault.example.com"),
teamvault.User("my-user"),
teamvault.Password("my-pass"),
libtime.NewCurrentDateTime(),
)
// Retrieve a password
password, err := connector.Password(ctx, teamvault.Key("vLVLbm"))
if err != nil {
panic(err)
}
fmt.Printf("Password: %s\n", password)
}
Library Usage
Using the Connector Interface
The Connector interface provides access to TeamVault secrets:
import (
"context"
"net/http"
teamvault "github.com/bborbe/teamvault-utils/v5/pkg/teamvault"
libtime "github.com/bborbe/time"
)
func example() {
ctx := context.Background()
connector := teamvault.NewRemoteConnector(
http.DefaultClient,
teamvault.Url("https://teamvault.example.com"),
teamvault.User("my-user"),
teamvault.Password("my-pass"),
libtime.NewCurrentDateTime(),
)
// Get password
password, err := connector.Password(ctx, teamvault.Key("abc123"))
if err != nil {
// handle error
}
// Get username
user, err := connector.User(ctx, teamvault.Key("abc123"))
if err != nil {
// handle error
}
// Get URL
url, err := connector.Url(ctx, teamvault.Key("abc123"))
if err != nil {
// handle error
}
// Get file
file, err := connector.File(ctx, teamvault.Key("abc123"))
if err != nil {
// handle error
}
// Search for secrets
keys, err := connector.Search(ctx, "database")
if err != nil {
// handle error
}
}
Template Parsing with ConfigParser
Parse configuration templates containing TeamVault placeholders:
import (
"context"
teamvault "github.com/bborbe/teamvault-utils/v5/pkg/teamvault"
)
func parseConfig(connector teamvault.Connector) {
ctx := context.Background()
parser := teamvault.NewConfigParser(connector)
template := []byte(`
database:
username: {{ "vLVLbm" | teamvaultUser }}
password: {{ "vLVLbm" | teamvaultPassword }}
url: {{ "vLVLbm" | teamvaultUrl }}
`)
result, err := parser.Parse(ctx, template)
if err != nil {
// handle error
}
// result now contains resolved values
}
Using Different Connector Types
Cache Connector (for performance):
connector := teamvault.NewCacheConnector(
teamvault.NewRemoteConnector(
http.DefaultClient,
teamvault.Url("https://teamvault.example.com"),
teamvault.User("my-user"),
teamvault.Password("my-pass"),
libtime.NewCurrentDateTime(),
),
)
Disk Fallback Connector (for reliability):
connector := teamvault.NewDiskFallbackConnector(
teamvault.NewRemoteConnector(
http.DefaultClient,
teamvault.Url("https://teamvault.example.com"),
teamvault.User("my-user"),
teamvault.Password("my-pass"),
libtime.NewCurrentDateTime(),
),
)
Dummy Connector (for testing):
connector := teamvault.NewDummyConnector()
Creating Connectors with Factory
Use the factory package for simplified connector creation:
import (
"context"
"net/http"
teamvault "github.com/bborbe/teamvault-utils/v5/pkg/teamvault"
"github.com/bborbe/teamvault-utils/v5/pkg/factory"
libtime "github.com/bborbe/time"
)
func createConnector() (teamvault.Connector, error) {
ctx := context.Background()
httpClient, err := factory.CreateHttpClient(ctx)
if err != nil {
return nil, err
}
connector, err := factory.CreateConnectorWithConfig(
ctx,
httpClient,
teamvault.TeamvaultConfigPath("~/.teamvault.json"),
teamvault.Url(""),
teamvault.User(""),
teamvault.Password(""),
teamvault.Staging(false),
true, // enable cache
libtime.NewCurrentDateTime(),
)
if err != nil {
return nil, err
}
return connector, nil
}
API Documentation
For complete API documentation, visit pkg.go.dev.
CLI Tools
The library ships a single teamvault command with subcommands for quick secret access.
Common flags
All teamvault subcommands accept these persistent flags:
--teamvault-timeout=5s HTTP request timeout for TeamVault API calls (env: TEAMVAULT_TIMEOUT; default: 5s)
--cache Enable disk-fallback cache (env: CACHE)
Cache behavior: Cache is enabled if EITHER the --cache / CACHE env var is true OR the config file's cacheEnabled: true is set. There is no way to force-disable via CLI when the config opts in; edit the config file to disable.
Teamvault Login
Verify TeamVault credentials and store the password in the macOS Keychain. Recommended first step on macOS — see Setup (macOS, recommended) for the full flow.
Install:
go install github.com/bborbe/teamvault-utils/v5@latest
Run:
teamvault login --teamvault-config ~/.teamvault.json
The command prompts for your TeamVault password (hidden input), verifies it against the API, and on success stores it in the macOS login Keychain. On non-macOS platforms it verifies only — no Keychain write.
Teamvault Get Password
Install:
go install github.com/bborbe/teamvault-utils/v5@latest
Run:
teamvault password \
--teamvault-config ~/.teamvault.json \
--teamvault-key vLVLbm
The resolved password is printed to stdout with no trailing newline, so it can be piped directly into tools like curl -u without corrupting basic-auth credentials.
Teamvault Get Username
Install:
go install github.com/bborbe/teamvault-utils/v5@latest
Run:
teamvault username \
--teamvault-config ~/.teamvault.json \
--teamvault-key vLVLbm
Teamvault Get URL
Install:
go install github.com/bborbe/teamvault-utils/v5@latest
Run:
teamvault url \
--teamvault-config ~/.teamvault.json \
--teamvault-key vLVLbm
Teamvault Get File
Install:
go install github.com/bborbe/teamvault-utils/v5@latest
Run:
teamvault file \
--teamvault-config ~/.teamvault.json \
--teamvault-key vLVLbm
Parse Config with Teamvault Secrets
Reads a template from stdin and writes the resolved config to stdout.
Install:
go install github.com/bborbe/teamvault-utils/v5@latest
Sample config template:
foo=bar
username={{ "vLVLbm" | teamvaultUser }}
password={{ "vLVLbm" | teamvaultPassword }}
url={{ "vLVLbm" | teamvaultUrl }}
Run:
cat my.config | teamvault config parse \
--teamvault-config ~/.teamvault.json \
--logtostderr \
-v=2
Generate Config Directory from Templates
Install:
go install github.com/bborbe/teamvault-utils/v5@latest
TeamVault config file (~/.teamvault.json):
{
"url": "https://teamvault.example.com",
"user": "my-user",
"pass": "my-pass",
"cacheEnabled": true,
"timeout": "30s"
}
cacheEnabled: true enables disk-fallback caching. timeout sets the HTTP request timeout (default: 5 seconds when absent).
Run:
teamvault config generate \
--teamvault-config ~/.teamvault.json \
--source-dir templates \
--target-dir results \
--logtostderr \
-v=2
Development
Running Tests
make test
Code Generation (Mocks)
make generate
Full Development Workflow
make precommit # Format, test, lint, and check
Full Example
Here's a complete, runnable example demonstrating real-world usage patterns combining multiple features:
package main
import (
"context"
"fmt"
"net/http"
"os"
teamvault "github.com/bborbe/teamvault-utils/v5/pkg/teamvault"
libtime "github.com/bborbe/time"
)
func main() {
ctx := context.Background()
// Create a cached connector for better performance
// The cache connector wraps the remote connector and caches responses
connector := teamvault.NewCacheConnector(
teamvault.NewRemoteConnector(
http.DefaultClient,
teamvault.Url("https://teamvault.example.com"),
teamvault.User("my-user"),
teamvault.Password("my-pass"),
libtime.NewCurrentDateTime(),
),
)
// Example 1: Retrieve individual secrets
password, err := connector.Password(ctx, teamvault.Key("vLVLbm"))
if err != nil {
fmt.Fprintf(os.Stderr, "Error getting password: %v\n", err)
os.Exit(1)
}
fmt.Printf("Retrieved password (length: %d)\n", len(password.String()))
user, err := connector.User(ctx, teamvault.Key("vLVLbm"))
if err != nil {
fmt.Fprintf(os.Stderr, "Error getting user: %v\n", err)
os.Exit(1)
}
fmt.Printf("Retrieved user: %s\n", user.String())
// Example 2: Parse a configuration template
parser := teamvault.NewConfigParser(connector)
configTemplate := []byte(`
# Database Configuration
database:
host: {{ "vLVLbm" | teamvaultUrl }}
username: {{ "vLVLbm" | teamvaultUser }}
password: {{ "vLVLbm" | teamvaultPassword }}
# Application Settings
app:
environment: {{ "production" | env }}
debug: false
`)
result, err := parser.Parse(ctx, configTemplate)
if err != nil {
fmt.Fprintf(os.Stderr, "Error parsing config: %v\n", err)
os.Exit(1)
}
fmt.Println("\nGenerated Configuration:")
fmt.Println(string(result))
// Example 3: Generate configuration files from templates
generator := teamvault.NewConfigGenerator(parser)
err = generator.Generate(
ctx,
teamvault.SourceDirectory("./templates"),
teamvault.TargetDirectory("./config"),
)
if err != nil {
fmt.Fprintf(os.Stderr, "Error generating configs: %v\n", err)
os.Exit(1)
}
fmt.Println("\nConfiguration files generated successfully!")
}
This example demonstrates:
- Creating a cached connector for performance optimization
- Retrieving individual secrets (password, user)
- Parsing configuration templates with TeamVault placeholders
- Generating multiple configuration files from a template directory
Testing
Testing code that uses this library is straightforward using the mock connector or dummy connector:
import (
"context"
"testing"
teamvault "github.com/bborbe/teamvault-utils/v5/pkg/teamvault"
"github.com/bborbe/teamvault-utils/v5/mocks"
)
func TestYourCode(t *testing.T) {
ctx := context.Background()
// Use mock connector for testing
mockConnector := &mocks.Connector{}
mockConnector.PasswordReturns(teamvault.Password("test-password"), nil)
// Test your code with the mock
result, err := mockConnector.Password(ctx, teamvault.Key("test-key"))
if err != nil {
t.Fatal(err)
}
if result != "test-password" {
t.Errorf("expected test-password, got %s", result)
}
}
func TestWithDummyConnector(t *testing.T) {
// Or use dummy connector for simple tests
connector := teamvault.NewDummyConnector()
// Test your code with dummy connector
}
License
This project is licensed under the BSD-style license. See the LICENSE file for details.
Documentation
¶
There is no documentation for this package.
Directories
¶
| Path | Synopsis |
|---|---|
|
Code generated by counterfeiter.
|
Code generated by counterfeiter. |
|
pkg
|
|
|
cli
Package cli provides the command-line interface for the teamvault utility.
|
Package cli provides the command-line interface for the teamvault utility. |
|
factory
Package factory provides factory functions for creating TeamVault connectors and HTTP clients.
|
Package factory provides factory functions for creating TeamVault connectors and HTTP clients. |
|
teamvault
Package teamvault provides utilities for accessing and managing TeamVault secrets.
|
Package teamvault provides utilities for accessing and managing TeamVault secrets. |