mirror of
https://github.com/lightninglabs/lightning-terminal.git
synced 2026-08-13 12:33:36 +02:00
rpc_proxy: special case the handling of BakeSuperMacaroon
In this commit, we special case the handling of BakeSuperMacaroon so as
to allow a user to make use of `litcli bakesupermacaroon` while LiT is
running in stateless init mode. The handling is as follows:
- if the call to _LiT's_ BakeSuperMacaroon is made while in stateless
init mode then we can assume that the macaroon provided is either:
1) an LND native macaroon which may or may not have the
necessary permissions for the _LND_
"/lnrpc.Lightning/BakeMacaroon" call.
2) a baked macaroon (possibly a super macaroon) which may or may
not have the permissions to the _LiT_
"/litrpc.Proxy/BakeSuperMacaroon" call.
For case 1: we check that the provided macaroon has the correct perms.
If it does, then we use LiT's existing connection to LND to bake the
super mac.
For case 2: we have a macaroon that doesnt have LND's bakemac call perms
directly but does have LiT's BakeSuperMac perms. So for this, we treat
the call as normal and verify using LiT's macaroon validator as normal.
This commit is contained in:
parent
d3dc753b9b
commit
6bcf19fb8e
1 changed files with 84 additions and 0 deletions
84
rpc_proxy.go
84
rpc_proxy.go
|
|
@ -34,6 +34,9 @@ const (
|
|||
// HeaderMacaroon is the HTTP header field name that is used to send
|
||||
// the macaroon.
|
||||
HeaderMacaroon = "Macaroon"
|
||||
|
||||
lndBakeMacMethod = "/lnrpc.Lightning/BakeMacaroon"
|
||||
litBakeSuperMacMethod = "/litrpc.Proxy/BakeSuperMacaroon"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -410,6 +413,87 @@ func (p *rpcProxy) UnaryServerInterceptor(ctx context.Context, req interface{},
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// We special case the handling of a call to LiT's BakeSuperMacaroon
|
||||
// method if we are in stateless init mode. If a user has called this
|
||||
// method, they are either calling with an LND macaroon or a baked
|
||||
// super macaroon.
|
||||
if p.cfg.statelessInitMode &&
|
||||
info.FullMethod == litBakeSuperMacMethod {
|
||||
|
||||
// Fetch permissions that are required for LND's BakeMacaroon
|
||||
// method. Since this will only be called in stateless-init mode
|
||||
// which is only possible in integrated mode, we can be sure
|
||||
// that the permissions returned here are the up-to-date
|
||||
// permissions for the LND method.
|
||||
requiredPerms, ok := p.permsMgr.URIPermissions(lndBakeMacMethod)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unknown permissions for %s",
|
||||
lndBakeMacMethod)
|
||||
}
|
||||
permissions := make(
|
||||
[]*lnrpc.MacaroonPermission, len(requiredPerms),
|
||||
)
|
||||
for idx, perm := range requiredPerms {
|
||||
permissions[idx] = &lnrpc.MacaroonPermission{
|
||||
Entity: perm.Entity,
|
||||
Action: perm.Action,
|
||||
}
|
||||
}
|
||||
|
||||
// Next, we extract the macaroon provided by the user.
|
||||
macHex, err := macaroons.RawMacaroonFromContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
macBytes, err := hex.DecodeString(macHex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lndClient, err := p.getBasicLNDClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Using LiT's existing connection to LND, we verify that the
|
||||
// provided macaroon contains the required permissions for the
|
||||
// LND BakeMacaroon method.
|
||||
resp, err := lndClient.CheckMacaroonPermissions(
|
||||
ctx, &lnrpc.CheckMacPermRequest{
|
||||
Macaroon: macBytes,
|
||||
Permissions: permissions,
|
||||
FullMethod: lndBakeMacMethod,
|
||||
},
|
||||
)
|
||||
|
||||
// There are two valid possible outcomes depending on if the
|
||||
// user used LND's macaroon which contains the permissions
|
||||
// required for LND's BakeMacaroon method or if they used a
|
||||
// super macaroon that contains the necessary permissions for
|
||||
// LiT's BakeSuperMacaroon method. If the former is the case,
|
||||
// and the macaroon is valid, then we can now directly call the
|
||||
// handler without further checking the macaroon.
|
||||
if err == nil && resp.Valid {
|
||||
// Call LiT's BakeSuperMacaroon function.
|
||||
return handler(ctx, req)
|
||||
}
|
||||
|
||||
// If we do get an error from the above call, then the later
|
||||
// case described above might be true: the call might have
|
||||
// been performed with a macaroon that has the permissions for
|
||||
// LiT's BakeSuperMacaroon method. In that case, we log the
|
||||
// error, but we pass the call on to LiT's macaroon validator
|
||||
// as normal.
|
||||
log.Warnf("The call to LiT's %s method did not contain a "+
|
||||
"macaroon with the permissions required for LND's %s "+
|
||||
"method: %v. The call will instead be verified "+
|
||||
"against LiT's macaroon validator to check if it has "+
|
||||
"direct permissions for LiT's %s method.",
|
||||
litBakeSuperMacMethod, lndBakeMacMethod, err,
|
||||
litBakeSuperMacMethod)
|
||||
}
|
||||
|
||||
// With the basic auth converted to a macaroon if necessary,
|
||||
// let's now validate the macaroon.
|
||||
err = p.macValidator.ValidateMacaroon(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue