Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

concept ACK requested: Generate tls certificate with CA #9325

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions cert/selfsigned.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cert

import (
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
Expand Down Expand Up @@ -200,8 +201,8 @@ func IsOutdated(cert *x509.Certificate, tlsExtraIPs,
// This function is adapted from https://github.com/btcsuite/btcd and
// https://github.com/btcsuite/btcd/btcutil
func GenCertPair(org string, tlsExtraIPs, tlsExtraDomains []string,
tlsDisableAutofill bool, certValidity time.Duration) (
[]byte, []byte, error) {
tlsDisableAutofill bool, certValidity time.Duration, caCertBytes []byte,
caKeyBytes []byte) ([]byte, []byte, error) {

now := time.Now()
validUntil := now.Add(certValidity)
Expand Down Expand Up @@ -232,6 +233,21 @@ func GenCertPair(org string, tlsExtraIPs, tlsExtraDomains []string,
return nil, nil, err
}

var caCert *x509.Certificate
isCa := true
var signerPriv crypto.PrivateKey = priv
if caKeyBytes != nil {
caCertData, parsedCaCert, err := LoadCertFromBytes(
caCertBytes, caKeyBytes,
)
if err != nil {
return nil, nil, err
}
isCa = false
signerPriv = caCertData.PrivateKey
caCert = parsedCaCert
}

// Construct the certificate template.
template := x509.Certificate{
SerialNumber: serialNumber,
Expand All @@ -248,16 +264,20 @@ func GenCertPair(org string, tlsExtraIPs, tlsExtraDomains []string,
ExtKeyUsage: []x509.ExtKeyUsage{
x509.ExtKeyUsageServerAuth,
},
IsCA: true, // so can sign self.
IsCA: isCa,
BasicConstraintsValid: true,

DNSNames: dnsNames,
IPAddresses: ipAddresses,
}

if isCa {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want some explanatory comments around this.

caCert = &template
}

derBytes, err := x509.CreateCertificate(
rand.Reader, &template,
&template, &priv.PublicKey, priv,
caCert, &priv.PublicKey, signerPriv,
)
if err != nil {
return nil, nil, fmt.Errorf("failed to create certificate: %w",
Expand Down
8 changes: 4 additions & 4 deletions cert/selfsigned_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func TestIsOutdatedCert(t *testing.T) {
// Generate TLS files with two extra IPs and domains.
certBytes, keyBytes, err := cert.GenCertPair(
"lnd autogenerated cert", extraIPs[:2], extraDomains[:2],
false, testTLSCertDuration,
false, testTLSCertDuration, nil, nil,
)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -90,7 +90,7 @@ func TestIsOutdatedPermutation(t *testing.T) {
// Generate TLS files from the IPs and domains.
certBytes, keyBytes, err := cert.GenCertPair(
"lnd autogenerated cert", extraIPs[:], extraDomains[:],
false, testTLSCertDuration,
false, testTLSCertDuration, nil, nil,
)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -161,7 +161,7 @@ func TestTLSDisableAutofill(t *testing.T) {
// Generate TLS files with two extra IPs and domains and no interface IPs.
certBytes, keyBytes, err := cert.GenCertPair(
"lnd autogenerated cert", extraIPs[:2], extraDomains[:2],
true, testTLSCertDuration,
true, testTLSCertDuration, nil, nil,
)
require.NoError(
t, err,
Expand Down Expand Up @@ -223,7 +223,7 @@ func TestTLSConfig(t *testing.T) {
// Generate TLS files with an extra IP and domain.
certBytes, keyBytes, err := cert.GenCertPair(
"lnd autogenerated cert", []string{extraIPs[0]},
[]string{extraDomains[0]}, false, testTLSCertDuration,
[]string{extraDomains[0]}, false, testTLSCertDuration, nil, nil,
)
require.NoError(t, err)

Expand Down
13 changes: 13 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ const (
defaultChainSubDirname = "chain"
defaultGraphSubDirname = "graph"
defaultTowerSubDirname = "watchtower"
defaultCACertFilename = "ca.cert"
defaultCAKeyFilename = "ca.key"
defaultTLSCertFilename = "tls.cert"
defaultTLSKeyFilename = "tls.key"
defaultAdminMacFilename = "admin.macaroon"
Expand Down Expand Up @@ -264,6 +266,8 @@ var (

defaultTowerDir = filepath.Join(defaultDataDir, defaultTowerSubDirname)

defaultCACertPath = filepath.Join(DefaultLndDir, defaultCACertFilename)
defaultCAKeyPath = filepath.Join(DefaultLndDir, defaultCAKeyFilename)
defaultTLSCertPath = filepath.Join(DefaultLndDir, defaultTLSCertFilename)
defaultTLSKeyPath = filepath.Join(DefaultLndDir, defaultTLSKeyFilename)
defaultLetsEncryptDir = filepath.Join(DefaultLndDir, defaultLetsEncryptDirname)
Expand Down Expand Up @@ -299,6 +303,8 @@ type Config struct {
DataDir string `short:"b" long:"datadir" description:"The directory to store lnd's data within"`
SyncFreelist bool `long:"sync-freelist" description:"Whether the databases used within lnd should sync their freelist to disk. This is disabled by default resulting in improved memory performance during operation, but with an increase in startup time."`

CACertPath string `long:"cacertpath" description:"Path to write the CA certificate for lnd's RPC and REST services"`
CAKeyPath string `long:"cakeypath" description:"Path to write the CA private key for lnd's RPC and REST services"`
TLSCertPath string `long:"tlscertpath" description:"Path to write the TLS certificate for lnd's RPC and REST services"`
TLSKeyPath string `long:"tlskeypath" description:"Path to write the TLS private key for lnd's RPC and REST services"`
TLSExtraIPs []string `long:"tlsextraip" description:"Adds an extra ip to the generated certificate"`
Expand Down Expand Up @@ -556,6 +562,8 @@ func DefaultConfig() Config {
ConfigFile: DefaultConfigFile,
DataDir: defaultDataDir,
DebugLevel: defaultLogLevel,
CACertPath: defaultCACertPath,
CAKeyPath: defaultCAKeyPath,
TLSCertPath: defaultTLSCertPath,
TLSKeyPath: defaultTLSKeyPath,
TLSCertDuration: defaultTLSCertDuration,
Expand Down Expand Up @@ -880,6 +888,8 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser,
cfg.LetsEncryptDir = filepath.Join(
lndDir, defaultLetsEncryptDirname,
)
cfg.CACertPath = filepath.Join(lndDir, defaultCACertFilename)
cfg.CAKeyPath = filepath.Join(lndDir, defaultCAKeyFilename)
cfg.TLSCertPath = filepath.Join(lndDir, defaultTLSCertFilename)
cfg.TLSKeyPath = filepath.Join(lndDir, defaultTLSKeyFilename)
cfg.LogDir = filepath.Join(lndDir, defaultLogDirname)
Expand Down Expand Up @@ -962,6 +972,8 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser,
// to directories and files are cleaned and expanded before attempting
// to use them later on.
cfg.DataDir = CleanAndExpandPath(cfg.DataDir)
cfg.CACertPath = CleanAndExpandPath(cfg.CACertPath)
cfg.CAKeyPath = CleanAndExpandPath(cfg.CAKeyPath)
cfg.TLSCertPath = CleanAndExpandPath(cfg.TLSCertPath)
cfg.TLSKeyPath = CleanAndExpandPath(cfg.TLSKeyPath)
cfg.LetsEncryptDir = CleanAndExpandPath(cfg.LetsEncryptDir)
Expand Down Expand Up @@ -1382,6 +1394,7 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser,
dirs := []string{
lndDir, cfg.DataDir, cfg.networkDir,
cfg.LetsEncryptDir, towerDir, cfg.graphDatabaseDir(),
filepath.Dir(cfg.CACertPath), filepath.Dir(cfg.CAKeyPath),
filepath.Dir(cfg.TLSCertPath), filepath.Dir(cfg.TLSKeyPath),
filepath.Dir(cfg.AdminMacPath), filepath.Dir(cfg.ReadMacPath),
filepath.Dir(cfg.InvoiceMacPath),
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ replace github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2
// allows us to specify that as an option.
replace google.golang.org/protobuf => github.com/lightninglabs/protobuf-go-hex-display v1.30.0-hex-display

replace github.com/lightningnetwork/lnd/cert => ./cert

// If you change this please also update .github/pull_request_template.md,
// docs/INSTALL.md and GO_IMAGE in lnrpc/gen_protos_docker.sh.
go 1.22.6
Expand Down
2 changes: 2 additions & 0 deletions lnd.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ func Main(cfg *Config, lisCfg ListenerCfg, implCfg *ImplementationCfg,
}

tlsManagerCfg := &TLSManagerCfg{
CACertPath: cfg.CACertPath,
CAKeyPath: cfg.CAKeyPath,
TLSCertPath: cfg.TLSCertPath,
TLSKeyPath: cfg.TLSKeyPath,
TLSEncryptKey: cfg.TLSEncryptKey,
Expand Down
Loading
Loading