Skip to content

Commit dea6cd9

Browse files
committed
firewall: extract SessionID from gRPC metadata
In this commit, we update our various firewall interceptors so that they rely on the session ID passed via gRPC metadata to extract a session ID. For the PrivacyMapper and RuleEnforcer, these _MUST_ always contain a session ID and so we error out if one was not found. For the request logger, the session ID is optional and so we pass it to the new SessionID field in the AddActionReq - our bbolt actions DB will not make use of this field on persistence (but our incoming SQL version will).
1 parent 87bef06 commit dea6cd9

File tree

5 files changed

+36
-4
lines changed

5 files changed

+36
-4
lines changed

firewall/privacy_mapper.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,11 @@ func (p *PrivacyMapper) Intercept(ctx context.Context,
106106
"interception request: %v", err)
107107
}
108108

109-
sessionID, err := session.IDFromMacaroon(ri.Macaroon)
109+
sessionID, err := ri.SessionID.UnwrapOrErr(
110+
fmt.Errorf("no session ID found in macaroon"),
111+
)
110112
if err != nil {
111-
return nil, fmt.Errorf("could not extract ID from macaroon")
113+
return nil, err
112114
}
113115

114116
log.Tracef("PrivacyMapper: Intercepting %v", ri)

firewall/privacy_mapper_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/lightningnetwork/lnd/lnrpc"
1414
"github.com/lightningnetwork/lnd/rpcperms"
1515
"github.com/stretchr/testify/require"
16+
"google.golang.org/grpc/metadata"
1617
"google.golang.org/protobuf/proto"
1718
"gopkg.in/macaroon-bakery.v2/bakery"
1819
"gopkg.in/macaroon.v2"
@@ -907,6 +908,9 @@ func TestPrivacyMapper(t *testing.T) {
907908
rawMsg, err := proto.Marshal(test.msg)
908909
require.NoError(t, err)
909910

911+
md := make(metadata.MD)
912+
session.AddToGRPCMetadata(md, sessionID)
913+
910914
interceptReq := &rpcperms.InterceptionRequest{
911915
Type: test.msgType,
912916
Macaroon: mac,
@@ -916,6 +920,7 @@ func TestPrivacyMapper(t *testing.T) {
916920
ProtoTypeName: string(
917921
proto.MessageName(test.msg),
918922
),
923+
CtxMetadataPairs: md,
919924
}
920925

921926
mwReq, err := interceptReq.ToRPC(1, 2)
@@ -1006,6 +1011,9 @@ func TestPrivacyMapper(t *testing.T) {
10061011
amounts := make([]uint64, numSamples)
10071012
timestamps := make([]uint64, numSamples)
10081013

1014+
md := make(metadata.MD)
1015+
session.AddToGRPCMetadata(md, sessionID)
1016+
10091017
for i := 0; i < numSamples; i++ {
10101018
interceptReq := &rpcperms.InterceptionRequest{
10111019
Type: rpcperms.TypeResponse,
@@ -1016,6 +1024,7 @@ func TestPrivacyMapper(t *testing.T) {
10161024
ProtoTypeName: string(
10171025
proto.MessageName(msg),
10181026
),
1027+
CtxMetadataPairs: md,
10191028
}
10201029

10211030
mwReq, err := interceptReq.ToRPC(1, 2)

firewall/request_info.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import (
44
"fmt"
55
"strings"
66

7+
"github.com/lightninglabs/lightning-terminal/session"
8+
"github.com/lightningnetwork/lnd/fn"
79
"github.com/lightningnetwork/lnd/lnrpc"
10+
"google.golang.org/grpc/metadata"
811
"gopkg.in/macaroon.v2"
912
)
1013

@@ -25,6 +28,7 @@ const (
2528
// RequestInfo stores the parsed representation of an incoming RPC middleware
2629
// request.
2730
type RequestInfo struct {
31+
SessionID fn.Option[session.ID]
2832
MsgID uint64
2933
RequestID uint64
3034
MWRequestType string
@@ -76,8 +80,22 @@ func NewInfoFromRequest(req *lnrpc.RPCMiddlewareRequest) (*RequestInfo, error) {
7680
return nil, fmt.Errorf("invalid request type: %T", t)
7781
}
7882

83+
md := make(metadata.MD)
84+
for k, vs := range req.MetadataPairs {
85+
for _, v := range vs.Values {
86+
md.Append(k, v)
87+
}
88+
}
89+
90+
sessionID, err := session.FromGRPCMetadata(md)
91+
if err != nil {
92+
return nil, fmt.Errorf("error extracting session ID "+
93+
"from request: %v", err)
94+
}
95+
7996
ri.MsgID = req.MsgId
8097
ri.RequestID = req.RequestId
98+
ri.SessionID = sessionID
8199

82100
// If there is no macaroon in the request, then there is nothing left
83101
// to parse.

firewall/request_logger.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ func (r *RequestLogger) addNewAction(ctx context.Context, ri *RequestInfo,
194194
}
195195

196196
actionReq := &firewalldb.AddActionReq{
197+
SessionID: ri.SessionID,
197198
MacaroonIdentifier: macaroonID,
198199
RPCMethod: ri.URI,
199200
}

firewall/rule_enforcer.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,11 @@ func (r *RuleEnforcer) Intercept(ctx context.Context,
237237
func (r *RuleEnforcer) handleRequest(ctx context.Context,
238238
ri *RequestInfo) (proto.Message, error) {
239239

240-
sessionID, err := session.IDFromMacaroon(ri.Macaroon)
240+
sessionID, err := ri.SessionID.UnwrapOrErr(
241+
fmt.Errorf("no session ID found in macaroon"),
242+
)
241243
if err != nil {
242-
return nil, fmt.Errorf("could not extract ID from macaroon")
244+
return nil, err
243245
}
244246

245247
rules, err := r.collectEnforcers(ctx, ri, sessionID)

0 commit comments

Comments
 (0)