teamvault-utils

command module
v5.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 9, 2026 License: BSD-2-Clause Imports: 1 Imported by: 0

README

Teamvault Utils

Go Reference CI Go Report Card

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


On macOS, store your TeamVault password in the login Keychain so it never needs to appear in a plaintext config file:

  1. Create a config file with only url and user — leave out pass:

    {
        "url": "https://teamvault.example.com",
        "user": "my-user"
    }
    
  2. Run teamvault login once to verify your credentials and store the password in the Keychain:

    teamvault login --teamvault-config ~/.teamvault.json
    

    The 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 pass directly 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 login verifies 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

The Go Gopher

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL