Skip to content

Commit 20504ed

Browse files
committed
rpcproxy: pass the bake-mac call directly to LND if in stateless mode
In this commit, we force the permissions manager to see the BakeSuperMacaroon call of LiT as whitelisted. This means that when the initial call comes in, the `LightningTerminal.ValidateMacaroon` method will return early and not validate the call (which would fail in stateless init mode since LiT does not have a macaroon service in that case). So the call ends up going through to the rpcProxy's BakeSuperMacaroon method. Here we now have the following flow: - if the request does not have stateless_init set, then we keep the flow as it was: 1) Use the lit mac validator to check that the call is allowed given the required permissions of `BakeSuperMacaroon`. 2) if it is, then use the existing connection to LND that Lit has to do the macaroon baking call. - if stateless_init mode is set, then we do the following: 1) we extract the macaroon from the call (this should be an LND macaroon) 2) we create a new connection to LND using this provided macaroon. 3) use this connection to LND to bake the macaroon.
1 parent 5aabbde commit 20504ed

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

rpc_proxy.go

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/lightninglabs/lightning-terminal/session"
1818
litstatus "github.com/lightninglabs/lightning-terminal/status"
1919
"github.com/lightninglabs/lightning-terminal/subservers"
20+
"github.com/lightninglabs/lndclient"
2021
"github.com/lightningnetwork/lnd/lncfg"
2122
"github.com/lightningnetwork/lnd/lnrpc"
2223
"github.com/lightningnetwork/lnd/macaroons"
@@ -34,6 +35,10 @@ const (
3435
// HeaderMacaroon is the HTTP header field name that is used to send
3536
// the macaroon.
3637
HeaderMacaroon = "Macaroon"
38+
39+
// bakeSuperMacURI is the LiT service URI that can be used to bake a
40+
// super macaroon.
41+
bakeSuperMacURI = "/litrpc.Proxy/BakeSuperMacaroon"
3742
)
3843

3944
var (
@@ -251,6 +256,14 @@ func (p *rpcProxy) GetInfo(_ context.Context, _ *litrpc.GetInfoRequest) (
251256
// BakeSuperMacaroon bakes a new macaroon that includes permissions for
252257
// all the active daemons that LiT is connected to.
253258
//
259+
// NOTE that we must always explicitly check the provided macaroon for this
260+
// method. If req.StatelessInit is false, then we check the macaroon against
261+
// LiT's macaroon validator, and then we just use LiT's existing, authenticated,
262+
// connection to LND to bake the macaroon. Otherwise, when StatelessInit is
263+
// true, we don't verify the macaroon here. We instead create a new connection
264+
// to LND using the provided macaroon for authentication, and we use this new
265+
// connection to bake the macaroon.
266+
//
254267
// NOTE: this is part of the litrpc.ProxyServiceServer interface.
255268
func (p *rpcProxy) BakeSuperMacaroon(ctx context.Context,
256269
req *litrpc.BakeSuperMacaroonRequest) (
@@ -260,7 +273,59 @@ func (p *rpcProxy) BakeSuperMacaroon(ctx context.Context,
260273
return nil, ErrWaitingToStart
261274
}
262275

263-
superMac, err := p.bakeSuperMac(ctx, p.basicClient, req.RootKeyIdSuffix)
276+
// Error out early if we are not in integrated mode and the
277+
// stateless_init flag was set. Note that if we pass this check, we
278+
// also know that LND is running in integrated mode
279+
if req.StatelessInit && !p.cfg.statelessInitMode {
280+
return nil, fmt.Errorf("LiT is not running in " +
281+
"stateless-init mode")
282+
}
283+
284+
var lndClient lnrpc.LightningClient
285+
if !req.StatelessInit {
286+
perms, ok := p.permsMgr.URIPermissions(bakeSuperMacURI)
287+
if !ok {
288+
return nil, fmt.Errorf("unknown perms for %s",
289+
bakeSuperMacURI)
290+
}
291+
292+
// Verify the macaroon using LiT's macaroon validator.
293+
err := p.litMacValidator.ValidateMacaroon(
294+
ctx, perms, bakeSuperMacURI,
295+
)
296+
if err != nil {
297+
return nil, err
298+
}
299+
300+
// Use LiT's authenticated connection to LND to bake the
301+
// macaroon.
302+
lndClient = p.basicClient
303+
} else {
304+
// If we are in stateless Init mode, then this call was made
305+
// unauthenticated into LiT. However, it should have an LND
306+
// macaroon attached which can be used to bake the macaroon.
307+
// So we create a new connection to LND using this macaroon.
308+
309+
// Extract the macaroon from the context. This should be an
310+
// LND macaroon.
311+
macHex, err := macaroons.RawMacaroonFromContext(ctx)
312+
if err != nil {
313+
return nil, err
314+
}
315+
316+
// Create a new connection to LND using the macaroon provided
317+
// in the context.
318+
lndClient, err = lndclient.NewBasicClient(
319+
p.cfg.lndDialAddr(), "", "", p.cfg.Network,
320+
lndclient.MacaroonData(macHex),
321+
lndclient.Insecure(),
322+
)
323+
if err != nil {
324+
return nil, err
325+
}
326+
}
327+
328+
superMac, err := p.bakeSuperMac(ctx, lndClient, req.RootKeyIdSuffix)
264329
if err != nil {
265330
return nil, err
266331
}

terminal.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,11 @@ func (g *LightningTerminal) Run() error {
251251
err)
252252
}
253253

254+
// We will check the BakeSuperMacaroon auth within the handler itself.
255+
if err = g.permsMgr.ForceWhiteListURL(bakeSuperMacURI); err != nil {
256+
return err
257+
}
258+
254259
// The litcli status command will call the "/lnrpc.State/GetState" RPC.
255260
// As the status command is available to the user before the macaroons
256261
// have been loaded/created, and before the lnd clients have been

0 commit comments

Comments
 (0)