Skip to content

Commit 352858a

Browse files
ellemoutonpositiveblue
authored andcommitted
multi: always use Lit's TLS cert
In this commit, we remove Lit's dependency on LND's tls cert in integrated mode. With this commit, even if Lit is started in integrated mode, it will create its own tls cert to use for serving the webserver.
1 parent ac23b2e commit 352858a

File tree

5 files changed

+65
-79
lines changed

5 files changed

+65
-79
lines changed

cmd/litcli/main.go

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/lightninglabs/lndclient"
1212
"github.com/lightninglabs/protobuf-hex-display/jsonpb"
1313
"github.com/lightninglabs/protobuf-hex-display/proto"
14-
"github.com/lightningnetwork/lnd"
1514
"github.com/lightningnetwork/lnd/lncfg"
1615
"github.com/lightningnetwork/lnd/macaroons"
1716
"github.com/urfave/cli"
@@ -47,16 +46,6 @@ var (
4746
Usage: "path to lit's TLS certificate",
4847
Value: terminal.DefaultTLSCertPath,
4948
}
50-
lndMode = cli.StringFlag{
51-
Name: "lndmode",
52-
Usage: "the mode that lnd is running in: remote or integrated",
53-
Value: terminal.ModeIntegrated,
54-
}
55-
lndTlsCertFlag = cli.StringFlag{
56-
Name: "lndtlscertpath",
57-
Usage: "path to lnd's TLS certificate",
58-
Value: lnd.DefaultConfig().TLSCertPath,
59-
}
6049
macaroonPathFlag = cli.StringFlag{
6150
Name: "macaroonpath",
6251
Usage: "path to lit's macaroon file",
@@ -78,9 +67,7 @@ func main() {
7867
},
7968
networkFlag,
8069
baseDirFlag,
81-
lndMode,
8270
tlsCertFlag,
83-
lndTlsCertFlag,
8471
macaroonPathFlag,
8572
}
8673
app.Commands = append(app.Commands, sessionCommands...)
@@ -175,18 +162,6 @@ func extractPathArgs(ctx *cli.Context) (string, string, error) {
175162
)
176163
}
177164

178-
// Get the LND mode. If Lit is in integrated LND mode, then LND's tls
179-
// cert is used directly. Otherwise, Lit's own tls cert is used.
180-
lndmode := strings.ToLower(ctx.GlobalString(lndMode.Name))
181-
if lndmode == terminal.ModeIntegrated {
182-
tlsCertPath := lncfg.CleanAndExpandPath(ctx.GlobalString(
183-
lndTlsCertFlag.Name,
184-
))
185-
186-
return tlsCertPath, macaroonPath, nil
187-
}
188-
189-
// Lit is in remote LND mode. So we need Lit's tls cert.
190165
tlsCertPath := lncfg.CleanAndExpandPath(ctx.GlobalString(
191166
tlsCertFlag.Name,
192167
))

config.go

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ type Config struct {
152152
LetsEncryptDir string `long:"letsencryptdir" description:"The directory where the Let's Encrypt library will store its key and certificate."`
153153
LetsEncryptListen string `long:"letsencryptlisten" description:"The IP:port on which LiT will listen for Let's Encrypt challenges. Let's Encrypt will always try to contact on port 80. Often non-root processes are not allowed to bind to ports lower than 1024. This configuration option allows a different port to be used, but must be used in combination with port forwarding from port 80. This configuration can also be used to specify another IP address to listen on, for example an IPv6 address."`
154154

155+
TLSCertPath string `long:"tlscertpath" description:"Path to write the self signed TLS certificate for LiT's RPC and REST proxy service (if Let's Encrypt is not used). This only applies to the HTTPSListen port."`
156+
TLSKeyPath string `long:"tlskeypath" description:"Path to write the self signed TLS private key for LiT's RPC and REST proxy service (if Let's Encrypt is not used). This only applies to the HTTPSListen port."`
157+
155158
LitDir string `long:"lit-dir" description:"The main directory where LiT looks for its configuration file. If LiT is running in 'remote' lnd mode, this is also the directory where the TLS certificates and log files are stored by default."`
156159
ConfigFile string `long:"configfile" description:"Path to LiT's configuration file."`
157160

@@ -211,9 +214,6 @@ type Config struct {
211214
// RemoteConfig holds the configuration parameters that are needed when running
212215
// LiT in the "remote" lnd mode.
213216
type RemoteConfig struct {
214-
LitTLSCertPath string `long:"lit-tlscertpath" description:"For lnd remote mode only: Path to write the self signed TLS certificate for LiT's RPC and REST proxy service (if Let's Encrypt is not used)."`
215-
LitTLSKeyPath string `long:"lit-tlskeypath" description:"For lnd remote mode only: Path to write the self signed TLS private key for LiT's RPC and REST proxy service (if Let's Encrypt is not used)."`
216-
217217
LitLogDir string `long:"lit-logdir" description:"For lnd remote mode only: Directory to log output."`
218218
LitMaxLogFiles int `long:"lit-maxlogfiles" description:"For lnd remote mode only: Maximum logfiles to keep (0 for no rotation)"`
219219
LitMaxLogFileSize int `long:"lit-maxlogfilesize" description:"For lnd remote mode only: Maximum logfile size in MB"`
@@ -286,9 +286,9 @@ func (c *Config) lndConnectParams() (string, lndclient.Network, string,
286286
func defaultConfig() *Config {
287287
return &Config{
288288
HTTPSListen: defaultHTTPSListen,
289+
TLSCertPath: DefaultTLSCertPath,
290+
TLSKeyPath: defaultTLSKeyPath,
289291
Remote: &RemoteConfig{
290-
LitTLSCertPath: DefaultTLSCertPath,
291-
LitTLSKeyPath: defaultTLSKeyPath,
292292
LitDebugLevel: defaultLogLevel,
293293
LitLogDir: defaultLogDir,
294294
LitMaxLogFiles: defaultMaxLogFiles,
@@ -598,6 +598,33 @@ func loadConfigFile(preCfg *Config, interceptor signal.Interceptor) (*Config,
598598
return nil, fmt.Errorf("invalid lnd mode %v", cfg.LndMode)
599599
}
600600

601+
// If the provided lit directory is not the default, we'll modify the
602+
// path to all of the files and directories that will live within it.
603+
if litDir != DefaultLitDir {
604+
if cfg.TLSKeyPath == defaultTLSKeyPath {
605+
cfg.TLSKeyPath = filepath.Join(
606+
litDir, DefaultTLSKeyFilename,
607+
)
608+
}
609+
610+
if cfg.TLSCertPath == DefaultTLSCertPath {
611+
cfg.TLSCertPath = filepath.Join(
612+
litDir, DefaultTLSCertFilename,
613+
)
614+
}
615+
}
616+
617+
cfg.TLSCertPath = lncfg.CleanAndExpandPath(cfg.TLSCertPath)
618+
cfg.TLSKeyPath = lncfg.CleanAndExpandPath(cfg.TLSKeyPath)
619+
620+
// Make sure the parent directories of our certificate files exist.
621+
if err := makeDirectories(filepath.Dir(cfg.TLSCertPath)); err != nil {
622+
return nil, err
623+
}
624+
if err := makeDirectories(filepath.Dir(cfg.TLSKeyPath)); err != nil {
625+
return nil, err
626+
}
627+
601628
// Warn about missing config file only after all other configuration is
602629
// done. This prevents the warning on help messages and invalid options.
603630
// Note this should go directly before the return.
@@ -637,25 +664,15 @@ func validateRemoteModeConfig(cfg *Config) error {
637664
// path to all of the files and directories that will live within it.
638665
litDir := lnd.CleanAndExpandPath(cfg.LitDir)
639666
if litDir != DefaultLitDir {
640-
r.LitTLSCertPath = filepath.Join(litDir, DefaultTLSCertFilename)
641-
r.LitTLSKeyPath = filepath.Join(litDir, DefaultTLSKeyFilename)
642-
r.LitLogDir = filepath.Join(litDir, defaultLogDirname)
667+
if r.LitLogDir == defaultLogDir {
668+
r.LitLogDir = filepath.Join(
669+
litDir, defaultLogDirname,
670+
)
671+
}
643672
}
644673

645-
r.LitTLSCertPath = lncfg.CleanAndExpandPath(r.LitTLSCertPath)
646-
r.LitTLSKeyPath = lncfg.CleanAndExpandPath(r.LitTLSKeyPath)
647674
r.LitLogDir = lncfg.CleanAndExpandPath(r.LitLogDir)
648675

649-
// Make sure the parent directories of our certificate files exist. We
650-
// don't need to do the same for the log dir as the log rotator will do
651-
// just that.
652-
if err := makeDirectories(filepath.Dir(r.LitTLSCertPath)); err != nil {
653-
return err
654-
}
655-
if err := makeDirectories(filepath.Dir(r.LitTLSKeyPath)); err != nil {
656-
return err
657-
}
658-
659676
// In remote mode, we don't call lnd's ValidateConfig that sets up a
660677
// logging backend for us. We need to manually create and start one. The
661678
// root logger should've already been created as part of the default
@@ -745,8 +762,7 @@ func readUIPassword(config *Config) error {
745762
func buildTLSConfigForHttp2(config *Config) (*tls.Config, error) {
746763
var tlsConfig *tls.Config
747764

748-
switch {
749-
case config.LetsEncrypt:
765+
if config.LetsEncrypt {
750766
serverName := config.LetsEncryptHost
751767
if serverName == "" {
752768
return nil, errors.New("let's encrypt host name " +
@@ -782,10 +798,9 @@ func buildTLSConfigForHttp2(config *Config) (*tls.Config, error) {
782798
tlsConfig = &tls.Config{
783799
GetCertificate: manager.GetCertificate,
784800
}
785-
786-
case config.LndMode == ModeRemote:
787-
tlsCertPath := config.Remote.LitTLSCertPath
788-
tlsKeyPath := config.Remote.LitTLSKeyPath
801+
} else {
802+
tlsCertPath := config.TLSCertPath
803+
tlsKeyPath := config.TLSKeyPath
789804

790805
if !lnrpc.FileExists(tlsCertPath) &&
791806
!lnrpc.FileExists(tlsKeyPath) {
@@ -807,16 +822,6 @@ func buildTLSConfigForHttp2(config *Config) (*tls.Config, error) {
807822
"keys: %v", err)
808823
}
809824
tlsConfig = cert.TLSConfFromCert(tlsCert)
810-
811-
default:
812-
tlsCert, _, err := cert.LoadCert(
813-
config.Lnd.TLSCertPath, config.Lnd.TLSKeyPath,
814-
)
815-
if err != nil {
816-
return nil, fmt.Errorf("failed reading TLS server "+
817-
"keys: %v", err)
818-
}
819-
tlsConfig = cert.TLSConfFromCert(tlsCert)
820825
}
821826

822827
// lnd's cipher suites are too restrictive for HTTP/2, we need to add

doc/config-lnd-integrated.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ Example `~/.lit/lit.conf`:
7171
```text
7272
# Application Options
7373
httpslisten=0.0.0.0:8443
74+
tlscertpath=~/.lit/tls.cert
75+
tlskeypath=~/.lit/tls.key
7476
letsencrypt=true
7577
letsencrypthost=loop.merchant.com
7678
lnd-mode=integrated
@@ -117,6 +119,15 @@ system:
117119
- **On Linux**: `~/.lit/lit.conf`
118120
- **On Windows**: `~/AppData/Roaming/Lit/lit.conf`
119121

122+
## LiT and LND interfaces
123+
124+
Port 10009 is the port that LND uses to expose its gRPC interface. LND's tls
125+
cert and macaroons will be required when making requests to this interface.
126+
127+
Port 8443 is a port that LiT uses to expose a variety of interfaces: gRPC,
128+
REST, grpc-web. When making requests using this interface, LiT's tls cert and
129+
macaroons should be used.
130+
120131
## Upgrade Existing Nodes
121132

122133
If you already have existing `lnd`, `loop`, or `faraday` nodes, you can easily

itest/litd_firewall_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ func testFWRateLimitAndPrivacyMapper(net *NetworkHarness, t *harnessTest) {
168168

169169
// We create a connection to the Alice node's RPC server.
170170
cfg := net.Alice.Cfg
171-
rawConn, err := connectRPC(ctx, cfg.LitAddr(), cfg.TLSCertPath)
171+
rawConn, err := connectRPC(ctx, cfg.LitAddr(), cfg.LitTLSCertPath)
172172
require.NoError(t.t, err)
173173

174174
macBytes, err := ioutil.ReadFile(cfg.LitMacPath)
@@ -419,7 +419,7 @@ func testHistoryLimitRule(net *NetworkHarness, t *harnessTest) {
419419

420420
// We create a connection to the Alice node's RPC server.
421421
cfg := net.Alice.Cfg
422-
rawConn, err := connectRPC(ctx, cfg.LitAddr(), cfg.TLSCertPath)
422+
rawConn, err := connectRPC(ctx, cfg.LitAddr(), cfg.LitTLSCertPath)
423423
require.NoError(t.t, err)
424424

425425
macBytes, err := ioutil.ReadFile(cfg.LitMacPath)
@@ -595,7 +595,7 @@ func testChanPolicyBoundsRule(net *NetworkHarness, t *harnessTest) {
595595

596596
// We create a connection to the Alice node's RPC server.
597597
cfg := net.Alice.Cfg
598-
rawConn, err := connectRPC(ctx, cfg.LitAddr(), cfg.TLSCertPath)
598+
rawConn, err := connectRPC(ctx, cfg.LitAddr(), cfg.LitTLSCertPath)
599599
require.NoError(t.t, err)
600600

601601
macBytes, err := ioutil.ReadFile(cfg.LitMacPath)
@@ -843,7 +843,7 @@ func testPeerAndChannelRestrictRules(net *NetworkHarness, t *harnessTest) {
843843

844844
// We create a connection to the Alice node's RPC server.
845845
cfg := net.Alice.Cfg
846-
rawConn, err := connectRPC(ctx, cfg.LitAddr(), cfg.TLSCertPath)
846+
rawConn, err := connectRPC(ctx, cfg.LitAddr(), cfg.LitTLSCertPath)
847847
require.NoError(t.t, err)
848848

849849
macBytes, err := ioutil.ReadFile(cfg.LitMacPath)
@@ -1175,7 +1175,7 @@ func testLargeHttpHeader(net *NetworkHarness, t *harnessTest) {
11751175

11761176
// We create a connection to the Alice node's RPC server.
11771177
cfg := net.Alice.Cfg
1178-
rawConn, err := connectRPC(ctx, cfg.LitAddr(), cfg.TLSCertPath)
1178+
rawConn, err := connectRPC(ctx, cfg.LitAddr(), cfg.LitTLSCertPath)
11791179
require.NoError(t.t, err)
11801180

11811181
macBytes, err := ioutil.ReadFile(cfg.LitMacPath)

itest/litd_mode_integrated_test.go

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ func testModeIntegrated(net *NetworkHarness, t *harnessTest) {
291291

292292
tt.Run(endpoint.name+" lit port", func(ttt *testing.T) {
293293
runGRPCAuthTest(
294-
ttt, cfg.LitAddr(), cfg.TLSCertPath,
294+
ttt, cfg.LitAddr(), cfg.LitTLSCertPath,
295295
endpoint.macaroonFn(cfg),
296296
endpoint.requestFn,
297297
endpoint.successPattern,
@@ -315,7 +315,7 @@ func testModeIntegrated(net *NetworkHarness, t *harnessTest) {
315315

316316
tt.Run(endpoint.name+" lit port", func(ttt *testing.T) {
317317
runUIPasswordCheck(
318-
ttt, cfg.LitAddr(), cfg.TLSCertPath,
318+
ttt, cfg.LitAddr(), cfg.LitTLSCertPath,
319319
cfg.UIPassword, endpoint.requestFn,
320320
false, endpoint.successPattern,
321321
)
@@ -364,7 +364,7 @@ func testModeIntegrated(net *NetworkHarness, t *harnessTest) {
364364

365365
tt.Run(endpoint.name+" lit port", func(ttt *testing.T) {
366366
runGRPCAuthTest(
367-
ttt, cfg.LitAddr(), cfg.TLSCertPath,
367+
ttt, cfg.LitAddr(), cfg.LitTLSCertPath,
368368
superMacFile,
369369
endpoint.requestFn,
370370
endpoint.successPattern,
@@ -403,7 +403,7 @@ func testModeIntegrated(net *NetworkHarness, t *harnessTest) {
403403
defer cancel()
404404

405405
rawLNCConn := setUpLNCConn(
406-
ctxt, t.t, cfg.LitAddr(), cfg.TLSCertPath,
406+
ctxt, t.t, cfg.LitAddr(), cfg.LitTLSCertPath,
407407
cfg.LitMacPath,
408408
litrpc.SessionType_TYPE_MACAROON_READONLY, nil,
409409
)
@@ -434,11 +434,11 @@ func testModeIntegrated(net *NetworkHarness, t *harnessTest) {
434434

435435
ht := newHarnessTest(tt, net)
436436
runAccountSystemTest(
437-
ht, net.Alice, cfg.RPCAddr(), cfg.TLSCertPath,
437+
ht, net.Alice, cfg.LitAddr(), cfg.LitTLSCertPath,
438438
superMacFile, 1,
439439
)
440440
runAccountSystemTest(
441-
ht, net.Alice, cfg.LitAddr(), cfg.TLSCertPath,
441+
ht, net.Alice, cfg.LitAddr(), cfg.LitTLSCertPath,
442442
superMacFile, 2,
443443
)
444444
})
@@ -465,7 +465,7 @@ func testModeIntegrated(net *NetworkHarness, t *harnessTest) {
465465
}
466466

467467
rawLNCConn := setUpLNCConn(
468-
ctxt, t.t, cfg.LitAddr(), cfg.TLSCertPath,
468+
ctxt, t.t, cfg.LitAddr(), cfg.LitTLSCertPath,
469469
cfg.LitMacPath,
470470
litrpc.SessionType_TYPE_MACAROON_CUSTOM, customPerms,
471471
)
@@ -525,14 +525,11 @@ func setUpLNCConn(ctx context.Context, t *testing.T, hostPort, tlsCertPath,
525525
// runCertificateCheck checks that the TLS certificates presented to clients are
526526
// what we expect them to be.
527527
func runCertificateCheck(t *testing.T, node *HarnessNode) {
528-
// In integrated mode we expect the LiT HTTPS port (8443 by default) and
529-
// lnd's RPC port to present the same certificate, namely lnd's TLS
530-
// cert.
531528
litCerts, err := getServerCertificates(node.Cfg.LitAddr())
532529
require.NoError(t, err)
533530
require.Len(t, litCerts, 1)
534531
require.Equal(
535-
t, "lnd autogenerated cert", litCerts[0].Issuer.Organization[0],
532+
t, "litd autogenerated cert", litCerts[0].Issuer.Organization[0],
536533
)
537534

538535
lndCerts, err := getServerCertificates(node.Cfg.RPCAddr())
@@ -541,8 +538,6 @@ func runCertificateCheck(t *testing.T, node *HarnessNode) {
541538
require.Equal(
542539
t, "lnd autogenerated cert", lndCerts[0].Issuer.Organization[0],
543540
)
544-
545-
require.Equal(t, litCerts[0].Raw, lndCerts[0].Raw)
546541
}
547542

548543
// runGRPCAuthTest tests authentication of the given gRPC interface.

0 commit comments

Comments
 (0)