Skip to content

Commit 2434152

Browse files
committed
multi: validate macaroons for lit calls
Use the new macaroon service to verify LitURI calls.
1 parent 822a01b commit 2434152

File tree

6 files changed

+72
-120
lines changed

6 files changed

+72
-120
lines changed

itest/litd_mode_integrated_test.go

Lines changed: 45 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -134,81 +134,60 @@ var (
134134
ctx, &litrpc.ListSessionsRequest{},
135135
)
136136
}
137+
litMacaroonFn = func(cfg *LitNodeConfig) string {
138+
return cfg.LitMacPath
139+
}
137140

138141
endpoints = []struct {
139-
name string
140-
macaroonFn macaroonFn
141-
requestFn requestFn
142-
successPattern string
143-
supportsMacAuthOnLndPort bool
144-
supportsMacAuthOnLitPort bool
145-
supportsUIPasswordOnLndPort bool
146-
supportsUIPasswordOnLitPort bool
147-
allowedThroughLNC bool
148-
grpcWebURI string
149-
restWebURI string
142+
name string
143+
macaroonFn macaroonFn
144+
requestFn requestFn
145+
successPattern string
146+
allowedThroughLNC bool
147+
grpcWebURI string
148+
restWebURI string
150149
}{{
151-
name: "lnrpc",
152-
macaroonFn: lndMacaroonFn,
153-
requestFn: lndRequestFn,
154-
successPattern: "\"identity_pubkey\":\"0",
155-
supportsMacAuthOnLndPort: true,
156-
supportsMacAuthOnLitPort: true,
157-
supportsUIPasswordOnLndPort: false,
158-
supportsUIPasswordOnLitPort: true,
159-
allowedThroughLNC: true,
160-
grpcWebURI: "/lnrpc.Lightning/GetInfo",
161-
restWebURI: "/v1/getinfo",
150+
name: "lnrpc",
151+
macaroonFn: lndMacaroonFn,
152+
requestFn: lndRequestFn,
153+
successPattern: "\"identity_pubkey\":\"0",
154+
allowedThroughLNC: true,
155+
grpcWebURI: "/lnrpc.Lightning/GetInfo",
156+
restWebURI: "/v1/getinfo",
162157
}, {
163-
name: "frdrpc",
164-
macaroonFn: faradayMacaroonFn,
165-
requestFn: faradayRequestFn,
166-
successPattern: "\"reports\":[]",
167-
supportsMacAuthOnLndPort: true,
168-
supportsMacAuthOnLitPort: true,
169-
supportsUIPasswordOnLndPort: false,
170-
supportsUIPasswordOnLitPort: true,
171-
allowedThroughLNC: true,
172-
grpcWebURI: "/frdrpc.FaradayServer/RevenueReport",
173-
restWebURI: "/v1/faraday/revenue",
158+
name: "frdrpc",
159+
macaroonFn: faradayMacaroonFn,
160+
requestFn: faradayRequestFn,
161+
successPattern: "\"reports\":[]",
162+
allowedThroughLNC: true,
163+
grpcWebURI: "/frdrpc.FaradayServer/RevenueReport",
164+
restWebURI: "/v1/faraday/revenue",
174165
}, {
175-
name: "looprpc",
176-
macaroonFn: loopMacaroonFn,
177-
requestFn: loopRequestFn,
178-
successPattern: "\"swaps\":[]",
179-
supportsMacAuthOnLndPort: true,
180-
supportsMacAuthOnLitPort: true,
181-
supportsUIPasswordOnLndPort: false,
182-
supportsUIPasswordOnLitPort: true,
183-
allowedThroughLNC: true,
184-
grpcWebURI: "/looprpc.SwapClient/ListSwaps",
185-
restWebURI: "/v1/loop/swaps",
166+
name: "looprpc",
167+
macaroonFn: loopMacaroonFn,
168+
requestFn: loopRequestFn,
169+
successPattern: "\"swaps\":[]",
170+
allowedThroughLNC: true,
171+
grpcWebURI: "/looprpc.SwapClient/ListSwaps",
172+
restWebURI: "/v1/loop/swaps",
186173
}, {
187-
name: "poolrpc",
188-
macaroonFn: poolMacaroonFn,
189-
requestFn: poolRequestFn,
190-
successPattern: "\"accounts_active\":0",
191-
supportsMacAuthOnLndPort: true,
192-
supportsMacAuthOnLitPort: true,
193-
supportsUIPasswordOnLndPort: false,
194-
supportsUIPasswordOnLitPort: true,
195-
allowedThroughLNC: true,
196-
grpcWebURI: "/poolrpc.Trader/GetInfo",
197-
restWebURI: "/v1/pool/info",
174+
name: "poolrpc",
175+
macaroonFn: poolMacaroonFn,
176+
requestFn: poolRequestFn,
177+
successPattern: "\"accounts_active\":0",
178+
allowedThroughLNC: true,
179+
grpcWebURI: "/poolrpc.Trader/GetInfo",
180+
restWebURI: "/v1/pool/info",
198181
}, {
199182
name: "litrpc",
200-
macaroonFn: nil,
183+
macaroonFn: litMacaroonFn,
201184
requestFn: litRequestFn,
202185
// In some test cases we actually expect some sessions, so we
203186
// don't explicitly check for an empty array but just the
204187
// existence of the array in the response.
205-
successPattern: "\"sessions\":[",
206-
supportsMacAuthOnLndPort: false,
207-
supportsMacAuthOnLitPort: false,
208-
supportsUIPasswordOnLndPort: true,
209-
supportsUIPasswordOnLitPort: true,
210-
allowedThroughLNC: false,
211-
grpcWebURI: "/litrpc.Sessions/ListSessions",
188+
successPattern: "\"sessions\":[",
189+
allowedThroughLNC: false,
190+
grpcWebURI: "/litrpc.Sessions/ListSessions",
212191
}}
213192
)
214193

@@ -236,10 +215,6 @@ func testModeIntegrated(net *NetworkHarness, t *harnessTest) {
236215
for _, endpoint := range endpoints {
237216
endpoint := endpoint
238217
tt.Run(endpoint.name+" lnd port", func(ttt *testing.T) {
239-
if !endpoint.supportsMacAuthOnLndPort {
240-
return
241-
}
242-
243218
runGRPCAuthTest(
244219
ttt, cfg.RPCAddr(), cfg.TLSCertPath,
245220
endpoint.macaroonFn(cfg),
@@ -249,10 +224,6 @@ func testModeIntegrated(net *NetworkHarness, t *harnessTest) {
249224
})
250225

251226
tt.Run(endpoint.name+" lit port", func(ttt *testing.T) {
252-
if !endpoint.supportsMacAuthOnLitPort {
253-
return
254-
}
255-
256227
runGRPCAuthTest(
257228
ttt, cfg.LitAddr(), cfg.TLSCertPath,
258229
endpoint.macaroonFn(cfg),
@@ -272,8 +243,7 @@ func testModeIntegrated(net *NetworkHarness, t *harnessTest) {
272243
runUIPasswordCheck(
273244
ttt, cfg.RPCAddr(), cfg.TLSCertPath,
274245
cfg.UIPassword,
275-
endpoint.requestFn, true,
276-
!endpoint.supportsUIPasswordOnLndPort,
246+
endpoint.requestFn,
277247
endpoint.successPattern,
278248
)
279249
})
@@ -282,8 +252,7 @@ func testModeIntegrated(net *NetworkHarness, t *harnessTest) {
282252
runUIPasswordCheck(
283253
ttt, cfg.LitAddr(), cfg.TLSCertPath,
284254
cfg.UIPassword,
285-
endpoint.requestFn, false,
286-
!endpoint.supportsUIPasswordOnLitPort,
255+
endpoint.requestFn,
287256
endpoint.successPattern,
288257
)
289258
})
@@ -321,10 +290,6 @@ func testModeIntegrated(net *NetworkHarness, t *harnessTest) {
321290
for _, endpoint := range endpoints {
322291
endpoint := endpoint
323292
tt.Run(endpoint.name+" lnd port", func(ttt *testing.T) {
324-
if !endpoint.supportsMacAuthOnLndPort {
325-
return
326-
}
327-
328293
runGRPCAuthTest(
329294
ttt, cfg.RPCAddr(), cfg.TLSCertPath,
330295
superMacFile,
@@ -334,10 +299,6 @@ func testModeIntegrated(net *NetworkHarness, t *harnessTest) {
334299
})
335300

336301
tt.Run(endpoint.name+" lit port", func(ttt *testing.T) {
337-
if !endpoint.supportsMacAuthOnLitPort {
338-
return
339-
}
340-
341302
runGRPCAuthTest(
342303
ttt, cfg.LitAddr(), cfg.TLSCertPath,
343304
superMacFile,
@@ -454,8 +415,7 @@ func runGRPCAuthTest(t *testing.T, hostPort, tlsCertPath, macPath string,
454415

455416
// runUIPasswordCheck tests UI password authentication.
456417
func runUIPasswordCheck(t *testing.T, hostPort, tlsCertPath, uiPassword string,
457-
makeRequest requestFn, shouldFailWithoutMacaroon,
458-
shouldFailWithDummyMacaroon bool, successContent string) {
418+
makeRequest requestFn, successContent string) {
459419

460420
ctxb := context.Background()
461421
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
@@ -490,28 +450,6 @@ func runUIPasswordCheck(t *testing.T, hostPort, tlsCertPath, uiPassword string,
490450
ctxm = uiPasswordContext(ctxt, uiPassword, false)
491451
resp, err := makeRequest(ctxm, rawConn)
492452

493-
// On lnd's gRPC interface we don't support using the UI password.
494-
if shouldFailWithoutMacaroon {
495-
require.Error(t, err)
496-
require.Contains(t, err.Error(), "expected 1 macaroon, got 0")
497-
498-
// Sending a dummy macaroon will allow us to not get an error in
499-
// case of the litrpc calls, where we don't support macaroons
500-
// but have the extraction call in the validator anyway. So we
501-
// provide a dummy macaroon but still the UI password must be
502-
// correct to pass.
503-
ctxm = uiPasswordContext(ctxt, uiPassword, true)
504-
resp, err = makeRequest(ctxm, rawConn)
505-
506-
if shouldFailWithDummyMacaroon {
507-
require.Error(t, err)
508-
require.Contains(
509-
t, err.Error(), "cannot get macaroon: root",
510-
)
511-
return
512-
}
513-
}
514-
515453
// We expect the call to succeed.
516454
require.NoError(t, err)
517455

itest/litd_mode_remote_test.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,6 @@ func testModeRemote(net *NetworkHarness, t *harnessTest) {
4343
for _, endpoint := range endpoints {
4444
endpoint := endpoint
4545
tt.Run(endpoint.name+" lit port", func(ttt *testing.T) {
46-
if !endpoint.supportsMacAuthOnLitPort {
47-
return
48-
}
49-
5046
runGRPCAuthTest(
5147
ttt, cfg.LitAddr(), cfg.LitTLSCertPath,
5248
endpoint.macaroonFn(cfg),
@@ -67,7 +63,6 @@ func testModeRemote(net *NetworkHarness, t *harnessTest) {
6763
ttt, cfg.LitAddr(), cfg.LitTLSCertPath,
6864
cfg.UIPassword,
6965
endpoint.requestFn, false,
70-
!endpoint.supportsUIPasswordOnLitPort,
7166
endpoint.successPattern,
7267
)
7368
})

itest/litd_node.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ type LitNodeConfig struct {
6767
LoopMacPath string
6868
PoolMacPath string
6969
LitTLSCertPath string
70+
LitMacPath string
7071

7172
UIPassword string
7273
LitDir string
@@ -279,6 +280,9 @@ func newNode(cfg *LitNodeConfig, harness *NetworkHarness) (*HarnessNode, error)
279280
cfg.PoolMacPath = filepath.Join(
280281
cfg.PoolDir, cfg.NetParams.Name, "pool.macaroon",
281282
)
283+
cfg.LitMacPath = filepath.Join(
284+
cfg.LitDir, cfg.NetParams.Name, "lit.macaroon",
285+
)
282286
cfg.LitTLSCertPath = filepath.Join(cfg.LitDir, "tls.cert")
283287
cfg.GenerateListeningPorts()
284288

rpc_proxy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ func (p *rpcProxy) basicAuthToMacaroon(basicAuth, requestURI string,
537537
}
538538

539539
case isLitURI(requestURI):
540-
return EmptyMacaroonBytes, nil
540+
macPath = p.cfg.MacaroonPath
541541

542542
default:
543543
return nil, fmt.Errorf("unknown gRPC web request: %v",

subserver_permissions.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,18 @@ var (
1212
// litPermissions is a map of all LiT RPC methods and their required
1313
// macaroon permissions to access the session service.
1414
litPermissions = map[string][]bakery.Op{
15-
"/litrpc.Sessions/AddSession": {{}},
16-
"/litrpc.Sessions/ListSessions": {{}},
17-
"/litrpc.Sessions/RevokeSession": {{}},
15+
"/litrpc.Sessions/AddSession": {{
16+
Entity: "sessions",
17+
Action: "write",
18+
}},
19+
"/litrpc.Sessions/ListSessions": {{
20+
Entity: "sessions",
21+
Action: "read",
22+
}},
23+
"/litrpc.Sessions/RevokeSession": {{
24+
Entity: "sessions",
25+
Action: "write",
26+
}},
1827
}
1928

2029
// whiteListedMethods is a map of all lnd RPC methods that don't require

terminal.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -749,12 +749,18 @@ func (g *LightningTerminal) ValidateMacaroon(ctx context.Context,
749749
}
750750

751751
case isLitURI(fullMethod):
752-
wrap := fmt.Errorf("invalid basic auth")
753-
_, err := g.rpcProxy.convertBasicAuth(ctx, fullMethod, wrap)
754-
if err != nil {
752+
if !g.sessionRpcServerStarted {
753+
return fmt.Errorf("the session server is not yet " +
754+
"ready for requests, lnd possibly still " +
755+
"starting or syncing")
756+
}
757+
758+
if err := g.sessionRpcServer.macaroonService.ValidateMacaroon(
759+
ctx, requiredPermissions, fullMethod,
760+
); err != nil {
755761
return &proxyErr{
756762
proxyContext: "lit",
757-
wrapped: fmt.Errorf("invalid auth: %v",
763+
wrapped: fmt.Errorf("invalid macaroon: %w",
758764
err),
759765
}
760766
}

0 commit comments

Comments
 (0)