Skip to content

Getting started

This walkthrough serves HTTPS with the package's hardened defaults, then points a client at it — the two ends of a TLS connection, both secured from the same config.

Install

go get gitlab.com/phpboyscout/go/tls

The module targets a current Go toolchain and pulls in only cockroachdb/errors.

Serve HTTPS with hardened defaults

A Pair is the typed {Enabled, Cert, Key} triple describing a certificate. ServerConfig loads that certificate into the hardened DefaultConfig and returns a ready *crypto/tls.Config:

package main

import (
    "log"
    "net/http"

    "gitlab.com/phpboyscout/go/tls"
)

func main() {
    pair := tls.Pair{
        Enabled: true,
        Cert:    "/etc/certs/server.pem",
        Key:     "/etc/certs/server-key.pem",
    }

    // Advertise HTTP/2 then HTTP/1.1 via ALPN; omit the args for no ALPN.
    cfg, err := pair.ServerConfig("h2", "http/1.1")
    if err != nil {
        log.Fatal(err)
    }

    srv := &http.Server{Addr: ":8443", TLSConfig: cfg}

    // The certificate is already loaded into TLSConfig, so the file
    // arguments to ListenAndServeTLS are empty.
    log.Fatal(srv.ListenAndServeTLS("", ""))
}

ServerConfig returns an error if the certificate or key cannot be loaded, so a misconfigured path fails fast at startup rather than on the first handshake.

Connect a hardened client

ClientConfig returns the same hardened config for the client side. With no arguments it trusts the system root store; pass PEM CA files to trust a private CA as well:

clientCfg, err := tls.ClientConfig() // trust system roots
if err != nil {
    log.Fatal(err)
}

client := &http.Client{
    Transport: &http.Transport{TLSClientConfig: clientCfg},
}

If your server presents a certificate from a private CA (self-signed or an internal authority), hand the client the CA's PEM file:

clientCfg, err := tls.ClientConfig("/etc/certs/ca.pem")

Guard on validity

Pair.Valid reports whether TLS is enabled and both paths are set — handy for deciding between an HTTP and an HTTPS listener at boot:

if pair.Valid() {
    // serve TLS with pair.ServerConfig(...)
} else {
    // fall back to plain HTTP, or refuse to start
}

Next steps