From 5276c1b850abcfc656b5d326852b265dc8eaaf51 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 10 Jan 2020 14:17:01 +0100 Subject: [PATCH] kirin: add autocert functionality --- kirin.go | 60 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/kirin.go b/kirin.go index 59fa641..17b467a 100644 --- a/kirin.go +++ b/kirin.go @@ -1,6 +1,7 @@ package kirin import ( + "crypto/tls" "fmt" "io" "io/ioutil" @@ -16,6 +17,7 @@ import ( "github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/cert" "github.com/lightningnetwork/lnd/lnrpc" + "golang.org/x/crypto/acme/autocert" "gopkg.in/yaml.v2" ) @@ -80,19 +82,57 @@ func start() error { Handler: http.HandlerFunc(servicesProxy.ServeHTTP), } - // Ensure we create TLS key and certificate if they don't exist. + // Create TLS certificates. tlsKeyFile := filepath.Join(kirinDataDir, defaultTLSKeyFilename) tlsCertFile := filepath.Join(kirinDataDir, defaultTLSCertFilename) - if !fileExists(tlsCertFile) && !fileExists(tlsKeyFile) { - log.Infof("Generating TLS certificates...") - err := cert.GenCertPair( - "kirin autogenerated cert", tlsCertFile, tlsKeyFile, - nil, nil, cert.DefaultAutogenValidity, - ) - if err != nil { - return err + switch { + // When using autocert, we set a TLSConfig on the server so the key and + // cert file we pass in are ignored and don't need to exist. + case cfg.AutoCert: + serverName := cfg.ServerName + if serverName == "" { + return fmt.Errorf("servername option is required for " + + "secure operation") + } + + certDir := filepath.Join(kirinDataDir, "autocert") + log.Infof("Configuring autocert for server %v with cache dir "+ + "%v", serverName, certDir) + + manager := autocert.Manager{ + Cache: autocert.DirCache(certDir), + Prompt: autocert.AcceptTOS, + HostPolicy: autocert.HostWhitelist(serverName), + } + + go func() { + err := http.ListenAndServe( + ":http", manager.HTTPHandler(nil), + ) + if err != nil { + log.Errorf("autocert http: %v", err) + } + }() + server.TLSConfig = &tls.Config{ + GetCertificate: manager.GetCertificate, + } + + // If we're not using autocert, we want to create self-signed TLS certs + // and save them at the specified location (if they don't already + // exist). + default: + if !fileExists(tlsCertFile) && !fileExists(tlsKeyFile) { + log.Infof("Generating TLS certificates...") + err := cert.GenCertPair( + "kirin autogenerated cert", tlsCertFile, + tlsKeyFile, nil, nil, + cert.DefaultAutogenValidity, + ) + if err != nil { + return err + } + log.Infof("Done generating TLS certificates") } - log.Infof("Done generating TLS certificates") } // The ListenAndServeTLS below will block until shut down or an error