Skip to content

Commit 8e61eb9

Browse files
committed
multi: make request logger level configurable
1 parent 2d57c25 commit 8e61eb9

File tree

4 files changed

+129
-30
lines changed

4 files changed

+129
-30
lines changed

config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/lightninglabs/faraday/chain"
1919
"github.com/lightninglabs/faraday/frdrpcserver"
2020
"github.com/lightninglabs/lightning-terminal/autopilotserver"
21+
"github.com/lightninglabs/lightning-terminal/firewall"
2122
mid "github.com/lightninglabs/lightning-terminal/rpcmiddleware"
2223
"github.com/lightninglabs/lndclient"
2324
"github.com/lightninglabs/loop/loopd"
@@ -188,6 +189,8 @@ type Config struct {
188189

189190
Autopilot *autopilotserver.Config `group:"Autopilot server options" namespace:"autopilot"`
190191

192+
Firewall *firewall.Config `group:"Firewall options" namespace:"firewall"`
193+
191194
// faradayRpcConfig is a subset of faraday's full configuration that is
192195
// passed into faraday's RPC server.
193196
faradayRpcConfig *frdrpcserver.Config
@@ -331,6 +334,7 @@ func defaultConfig() *Config {
331334
Autopilot: &autopilotserver.Config{
332335
PingCadence: time.Hour,
333336
},
337+
Firewall: firewall.DefaultConfig(),
334338
}
335339
}
336340

firewall/config.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package firewall
2+
3+
// Config holds all config options for the firewall.
4+
type Config struct {
5+
RequestLogger *RequestLoggerConfig `group:"request-logger" namespace:"request-logger" description:"request logger settings"`
6+
}
7+
8+
// RequestLoggerConfig holds all the config options for the request logger.
9+
type RequestLoggerConfig struct {
10+
RequestLoggerLevel RequestLoggerLevel `long:"level" description:"Set the request logger level. Options include 'all', 'full' and 'interceptor''"`
11+
}
12+
13+
// DefaultConfig constructs the default firewall Config struct.
14+
func DefaultConfig() *Config {
15+
return &Config{
16+
RequestLogger: &RequestLoggerConfig{
17+
RequestLoggerLevel: RequestLoggerLevelInterceptor,
18+
},
19+
}
20+
}

firewall/request_logger.go

Lines changed: 98 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package firewall
33
import (
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

1719
const (
@@ -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.
3949
type 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)

terminal.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,13 @@ func (g *LightningTerminal) startSubservers() error {
727727
}
728728
g.accountServiceStarted = true
729729

730-
requestLogger := firewall.NewRequestLogger(g.firewallDB)
730+
requestLogger, err := firewall.NewRequestLogger(
731+
g.cfg.Firewall.RequestLogger, g.firewallDB,
732+
)
733+
if err != nil {
734+
return fmt.Errorf("error creating new request logger")
735+
}
736+
731737
privacyMapper := firewall.NewPrivacyMapper(
732738
g.firewallDB.PrivacyDB, firewall.CryptoRandIntn,
733739
)

0 commit comments

Comments
 (0)