@@ -3,6 +3,7 @@ package firewall
33import (
44 "context"
55 "fmt"
6+ "strings"
67 "sync"
78 "time"
89
@@ -12,6 +13,7 @@ import (
1213 "github.com/lightninglabs/lightning-terminal/session"
1314 "github.com/lightninglabs/protobuf-hex-display/jsonpb"
1415 "github.com/lightningnetwork/lnd/lnrpc"
16+ "github.com/lightningnetwork/lnd/macaroons"
1517)
1618
1719const (
@@ -35,10 +37,20 @@ var (
3537 _ mid.RequestInterceptor = (* RequestLogger )(nil )
3638)
3739
40+ type RequestLoggerLevel string
41+
42+ const (
43+ RequestLoggerLevelInterceptor = "interceptor"
44+ RequestLoggerLevelAll = "all"
45+ RequestLoggerLevelFull = "full"
46+ )
47+
3848// RequestLogger is a RequestInterceptor that just logs incoming RPC requests.
3949type RequestLogger struct {
4050 actionsDB firewalldb.ActionsWriteDB
4151
52+ shouldLogAction func (ri * RequestInfo ) (bool , bool )
53+
4254 // reqIDToAction is a map from request ID to an ActionLocator that can
4355 // be used to find the corresponding action. This is used so that
4456 // requests and responses can be easily linked. The mu mutex must be
@@ -48,11 +60,55 @@ type RequestLogger struct {
4860}
4961
5062// NewRequestLogger creates a new RequestLogger.
51- func NewRequestLogger (actionsDB firewalldb.ActionsWriteDB ) * RequestLogger {
52- return & RequestLogger {
53- actionsDB : actionsDB ,
54- reqIDToAction : make (map [uint64 ]* firewalldb.ActionLocator ),
63+ func NewRequestLogger (cfg * RequestLoggerConfig ,
64+ actionsDB firewalldb.ActionsWriteDB ) (* RequestLogger , error ) {
65+
66+ hasInterceptorCaveat := func (caveats []string ) bool {
67+ for _ , c := range caveats {
68+ if strings .HasPrefix (c , macaroons .CondLndCustom ) {
69+ return true
70+ }
71+ }
72+
73+ return false
74+ }
75+
76+ var shouldLogAction func (ri * RequestInfo ) (bool , bool )
77+ switch cfg .RequestLoggerLevel {
78+ // Only log requests that have an interceptor caveat attached.
79+ case RequestLoggerLevelInterceptor :
80+ shouldLogAction = func (ri * RequestInfo ) (bool , bool ) {
81+ if hasInterceptorCaveat (ri .Caveats ) {
82+ return true , true
83+ }
84+
85+ return false , false
86+ }
87+
88+ // Log all requests but only log request params if the request
89+ // has an interceptor caveat.
90+ case RequestLoggerLevelAll :
91+ shouldLogAction = func (ri * RequestInfo ) (bool , bool ) {
92+ return true , hasInterceptorCaveat (ri .Caveats )
93+ }
94+
95+ // Log all requests will all request parameters.
96+ case RequestLoggerLevelFull :
97+ shouldLogAction = func (ri * RequestInfo ) (bool , bool ) {
98+ return true , true
99+ }
100+
101+ default :
102+ return nil , fmt .Errorf ("unknown request logger level: %s. " +
103+ "Expected either 'interceptor', 'all' or 'full'" ,
104+ cfg .RequestLoggerLevel )
55105 }
106+
107+ return & RequestLogger {
108+ shouldLogAction : shouldLogAction ,
109+ actionsDB : actionsDB ,
110+ reqIDToAction : make (map [uint64 ]* firewalldb.ActionLocator ),
111+ }, nil
56112}
57113
58114// Name returns the name of the interceptor.
@@ -89,6 +145,11 @@ func (r *RequestLogger) Intercept(_ context.Context,
89145 return mid .RPCOk (req )
90146 }
91147
148+ shouldLogAction , withPayloadData := r .shouldLogAction (ri )
149+ if ! shouldLogAction {
150+ return mid .RPCOk (req )
151+ }
152+
92153 log .Tracef ("RequestLogger: Intercepting %v" , ri )
93154
94155 switch ri .MWRequestType {
@@ -97,7 +158,7 @@ func (r *RequestLogger) Intercept(_ context.Context,
97158
98159 // Parse incoming requests and act on them.
99160 case MWRequestTypeRequest :
100- return mid .RPCErr (req , r .addNewAction (ri ))
161+ return mid .RPCErr (req , r .addNewAction (ri , withPayloadData ))
101162
102163 // Parse and possibly manipulate outgoing responses.
103164 case MWRequestTypeResponse :
@@ -120,7 +181,9 @@ func (r *RequestLogger) Intercept(_ context.Context,
120181}
121182
122183// addNewAction persists the new action to the db.
123- func (r * RequestLogger ) addNewAction (ri * RequestInfo ) error {
184+ func (r * RequestLogger ) addNewAction (ri * RequestInfo ,
185+ withPayloadData bool ) error {
186+
124187 // If no macaroon is provided, then an empty 4-byte array is used as the
125188 // session ID. Otherwise, the macaroon is used to derive a session ID.
126189 var sessionID [4 ]byte
@@ -132,34 +195,40 @@ func (r *RequestLogger) addNewAction(ri *RequestInfo) error {
132195 }
133196 }
134197
135- msg , err := mid .ParseProtobuf (ri .GRPCMessageType , ri .Serialized )
136- if err != nil {
137- return err
198+ action := & firewalldb.Action {
199+ RPCMethod : ri .URI ,
200+ AttemptedAt : time .Now (),
201+ State : firewalldb .ActionStateInit ,
138202 }
139203
140- jsonMarshaler := & jsonpb.Marshaler {
141- EmitDefaults : true ,
142- OrigName : true ,
143- }
204+ if withPayloadData {
205+ msg , err := mid .ParseProtobuf (ri .GRPCMessageType , ri .Serialized )
206+ if err != nil {
207+ return err
208+ }
144209
145- jsonStr , err := jsonMarshaler . MarshalToString ( proto . MessageV1 ( msg ))
146- if err != nil {
147- return fmt . Errorf ( "unable to decode response: %v" , err )
148- }
210+ jsonMarshaler := & jsonpb. Marshaler {
211+ EmitDefaults : true ,
212+ OrigName : true ,
213+ }
149214
150- action := & firewalldb. Action {
151- RPCMethod : ri . URI ,
152- RPCParamsJson : [] byte ( jsonStr ),
153- AttemptedAt : time . Now (),
154- State : firewalldb . ActionStateInit ,
155- }
215+ jsonStr , err := jsonMarshaler . MarshalToString (
216+ proto . MessageV1 ( msg ) ,
217+ )
218+ if err != nil {
219+ return fmt . Errorf ( "unable to decode response: %v" , err )
220+ }
156221
157- if ri .MetaInfo != nil {
158- action .ActorName = ri .MetaInfo .ActorName
159- action .FeatureName = ri .MetaInfo .Feature
160- action .Trigger = ri .MetaInfo .Trigger
161- action .Intent = ri .MetaInfo .Intent
162- action .StructuredJsonData = ri .MetaInfo .StructuredJsonData
222+ action .RPCParamsJson = []byte (jsonStr )
223+
224+ meta := ri .MetaInfo
225+ if meta != nil {
226+ action .ActorName = meta .ActorName
227+ action .FeatureName = meta .Feature
228+ action .Trigger = meta .Trigger
229+ action .Intent = meta .Intent
230+ action .StructuredJsonData = meta .StructuredJsonData
231+ }
163232 }
164233
165234 id , err := r .actionsDB .AddAction (sessionID , action )
0 commit comments