bifrost

package module
v1.1.4 Latest Latest
Warning

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

Go to latest
Published: Jul 5, 2023 License: MPL-2.0 Imports: 18 Imported by: 0

README

Bifrost

CI

My First CA

Bifrost is a minimal Certificate Authority that issues X.509 certificates meant for mTLS client authentication. Bifrost CA does not authenticate certificate signing requests before issuance. You must authorise or control access to Bifrost CA as needed.

Bifrost CA issues certificates signed by a private key and TLS X.509 certificate. A TLS reverse proxy can use the same certificate to authenticate clients and secure access to web applications. Bifrost identifies clients uniquely by mapping an ECDSA public key to a UUID deterministically. Client identity namespaces allow Bifrost to be natively multi-tenant.

Releases

Bifrost binaries are available on the releases page. Container images are on ghcr.io.

bifrost contains all binaries. Its intended for local development.

podman pull ghcr.io/realimage/bifrost

bifrost-ca contains the issuer binary. The image has the AWS Lambda Web Adapter extension installed.

podman pull ghcr.io/realimage/bifrost-ca

Identity

Bifrost UUIDs are UUIDv5 deterministically created from ECDSA public keys. The namespace UUID appended to the X and Y curve points (big-endian) from an ECDSA P256 public key hashed using SHA1 form the public key's UUID. A public key will always map to a UUID within a namespace.

In pseudo-code,

bifrostUUID = UUIDv5(sha1(NamespaceClientIdentity, PublicKey.X.Bytes() + PublicKey.Y.Bytes())

Components

bf (alpha)

bf is an interactive tool that generates Bifrost CA material. It uses [Charm Cloud] to store your key material securely in the cloud.

bfid

bfid prints the Bifrost UUID of a certificate, public key, or private key.

bouncer

bouncer is a simple mTLS reverse proxy suitable for local development. If client authentication succeeds, bouncer proxies the requests to the backend url. The client's TLS certificate is available in the x-amzn-request-context header.

Sample Request Context containing Client Certificate:

"requestContext": {
    "authentication": {
        "clientCert": {
            "clientCertPem": "-----BEGIN CERTIFICATE-----\nMIIEZTCCAk0CAQEwDQ...",
            "issuerDN": "C=IN,ST=Tamil Nadu,L=Chennai,O=Qube Cinema,OU=Qube Wire,CN=My Private CA",
            "serialNumber": "1",
            "subjectDN": "C=US,ST=Tamil Nadu,L=Chennai,O=Qube Cinema,OU=Qube Wire,CN=My Client",
            "validity": {
                "notAfter": "Aug  5 00:28:21 2120 GMT",
                "notBefore": "Aug 29 00:28:21 2020 GMT"
            }
        }
    },
}

Run bouncer in front of a HTTP server listening on localhost port 5000:

env BACKEND_URL=http://127.0.0.1:5000 ./bouncer
issuer

OpenAPI schema

issuer signs certificates with the configured certificate and its private key. Clients must send certificate requests signed by an ECDSA P256 private key using the ECDSA SHA256 signature algorithm.

issuer can read its signing certificate and private key in PEM form from a variety of sources. If unconfigured, it looks for crt.pem and key.pem in the current working directory.

The BF_NS environment variable sets the Bifrost Identifier Namespace to use. If unset, it defaults to bifrost.Namespace.

issuer exposes prometheus format metrics at the /metrics path.

Build

Go toolchain

Build Go binaries on your machine:

mkdir build
go build -o build ./...
Containers

issuer:

podman build -t ghcr.io/realimage/bifrost-ca --target=ca .

bifrost:

podman build -t gcr.io/realimage/bifrost .

Run Issuer CA

  1. Create ECDSA P256 Private Key in PEM format:

    openssl ecparam -out key.pem -name prime256v1 -genkey -noout

  2. Create 10 year self-signed certificate from the newly generated key:

    openssl req -new -key key.pem -x509 -nodes -days 3650 -out crt.pem

  3. Run the binary:

    ./issuer

  4. Generate a new client key and CSR, and get it signed by issuer:

    openssl ecparam -out clientkey.pem -name prime256v1 -genkey -noout

  5. Create a Certificate Signing Request using the new private key:

    openssl req -new -key clientkey.pem -sha256 -subj "/CN=$(./bfid clientkey.pem)" -out csr.pem

  6. Fetch signed certificate from the CA:

    curl -X POST -H "Content-Type: text/plain" --data-binary "@csr.pem" localhost:8888/issue >clientcrt.pem

  7. Admire your shiny new client certificate (optional):

    openssl x509 -in clientcrt.pem -noout -text

Fishy Benchmarks

A toy benchmark for your favourite toy CA.

my-first-benchmark.jpg

issuer issued 10,000 certificates on my Macbook Pro M1 Pro in ~41s. The slowest request completed in 12ms. With a mean response time of 4ms this is objectively the fastest CA on the planet. Statisticians hate this one weird trick.

LICENSE

Bifrost is available under the Mozilla Public License 2.0.

Qube Cinema © 2023

Documentation

Overview

Bifrost is an mTLS authentication toolkit.

Index

Examples

Constants

View Source
const (
	SignatureAlgorithm = x509.ECDSAWithSHA256
	PublicKeyAlgorithm = x509.ECDSA
)

Signature and Public Key Algorithms

Variables

View Source
var (
	ErrInvalidPublicKey     = errors.New("invalid public key")
	ErrUnsupportedAlgorithm = errors.New("unsupported algorithm")
	ErrWrongNamespace       = errors.New("wrong namespace")
)

Errors.

View Source
var Namespace = uuid.MustParse("1512daa4-ddc1-41d1-8673-3fd19d2f338d")

Namespace is the default UUID Namespace for Bifrost identities.

Functions

func FromContext added in v0.0.10

func FromContext(ctx context.Context) (uuid.UUID, *x509.Certificate)

FromContext returns the client's UUID and Certificate from the request context. The context must be from a request that has passed through Interceptor.

func HTTPClient added in v0.0.6

func HTTPClient(apiUrl string, clientCert *tls.Certificate) (*http.Client, error)

HTTPClient returns a HTTP client set up for mTLS with the provided api URL. The returned client will only send requests to the api URL host. The request path will be joined with the api URL path, if any. The client will use the provided TLS client certificate to identify itself.

func Interceptor added in v0.0.9

func Interceptor(next http.Handler) http.Handler

Interceptor returns a HTTP Handler middleware function that reads The x-amzn-request-context header and adds the client's UUID and certificate to the request context.

func NewIdentity added in v0.0.8

func NewIdentity() (*ecdsa.PrivateKey, []byte, error)

NewIdentity generates a new ECDSA private key. The private key is also returned as a PEM encoded DER bytes in the second return value.

func ParseCertificate

func ParseCertificate(der []byte) (uuid.UUID, *x509.Certificate, error)

ParseCertificate returns the UUID and certificate from an ASN.1 DER encoded certificate.

func RequestCertificate

func RequestCertificate(
	ctx context.Context,
	url string,
	ns uuid.UUID,
	key *ecdsa.PrivateKey,
) (*x509.Certificate, error)

RequestCertificate sends a certificate request to url and returns the signed certificate.

Example
exampleNS := uuid.MustParse("228b9676-998e-489a-8468-92d46a94a32d")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// TODO: handle errors
key, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
crt, _ := RequestCertificate(ctx, "https://bifrost-ca", exampleNS, key)
fmt.Println(crt.Subject)
Output:

func UUID

func UUID(ns uuid.UUID, pubkey *ecdsa.PublicKey) uuid.UUID

UUID returns a unique identifier derived from the namespace and the client's public key identity. The UUID is generated by SHA-1 hashing the namesapce UUID with the big endian bytes of the X and Y curve points from the public key.

func X509ToTLSCertificate

func X509ToTLSCertificate(crt *x509.Certificate, key *ecdsa.PrivateKey) *tls.Certificate

X509ToTLSCertificate puts an x509.Certificate inside a tls.Certificate.

Types

type Key added in v0.0.9

type Key string

Directories

Path Synopsis
cmd
bf
internal
cafiles
cafiles can fetch CA certificate and private key PEM files from many storage backends.
cafiles can fetch CA certificate and private key PEM files from many storage backends.
pkg
club
Package club provides middleware for use in HTTP API servers and gateways.
Package club provides middleware for use in HTTP API servers and gateways.
tinyca
Package tinyca implements a Certificate Authority that issues certificates for client authentication.
Package tinyca implements a Certificate Authority that issues certificates for client authentication.

Jump to

Keyboard shortcuts

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