@@ -2,10 +2,12 @@ package terminal
2
2
3
3
import (
4
4
"context"
5
+ "crypto/tls"
5
6
"encoding/base64"
6
7
"encoding/hex"
7
8
"fmt"
8
9
"io/ioutil"
10
+ "net"
9
11
"net/http"
10
12
"strings"
11
13
"time"
@@ -18,6 +20,7 @@ import (
18
20
"google.golang.org/grpc/backoff"
19
21
"google.golang.org/grpc/credentials"
20
22
"google.golang.org/grpc/metadata"
23
+ "google.golang.org/grpc/test/bufconn"
21
24
"gopkg.in/macaroon-bakery.v2/bakery"
22
25
"gopkg.in/macaroon.v2"
23
26
)
@@ -34,7 +37,8 @@ const (
34
37
// or REST request and delegate (and convert if necessary) it to the correct
35
38
// component.
36
39
func newRpcProxy (cfg * Config , validator macaroons.MacaroonValidator ,
37
- permissionMap map [string ][]bakery.Op ) * rpcProxy {
40
+ permissionMap map [string ][]bakery.Op ,
41
+ bufListener * bufconn.Listener ) * rpcProxy {
38
42
39
43
// The gRPC web calls are protected by HTTP basic auth which is defined
40
44
// by base64(username:password). Because we only have a password, we
@@ -52,6 +56,7 @@ func newRpcProxy(cfg *Config, validator macaroons.MacaroonValidator,
52
56
cfg : cfg ,
53
57
basicAuth : basicAuth ,
54
58
macValidator : validator ,
59
+ bufListener : bufListener ,
55
60
}
56
61
p .grpcServer = grpc .NewServer (
57
62
// From the grpxProxy doc: This codec is *crucial* to the
@@ -125,6 +130,9 @@ type rpcProxy struct {
125
130
basicAuth string
126
131
127
132
macValidator macaroons.MacaroonValidator
133
+ bufListener * bufconn.Listener
134
+
135
+ superMacaroon string
128
136
129
137
lndConn * grpc.ClientConn
130
138
faradayConn * grpc.ClientConn
@@ -140,8 +148,14 @@ func (p *rpcProxy) Start() error {
140
148
var err error
141
149
142
150
// Setup the connection to lnd.
143
- host , _ , tlsPath , _ := p .cfg .lndConnectParams ()
144
- p .lndConn , err = dialBackend ("lnd" , host , tlsPath )
151
+ host , _ , tlsPath , _ , _ := p .cfg .lndConnectParams ()
152
+
153
+ // We use a bufconn to connect to lnd in integrated mode.
154
+ if p .cfg .LndMode == ModeIntegrated {
155
+ p .lndConn , err = dialBufConnBackend (p .bufListener )
156
+ } else {
157
+ p .lndConn , err = dialBackend ("lnd" , host , tlsPath )
158
+ }
145
159
if err != nil {
146
160
return fmt .Errorf ("could not dial lnd: %v" , err )
147
161
}
@@ -390,10 +404,13 @@ func (p *rpcProxy) basicAuthToMacaroon(ctx context.Context,
390
404
return ctx , nil
391
405
}
392
406
393
- var macPath string
407
+ var (
408
+ macPath string
409
+ macData []byte
410
+ )
394
411
switch {
395
412
case isLndURI (requestURI ):
396
- _ , _ , _ , macPath = p .cfg .lndConnectParams ()
413
+ _ , _ , _ , macPath , macData = p .cfg .lndConnectParams ()
397
414
398
415
case isFaradayURI (requestURI ):
399
416
if p .cfg .faradayRemote {
@@ -421,16 +438,64 @@ func (p *rpcProxy) basicAuthToMacaroon(ctx context.Context,
421
438
requestURI )
422
439
}
423
440
424
- // Now that we know which macaroon to load, do it and attach it to the
425
- // request context.
426
- macBytes , err := readMacaroon (lncfg .CleanAndExpandPath (macPath ))
427
- if err != nil {
428
- return ctx , fmt .Errorf ("error reading macaroon: %v" , err )
441
+ switch {
442
+ // If we have a super macaroon, we can use that one directly since it
443
+ // will contain all permissions we need.
444
+ case len (p .superMacaroon ) > 0 :
445
+ md .Set (HeaderMacaroon , p .superMacaroon )
446
+
447
+ // If we have macaroon data directly, just encode them. This could be
448
+ // for initial requests to lnd while we don't have the super macaroon
449
+ // just yet (or are actually calling to bake the super macaroon).
450
+ case len (macData ) > 0 :
451
+ md .Set (HeaderMacaroon , hex .EncodeToString (macData ))
452
+
453
+ // The fall back is to read the macaroon from a path. This is in remote
454
+ // mode.
455
+ case len (macPath ) > 0 :
456
+ // Now that we know which macaroon to load, do it and attach it
457
+ // to the request context.
458
+ macBytes , err := readMacaroon (lncfg .CleanAndExpandPath (macPath ))
459
+ if err != nil {
460
+ return ctx , fmt .Errorf ("error reading macaroon %s: %v" ,
461
+ lncfg .CleanAndExpandPath (macPath ), err )
462
+ }
463
+
464
+ md .Set (HeaderMacaroon , hex .EncodeToString (macBytes ))
429
465
}
430
- md . Set ( HeaderMacaroon , hex . EncodeToString ( macBytes ))
466
+
431
467
return metadata .NewIncomingContext (ctx , md ), nil
432
468
}
433
469
470
+ // dialBufConnBackend dials an in-memory connection to an RPC listener and
471
+ // ignores any TLS certificate mismatches.
472
+ func dialBufConnBackend (listener * bufconn.Listener ) (* grpc.ClientConn , error ) {
473
+ tlsConfig := credentials .NewTLS (& tls.Config {
474
+ InsecureSkipVerify : true ,
475
+ })
476
+ conn , err := grpc .Dial (
477
+ "" ,
478
+ grpc .WithContextDialer (
479
+ func (context.Context , string ) (net.Conn , error ) {
480
+ return listener .Dial ()
481
+ },
482
+ ),
483
+ grpc .WithTransportCredentials (tlsConfig ),
484
+
485
+ // From the grpcProxy doc: This codec is *crucial* to the
486
+ // functioning of the proxy.
487
+ grpc .WithCodec (grpcProxy .Codec ()), // nolint
488
+ grpc .WithTransportCredentials (tlsConfig ),
489
+ grpc .WithDefaultCallOptions (maxMsgRecvSize ),
490
+ grpc .WithConnectParams (grpc.ConnectParams {
491
+ Backoff : backoff .DefaultConfig ,
492
+ MinConnectTimeout : defaultConnectTimeout ,
493
+ }),
494
+ )
495
+
496
+ return conn , err
497
+ }
498
+
434
499
// dialBackend connects to a gRPC backend through the given address and uses the
435
500
// given TLS certificate to authenticate the connection.
436
501
func dialBackend (name , dialAddr , tlsCertPath string ) (* grpc.ClientConn , error ) {
@@ -470,12 +535,12 @@ func readMacaroon(macPath string) ([]byte, error) {
470
535
// Load the specified macaroon file.
471
536
macBytes , err := ioutil .ReadFile (macPath )
472
537
if err != nil {
473
- return nil , fmt .Errorf ("unable to read macaroon path : %v" , err )
538
+ return nil , fmt .Errorf ("unable to read macaroon path: %v" , err )
474
539
}
475
540
476
541
// Make sure it actually is a macaroon by parsing it.
477
542
mac := & macaroon.Macaroon {}
478
- if err = mac .UnmarshalBinary (macBytes ); err != nil {
543
+ if err : = mac .UnmarshalBinary (macBytes ); err != nil {
479
544
return nil , fmt .Errorf ("unable to decode macaroon: %v" , err )
480
545
}
481
546
0 commit comments