DynamicTLS watches the filesystem and updates TLS configuration when certificate changes occur.
It provides simple integrations with HTTP/1.1, HTTP/2, gRPC, and Prometheus.
// create metrics
observer, err := tlsprom.NewObserver(
tlsprom.WithHTTP(),
tlsprom.WithServer(),
)
check(err)
prometheus.MustRegister(observer)
// create TLS config
cfg, err := dynamictls.NewConfig(
dynamictls.WithObserver(observer),
dynamictls.WithCertificate(primaryCertFile, primaryKeyFile),
dynamictls.WithCertificate(secondaryCertFile, secondaryKeyFile),
dynamictls.WithRootCAs(caFile),
dynamictls.WithHTTP(), // NB: adds HTTP/2 and HTTP/1.1 protocols
)
check(err)
defer cfg.Close()
// listen and serve
lis, err := cfg.Listen(context.Background(), "tcp", addr)
check(err)
check(http.Serve(lis, http.DefaultServeMux))
// create metrics
observer, err := tlsprom.NewObserver(
tlsprom.WithHTTP(),
tlsprom.WithClient(),
)
check(err)
prometheus.MustRegister(observer)
// create TLS config
cfg, err := dynamictls.NewConfig(
dynamictls.WithObserver(observer),
dynamictls.WithBase(&tls.Config{
MinVersion: tls.VersionTLS12,
}),
dynamictls.WithCertificate(certFile, keyFile),
dynamictls.WithRootCAs(caFile),
dynamictls.WithHTTP(), // NB: adds HTTP/2 and HTTP/1.1 protocols
)
check(err)
defer cfg.Close()
// create HTTP client
client := &http.Client{
Transport: &http.Transport{
DialTLSContext: cfg.Dial, // NB: DialTLSContext added in go 1.14
ForceAttemptHTTP2: true, // NB: required if using a custom dialer with HTTP/2
},
}
defer client.CloseIdleConnections()
// create metrics
observer, err := tlsprom.NewObserver(
tlsprom.WithGRPC(),
tlsprom.WithServer(),
)
check(err)
prometheus.MustRegister(observer)
// create TLS config
cfg, err := dynamictls.NewConfig(
dynamictls.WithObserver(observer),
dynamictls.WithBase(&tls.Config{
ClientAuth: tls.RequireAndVerifyClientCert,
MinVersion: tls.VersionTLS13,
}),
dynamictls.WithCertificate(certFile, keyFile),
dynamictls.WithRootCAs(caFile), // NB: metrics use RootCAs to verify local cert expiration
dynamictls.WithClientCAs(caFile),
dynamictls.WithHTTP2(),
)
check(err)
defer cfg.Close()
// create server with credentials
creds, err := grpctls.NewCredentials(cfg)
check(err)
srv := grpc.NewServer(grpc.Creds(creds))
pb.RegisterTestServiceServer(srv, &testServer{})
// listen and serve
lis, err := net.Listen("tcp", addr) // NB: use plain listener
check(err)
check(srv.Serve(lis))
// create metrics
observer, err := tlsprom.NewObserver(
tlsprom.WithGRPC(),
tlsprom.WithClient(),
)
check(err)
prometheus.MustRegister(observer)
// create TLS config
cfg, err := dynamictls.NewConfig(
dynamictls.WithObserver(observer),
dynamictls.WithBase(&tls.Config{
MinVersion: tls.VersionTLS13,
}),
dynamictls.WithCertificate(certFile, keyFile),
dynamictls.WithRootCAs(caFile),
dynamictls.WithHTTP2(),
)
check(err)
defer cfg.Close()
// create client with credentials
creds, err := grpctls.NewCredentials(cfg)
check(err)
conn, err := grpc.Dial(
addr,
grpc.WithTransportCredentials(creds),
grpc.WithDefaultCallOptions(grpc.WaitForReady(true)),
)
check(err)
defer conn.Close()
client := pb.NewTestServiceClient(conn)