certstore

package module
v0.0.0-...-b886760 Latest Latest
Warning

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

Go to latest
Published: Aug 19, 2026 License: MIT Imports: 17 Imported by: 0

README

caddy-certstore

codecov Tests

A Caddy v2 HTTP reverse proxy transport module that enables client certificate authentication using certificates from OS certificate stores (macOS Keychain and Windows Certificate Store) for mTLS connections to upstream servers.

Overview

This module extends Caddy's reverse proxy HTTP transport to support client certificate authentication using certificates stored in your operating system's native certificate store. This is particularly useful in enterprise environments where client certificates are managed centrally through the OS certificate infrastructure.

Supported Platforms:

  • macOS: Loads certificates from Keychain (System and Login keychains)
  • Windows: Loads certificates from Certificate Store (LocalMachine and CurrentUser stores)

Installation

CGO_ENABLED=1 xcaddy build --with github.com/hurricanehrndz/caddy-certstore

Configuration

The module uses the ID http.reverse_proxy.transport.certstore and can be configured in your Caddyfile or JSON config.

JSON Configuration
{
  "apps": {
    "http": {
      "servers": {
        "srv0": {
          "routes": [
            {
              "handle": [
                {
                  "handler": "reverse_proxy",
                  "transport": {
                    "protocol": "certstore",
                    "client_certificate": {
                      "pattern": "client.example.com",
                      "location": "user"
                    }
                  },
                  "upstreams": [
                    {
                      "dial": "upstream.example.com:443"
                    }
                  ]
                }
              ]
            }
          ]
        }
      }
    }
  }
}
Caddyfile Configuration
example.com {
    reverse_proxy https://upstream.example.com {
        transport certstore {
            client_certificate {
                pattern client.example.com
                location user
            }
        }
    }
}
Certificate Selector Options

The client_certificate object supports the following fields:

  • name (required): Common name or regex pattern of the certificate to load
    • Exact match: "client.example.com"
    • Regex pattern: "client\\..*\\.com" (automatically detected by presence of regex metacharacters)
  • location (optional): Certificate store location
    • macOS: "system" or "user" (searches both automatically)
    • Windows: "machine" or "user" (maps to LocalMachine or CurrentUser)
    • Default: "system"
Regex Pattern Support

The module automatically detects regex patterns by checking for metacharacters (*, +, ?, ^, $, (), [], {}, |, \). When detected, the pattern is compiled and used for matching against certificate common names.

Examples:

  • "^client-.*\\.example\\.com$" - Matches any client certificate under example.com
  • "test\\..*" - Matches any certificate starting with "test."
  • "*.example.com" - Wildcard pattern

Features

  • Native OS Integration: Uses platform-specific certificate APIs via tailscale/certstore
  • mTLS Support: Enables mutual TLS authentication to upstream servers
  • Automatic Cleanup: Properly releases certificate store resources
  • Regex Matching: Flexible certificate selection using regex patterns
  • Structured Logging: Logs certificate details when loaded (common name, issuer, serial number, location)
  • Zero-Config Keychain: macOS automatically searches both system and user keychains

How It Works

  1. During Caddy's provision phase, the module:

    • Validates that a certificate name is specified
    • Detects and compiles regex patterns if present
    • Opens the OS certificate store (read-only)
    • Searches for matching certificate identity
    • Loads the certificate and private key
    • Configures the HTTP transport's TLS client config
  2. When making requests to upstream servers:

    • Caddy's reverse proxy uses the configured client certificate
    • The certificate and private key are presented during TLS handshake
    • Upstream server validates the client certificate (mTLS)
  3. On shutdown:

    • Certificate store resources are properly closed
    • Identity handles are released

Logging

When a certificate is successfully loaded, the module logs an informational message:

{
  "level": "info",
  "msg": "loaded client certificate from OS certificate store",
  "common_name": "client.example.com",
  "issuer": "Example CA",
  "serial_number": "123456789",
  "location": "user"
}

This helps verify which certificate was selected during provisioning.

Testing

Comprehensive test suite covering unit tests and platform-specific integration tests. See TEST_README.md for detailed testing instructions.

Quick Start:

# Run all tests (macOS/Windows)
make test

Development

Requirements:

  • Go 1.21+
  • macOS or Windows for integration testing

Build:

make caddy

Lint:

make lint

Format:

make format

Use Cases

  • Enterprise mTLS: Use corporate-managed client certificates stored in OS certificate stores
  • Zero-Touch Configuration: Certificates provisioned via MDM/Group Policy work automatically
  • Certificate Rotation: OS-managed certificates can be updated without modifying Caddy config
  • Simplified Management: No need to manage PEM files or certificate paths in configuration

Breaking Changes from Previous Versions

If upgrading from a previous version that used CertificateLoader interface:

  • Module ID changed: tls.certificates.load_certstore → http.reverse_proxy.transport.certstore
  • Configuration structure changed to support reverse proxy transport
  • JSON field renamed: client_certificate_match → client_certificate
  • Type renamed: Matcher → CertSelector (internal, not visible in config)

License

See LICENSE file for details.

Contributing

Contributions are welcome! Please ensure all tests pass and code is properly formatted before submitting PRs.

Acknowledgments

Documentation

Overview

Package certstore provides a Caddy v2 HTTP transport module that enables client certificate authentication using certificates from OS certificate stores (macOS Keychain and Windows Certificate Store) for mTLS connections to upstream servers.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CertSelector

type CertSelector struct {
	// Pattern is the regex pattern to match against the certificate field.
	// Required. Use anchors (^, $) for exact matches, e.g., "^exact\.match$"
	Pattern string `json:"pattern"`

	// Field specifies which certificate field to match against.
	// Valid values: "subject" (default), "issuer", "serial", "dns_names"
	Field string `json:"field,omitempty"`

	// Location specifies which certificate store to use.
	// On Windows: "user" (CurrentUser) or "machine" (LocalMachine)
	// On macOS: "user" or "system" (no effect - Keychain searches both automatically)
	Location string `json:"location,omitempty"`
	// contains filtered or unexported fields
}

CertSelector specifies criteria for selecting a certificate from the store.

func (*CertSelector) UnmarshalCaddyfile

func (cs *CertSelector) UnmarshalCaddyfile(d *caddyfile.Dispenser) error

type HTTPTransport

type HTTPTransport struct {
	// Embed the standard HTTP transport
	*reverseproxy.HTTPTransport

	// ClientCert specifies the criteria for selecting a client
	// certificate from the OS certificate store for mTLS authentication.
	ClientCert *CertSelector `json:"client_certificate,omitempty"`
}

HTTPTransport wraps reverseproxy.HTTPTransport to provide client certificate authentication using certificates from OS certificate stores (macOS Keychain, Windows Certificate Store) for mTLS connections to upstream servers.

func (HTTPTransport) CaddyModule

func (h HTTPTransport) CaddyModule() caddy.ModuleInfo

CaddyModule returns the Caddy module information.

func (*HTTPTransport) Cleanup

func (h *HTTPTransport) Cleanup() error

Cleanup implements caddy.CleanerUpper. It closes any idle connections and decrements the reference count for the cached certificate. When the reference count reaches zero, the certificate's OS resources are freed.

func (*HTTPTransport) Provision

func (h *HTTPTransport) Provision(ctx caddy.Context) error

Provision sets up the HTTP transport by loading the client certificate from the OS certificate store based on the configured matcher criteria. It compiles regex patterns if needed and validates the certificate exists.

func (*HTTPTransport) UnmarshalCaddyfile

func (h *HTTPTransport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error

Jump to

Keyboard shortcuts

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