locket

package module
v0.6.1 Latest Latest
Warning

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

Go to latest
Published: Mar 16, 2025 License: MIT Imports: 25 Imported by: 0

README

🔐 locket ❤️

Go - Test

secrets management service

Purpose

Locket is a secrets cache for production services. It stores secrets in memory, loaded from external secrets cache, environment, or .env file as source. Why? Because the 1password GUI is great for business use, but the sacntioned 1password cache was flaky, and I wanted a go based soluton that abstracts away secret origin while providing tight access control and integration with existing deployment.

Overview

sequenceDiagram
    autonumber

    box rgb(0, 40, 0) External 
    participant CI
    participant source
    end

    box rgb(40, 0, 0) Locket Server
    participant secrets
    participant registry
    participant handler
    end

    box rgb(0, 0, 40) Locket Client
    participant client
    end

    activate CI
    CI->>registry: public signing keys
    CI->>client: private signing key
    CI->>secrets: source access key (or source files)
    note over CI: depoy complete
    deactivate CI

    secrets->>source: request all secrets
    activate secrets
    source->>secrets: all secrets
    note over secrets: server init complete
    deactivate secrets

    client->>handler: GET - public key
    activate client
    handler->>client: server public encryption key
    note over client: client init complete
    deactivate client

    client->>handler: GET - public key
    activate client
    handler->>client: server public encryption key
    client->>handler: POST - secret (encrypted & signed)
    handler->>registry: authenticate signing key
    activate handler
    registry->>handler: verify identity
    note over handler: auth & access control
    handler--x client: forbidden
    deactivate handler
    handler->>secrets: request secret
    secrets->>handler: secret value
    handler-->>client: encrypted secret
    note over client: secret fetched
    deactivate client
1-3 Deploy

Create registry and distribute signing keys.

4-5 Init Server

Load secrets using any struct that satisfies the source interface.

struct source
env local environment
dotenv .env file
onepass 1password server
6-7 Init Client

Fetch server public encryption key.

8-9 Refetch public encryption key

Server may generate a new public key upon restart. No caching is currently implemented. 🤷

10-12 Enforce Access Control
  • clients must encrypt and sign every request
  • clients can only requeest their own secrets
13-15 Fetch & Return Secret
  • responses are encrypted

Examples

See tests for examples, and checkout docstings for extensive descriptions.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ClientSigningPubkey is the environment variable name for
	// the client's signing public key. The sever should already have this
	// via side channel before the client makes a request, and uses this
	// to verify the authenticity of the requestor.
	// In testing, this is set to the client's signing public key.
	ClientSigningPubkey = "LOCKET_CLIENT_PUBKEY_SIGNING"
)
View Source
var Defaults = defaults{
	AllowCird:  "10.0.0.0/24",
	BitsizeRSA: 2048,
}
View Source
var OnePasswordVar = "LOCKET_OP_SERVICE_ACCOUNT_TOKEN"

1password service account token environment variable name

Functions

func Bootstrap added in v0.0.2

func Bootstrap(serviceSecrets map[string][]string) ([]RegEntry, KeysPrivateSigning, error)

Bootstrap generates a new signing key pair for each service in the provided list. Public keys are added to a registry (expected to be written to file), and private keys are returned in a map (expected to be provided to clients upon deploy).

func NewPairEd25519

func NewPairEd25519() (string, string, error)

NewPairEd25519 generates a new Ed25519 key pair used to authenticate clients requests to the server.

func WriteRegistry

func WriteRegistry(path string, data []RegEntry) error

WriteRegistry creates a yaml file with a registry of allowed clients.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client makes reqeuests to a locket server, and must know the server address. serverPubkey is the server's encryption public key, and will be fetched on creation of NewClient(). Rsa and Ed25519 key pairs are also generated on creation of NewClient().

func NewClient

func NewClient(serverURL, keyPub, keyPriv string) (*Client, error)

NewClient creates a new client, fetches the server's encryption public key, and generates RSA key pairs for encrypting k/v secret requests.

Pre-computed ed25519 signing keys (via NewPairEd25519() or any other means) must be passed to a new client, with the expectation that the public key be made available to the server to facilitate authentication. see: WriteRegistry() for details

type Dotenv added in v0.0.2

type Dotenv struct {
	Path           string              // path to .env file to read
	ServiceSecrets map[string][]string // service names and a list of their secrets
}

func (Dotenv) Load added in v0.2.1

func (d Dotenv) Load() (map[string]Secrets, error)

Load k=v pairs from a .env file, ignoring any #comments.

type Env added in v0.2.1

type Env struct {
	ServiceSecrets map[string][]string
}

Env satisfies the source interface, loading secrets from the local environment.

func (Env) Load added in v0.2.1

func (e Env) Load() (map[string]Secrets, error)

Load k=v pairs from local environment.

Expect environment variables to be prefixed with the service name.

type KeysPrivateSigning added in v0.2.0

type KeysPrivateSigning map[string]string

map[serviceName]keyPrivateSigning

type Onepass added in v0.0.2

type Onepass struct {
	Vault string // name of the vault containig service secrets
}

Onepass satisfies the source interface, loading secrets from a 1password vault over the net with 1password API. Service account token must be set environment as locket.OnePasswordVar.

func (Onepass) Load added in v0.2.1

func (o Onepass) Load() (map[string]Secrets, error)

Load all service secrets from a named 1password vault, returning a map of service names to their set of k/v secrets.

type RegEntry

type RegEntry struct {
	Name   string `yaml:"name"`
	KeyPub string `yaml:"keypub"`
}

RegEntry is a single registry item, representing a single client which the server should recognize and authorize

func ReadRegistryBytes added in v0.3.0

func ReadRegistryBytes(bytes []byte) ([]RegEntry, error)

ReadRegistryBytes turns a byte slice into a list of RegEntry for use in server authenticating client requests. Bytes format easier for embed.FS

func ReadRegistryFile added in v0.3.0

func ReadRegistryFile(filepath string) ([]RegEntry, error)

ReadRegistryFile turns a yaml file into a list of RegEntry for use in server authenticating client requests.

type Secrets added in v0.0.2

type Secrets map[string]string // all key/value secrets for a single service

type Server

type Server struct {
	// contains filtered or unexported fields
}

func NewServer

func NewServer(opts source, registry []RegEntry) (*Server, error)

NewServer sets up a new secrets server when provided source options and registry of allowed services (and their public signing keys), expected to be read from file or embed before calling NewServer().

func (*Server) Handler

func (s *Server) Handler(w http.ResponseWriter, r *http.Request)

Jump to

Keyboard shortcuts

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