Merge pull request #22 from guggero/autocert

Add autocert functionality to get certificate through Let's Encrypt
This commit is contained in:
Olaoluwa Osuntokun
2020-01-15 19:36:09 -08:00
committed by GitHub
5 changed files with 64 additions and 11 deletions

View File

@@ -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.

1
go.mod
View File

@@ -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

2
go.sum
View File

@@ -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=

View File

@@ -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

View File

@@ -1,6 +1,8 @@
listenaddr: "localhost:8081"
staticroot: "./static"
debuglevel: "debug"
servername: kirin.example.com
autocert: false
authenticator:
lndhost: "localhost:10009"