Skip to content

Commit 75cfa0b

Browse files
committed
rpc_proxy: only allow requests if sub-server is ready
1 parent 21456a5 commit 75cfa0b

File tree

2 files changed

+65
-15
lines changed

2 files changed

+65
-15
lines changed

rpc_proxy.go

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/lightninglabs/lightning-terminal/litrpc"
1616
"github.com/lightninglabs/lightning-terminal/perms"
1717
"github.com/lightninglabs/lightning-terminal/session"
18+
litstatus "github.com/lightninglabs/lightning-terminal/status"
1819
"github.com/lightninglabs/lightning-terminal/subservers"
1920
"github.com/lightningnetwork/lnd/lncfg"
2021
"github.com/lightningnetwork/lnd/macaroons"
@@ -67,7 +68,8 @@ func (e *proxyErr) Unwrap() error {
6768
// component.
6869
func newRpcProxy(cfg *Config, validator macaroons.MacaroonValidator,
6970
superMacValidator session.SuperMacaroonValidator,
70-
permsMgr *perms.Manager, subServerMgr *subservers.Manager) *rpcProxy {
71+
permsMgr *perms.Manager, subServerMgr *subservers.Manager,
72+
statusMgr *litstatus.Manager) *rpcProxy {
7173

7274
// The gRPC web calls are protected by HTTP basic auth which is defined
7375
// by base64(username:password). Because we only have a password, we
@@ -88,6 +90,7 @@ func newRpcProxy(cfg *Config, validator macaroons.MacaroonValidator,
8890
macValidator: validator,
8991
superMacValidator: superMacValidator,
9092
subServerMgr: subServerMgr,
93+
statusMgr: statusMgr,
9194
}
9295
p.grpcServer = grpc.NewServer(
9396
// From the grpxProxy doc: This codec is *crucial* to the
@@ -162,6 +165,7 @@ type rpcProxy struct {
162165
basicAuth string
163166
permsMgr *perms.Manager
164167
subServerMgr *subservers.Manager
168+
statusMgr *litstatus.Manager
165169

166170
bakeSuperMac bakeSuperMac
167171

@@ -333,6 +337,10 @@ func (p *rpcProxy) makeDirector(allowLitRPC bool) func(ctx context.Context,
333337
}
334338
}
335339

340+
if err := p.checkSubSystemStarted(requestURI); err != nil {
341+
return outCtx, nil, err
342+
}
343+
336344
// Direct the call to the correct backend. All gRPC calls end up
337345
// here since our gRPC server instance doesn't have any handlers
338346
// registered itself. So all daemon calls that are remote are
@@ -359,12 +367,6 @@ func (p *rpcProxy) makeDirector(allowLitRPC bool) func(ctx context.Context,
359367
)
360368
}
361369

362-
// If the rpcProxy has not started yet, then the lnd connection
363-
// will not be initialised yet.
364-
if !p.hasStarted() {
365-
return outCtx, nil, ErrWaitingToStart
366-
}
367-
368370
return outCtx, p.lndConn, nil
369371
}
370372
}
@@ -375,15 +377,15 @@ func (p *rpcProxy) UnaryServerInterceptor(ctx context.Context, req interface{},
375377
info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{},
376378
error) {
377379

378-
if !p.hasStarted() && !isStatusReq(info.FullMethod) {
379-
return nil, ErrWaitingToStart
380-
}
381-
382380
uriPermissions, ok := p.permsMgr.URIPermissions(info.FullMethod)
383381
if !ok {
384382
return nil, ErrUnknownRequest
385383
}
386384

385+
if err := p.checkSubSystemStarted(info.FullMethod); err != nil {
386+
return nil, err
387+
}
388+
387389
// For now, basic authentication is just a quick fix until we
388390
// have proper macaroon support implemented in the UI. We allow
389391
// gRPC web requests to have it and "convert" the auth into a
@@ -419,15 +421,15 @@ func (p *rpcProxy) StreamServerInterceptor(srv interface{},
419421
ss grpc.ServerStream, info *grpc.StreamServerInfo,
420422
handler grpc.StreamHandler) error {
421423

422-
if !p.hasStarted() && !isStatusReq(info.FullMethod) {
423-
return ErrWaitingToStart
424-
}
425-
426424
uriPermissions, ok := p.permsMgr.URIPermissions(info.FullMethod)
427425
if !ok {
428426
return ErrUnknownRequest
429427
}
430428

429+
if err := p.checkSubSystemStarted(info.FullMethod); err != nil {
430+
return err
431+
}
432+
431433
// For now, basic authentication is just a quick fix until we
432434
// have proper macaroon support implemented in the UI. We allow
433435
// gRPC web requests to have it and "convert" the auth into a
@@ -604,6 +606,53 @@ func (p *rpcProxy) convertSuperMacaroon(ctx context.Context, macHex string,
604606
return nil, nil
605607
}
606608

609+
// checkSubSystemStarted checks if the subsystem responsible for handling the
610+
// given URI has started.
611+
func (p *rpcProxy) checkSubSystemStarted(requestURI string) error {
612+
// A request to Lit's status server is always allowed.
613+
if isStatusReq(requestURI) {
614+
return nil
615+
}
616+
617+
// Check if the rpcProxy has started yet.
618+
if !p.hasStarted() {
619+
return ErrWaitingToStart
620+
}
621+
622+
// Currently, Lit and LND are not registered with the sub-server
623+
// manager, so we let any request for them through.
624+
if p.permsMgr.IsSubServerURI(subservers.LIT, requestURI) ||
625+
p.permsMgr.IsSubServerURI(subservers.LND, requestURI) {
626+
627+
return nil
628+
}
629+
630+
// Check that the sub-server manager does have a sub-server registered
631+
// that can handle the given URI.
632+
handled, system := p.subServerMgr.Handles(requestURI)
633+
if !handled {
634+
return fmt.Errorf("unknown gRPC web request: %v", requestURI)
635+
}
636+
637+
// Check with the status manger to see if the sub-server is ready to
638+
// handle the request.
639+
serverStatus, err := p.statusMgr.GetStatus(system)
640+
if err != nil {
641+
return err
642+
}
643+
644+
if serverStatus.Disabled {
645+
return fmt.Errorf("%s has been disabled", system)
646+
}
647+
648+
if !serverStatus.Running {
649+
return fmt.Errorf("%s is not running: %s", system,
650+
serverStatus.Err)
651+
}
652+
653+
return nil
654+
}
655+
607656
// readMacaroon tries to read the macaroon file at the specified path and create
608657
// gRPC dial options from it.
609658
func readMacaroon(macPath string) ([]byte, error) {

terminal.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ func (g *LightningTerminal) Run() error {
244244
// server is started.
245245
g.rpcProxy = newRpcProxy(
246246
g.cfg, g, g.validateSuperMacaroon, g.permsMgr, g.subServerMgr,
247+
g.statusMgr,
247248
)
248249

249250
// Register any gRPC services that should be served using LiT's

0 commit comments

Comments
 (0)