@@ -2,10 +2,12 @@ package terminal
22
33import (
44 "context"
5+ "crypto/tls"
56 "encoding/base64"
67 "encoding/hex"
78 "fmt"
89 "io/ioutil"
10+ "net"
911 "net/http"
1012 "strings"
1113 "time"
@@ -18,6 +20,7 @@ import (
1820 "google.golang.org/grpc/backoff"
1921 "google.golang.org/grpc/credentials"
2022 "google.golang.org/grpc/metadata"
23+ "google.golang.org/grpc/test/bufconn"
2124 "gopkg.in/macaroon-bakery.v2/bakery"
2225 "gopkg.in/macaroon.v2"
2326)
@@ -34,7 +37,8 @@ const (
3437// or REST request and delegate (and convert if necessary) it to the correct
3538// component.
3639func newRpcProxy (cfg * Config , validator macaroons.MacaroonValidator ,
37- permissionMap map [string ][]bakery.Op ) * rpcProxy {
40+ permissionMap map [string ][]bakery.Op ,
41+ bufListener * bufconn.Listener ) * rpcProxy {
3842
3943 // The gRPC web calls are protected by HTTP basic auth which is defined
4044 // by base64(username:password). Because we only have a password, we
@@ -52,6 +56,7 @@ func newRpcProxy(cfg *Config, validator macaroons.MacaroonValidator,
5256 cfg : cfg ,
5357 basicAuth : basicAuth ,
5458 macValidator : validator ,
59+ bufListener : bufListener ,
5560 }
5661 p .grpcServer = grpc .NewServer (
5762 // From the grpxProxy doc: This codec is *crucial* to the
@@ -125,6 +130,9 @@ type rpcProxy struct {
125130 basicAuth string
126131
127132 macValidator macaroons.MacaroonValidator
133+ bufListener * bufconn.Listener
134+
135+ superMacaroon string
128136
129137 lndConn * grpc.ClientConn
130138 faradayConn * grpc.ClientConn
@@ -140,8 +148,14 @@ func (p *rpcProxy) Start() error {
140148 var err error
141149
142150 // 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+ }
145159 if err != nil {
146160 return fmt .Errorf ("could not dial lnd: %v" , err )
147161 }
@@ -390,10 +404,13 @@ func (p *rpcProxy) basicAuthToMacaroon(ctx context.Context,
390404 return ctx , nil
391405 }
392406
393- var macPath string
407+ var (
408+ macPath string
409+ macData []byte
410+ )
394411 switch {
395412 case isLndURI (requestURI ):
396- _ , _ , _ , macPath = p .cfg .lndConnectParams ()
413+ _ , _ , _ , macPath , macData = p .cfg .lndConnectParams ()
397414
398415 case isFaradayURI (requestURI ):
399416 if p .cfg .faradayRemote {
@@ -421,16 +438,64 @@ func (p *rpcProxy) basicAuthToMacaroon(ctx context.Context,
421438 requestURI )
422439 }
423440
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 ))
429465 }
430- md . Set ( HeaderMacaroon , hex . EncodeToString ( macBytes ))
466+
431467 return metadata .NewIncomingContext (ctx , md ), nil
432468}
433469
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+
434499// dialBackend connects to a gRPC backend through the given address and uses the
435500// given TLS certificate to authenticate the connection.
436501func dialBackend (name , dialAddr , tlsCertPath string ) (* grpc.ClientConn , error ) {
@@ -470,12 +535,12 @@ func readMacaroon(macPath string) ([]byte, error) {
470535 // Load the specified macaroon file.
471536 macBytes , err := ioutil .ReadFile (macPath )
472537 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 )
474539 }
475540
476541 // Make sure it actually is a macaroon by parsing it.
477542 mac := & macaroon.Macaroon {}
478- if err = mac .UnmarshalBinary (macBytes ); err != nil {
543+ if err : = mac .UnmarshalBinary (macBytes ); err != nil {
479544 return nil , fmt .Errorf ("unable to decode macaroon: %v" , err )
480545 }
481546
0 commit comments