From 9af86470285ad334c06f62f751aba723c8879bdd Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 10 Jan 2020 14:00:36 +0100 Subject: [PATCH 1/3] config: add autocert options --- config.go | 10 +++++++++- sample-conf.yaml | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/config.go b/config.go index 50e2894..4af7a2b 100644 --- a/config.go +++ b/config.go @@ -36,7 +36,15 @@ type authConfig struct { type config struct { // ListenAddr is the listening address that we should use to allow Kirin // to listen for requests. - ListenAddr string `long:"listenaddr" description:"The interface we should listen on for client requests"` + ListenAddr string `long:"listenaddr" description:"The interface we should listen on for client requests."` + + // ServerName can be set to a fully qualifying domain name that should + // be used while creating a certificate through Let's Encrypt. + ServerName string `long:"servername" description:"Server name (FQDN) to use for the TLS certificate."` + + // AutoCert can be set to true if kirin should try to create a valid + // certificate through Let's Encrypt using ServerName. + AutoCert bool `long:"autocert" description:"Automatically create a Let's Encrypt cert using ServerName."` // StaticRoot is the folder where the static content served by the proxy // is located. diff --git a/sample-conf.yaml b/sample-conf.yaml index adfa26b..6bf5d19 100644 --- a/sample-conf.yaml +++ b/sample-conf.yaml @@ -1,6 +1,8 @@ listenaddr: "localhost:8081" staticroot: "./static" debuglevel: "debug" +servername: kirin.example.com +autocert: false authenticator: lndhost: "localhost:10009" From e539e6306fe511dd7eba556a92f1acb9bc12fcde Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 10 Jan 2020 14:16:41 +0100 Subject: [PATCH 2/3] mod: add autocert library --- go.mod | 1 + go.sum | 2 ++ 2 files changed, 3 insertions(+) diff --git a/go.mod b/go.mod index d11743a..6575635 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect go.uber.org/zap v1.13.0 // indirect + golang.org/x/crypto v0.0.0-20200109152110-61a87790db17 golang.org/x/net v0.0.0-20191112182307-2180aed22343 // indirect golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea // indirect google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a // indirect diff --git a/go.sum b/go.sum index 82f99e0..3f6f830 100644 --- a/go.sum +++ b/go.sum @@ -266,6 +266,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM= golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200109152110-61a87790db17 h1:nVJ3guKA9qdkEQ3TUdXI9QSINo2CUPM/cySEvw2w8I0= +golang.org/x/crypto v0.0.0-20200109152110-61a87790db17/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= From 5276c1b850abcfc656b5d326852b265dc8eaaf51 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 10 Jan 2020 14:17:01 +0100 Subject: [PATCH 3/3] 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