connector

package module
v0.0.0-...-0b3e5f9 Latest Latest
Warning

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

Go to latest
Published: Dec 10, 2023 License: MIT Imports: 4 Imported by: 1

README

pg-secrets-driver

Build

A Postgres database driver that supports credential rotation.

Getting Started

The following example demonstrates a simple CredentialsProvider implementation, configured with a fixed list of passwords. The implementation cycles though the fixed list of passwords, trying each in turn, until it is able to establish a connection successfully.

In actual usage, it is likely that a CredentialsProvider implementation would source the dynamic components of the data source name (e.g. the password) from either the environment of the process or a service such as AWS SecretsManager or HashiCorp Vault.

package main

import (
	"database/sql"
	conn "github.com/progbits/pg-secrets-driver"
	"log"
	"net/url"
)

type TestCredentialsProvider struct {
	count     int
	passwords []string
}

func (p *TestCredentialsProvider) GetDataSourceName() (string, error) {
	withPassword := func(password string) string {
		dsn, _ := url.Parse("postgresql://localhost/postgres")
		query := dsn.Query()
		query.Add("user", "postgres")
		query.Add("password", password)
		query.Add("sslmode", "disable")
		dsn.RawQuery = query.Encode()
		return dsn.String()
	}

	password := p.passwords[p.count]
	p.count++

	fmt.Printf("Returning data source name with password: %s\n", password)

	return withPassword(password), nil
}

func (p *TestCredentialsProvider) Retries() int {
	return len(p.passwords)
}

func main() {
	passwords := []string{"foo", "bar", "baz", "password", "pa$$w0rd", "p@ssw0rd"}
	provider := &TestCredentialsProvider{
		passwords: passwords,
	}
	connector := conn.NewPgSecretsConnector(provider)

	db := sql.OpenDB(connector)
	_, err := db.Exec("SELECT 1")
	if err != nil {
		log.Print(err)
	}
}

The example code above can be found in the example directory.

To run the example, start a new Postgres instance with the superuser password pa$$w0rd, the 5th value in the list held by TestCredentialsProvider:

docker run -e 'POSTGRES_PASSWORD=pa$$w0rd' -d -p 5432:5432 postgres:14.3

The example can then be run using make:

make run-example

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CredentialsProvider

type CredentialsProvider interface {
	GetDataSourceName() (string, error)
	Retries() int
}

CredentialsProvider implementations are a source of Postgres data source names, where a data source name is a valid Postgres connection string (https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING).

The GetDataSourceName method is called each time a new database connection is required, e.g. each time the PgSecretsConnector.Connect method is called. If the PgSecretsConnector.Connect method fails with `invalid_password`, the GetDataSourceName method is called a further n times, where n is determined by the result of the Retries method. This presents an opportunity to attempt to connect with different sets of credentials, e.g. rotated_current and rotated_previous.

type PgSecretsConnector

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

PgSecretsConnector is the main library type and implements the driver.Connector interface. This means it can be passed to the sql.OpenDB method as a source of database connections. The connection string used to open a new database connection is sourced from the configured CredentialsProvider implementation.

func NewPgSecretsConnector

func NewPgSecretsConnector(provider CredentialsProvider) *PgSecretsConnector

func (*PgSecretsConnector) Connect

func (c *PgSecretsConnector) Connect(ctx context.Context) (driver.Conn, error)

func (*PgSecretsConnector) Driver

func (c *PgSecretsConnector) Driver() driver.Driver

Driver returns the underlying driver of the connector.

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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