Merge pull request #3783 from halseth/mobile-macaroons
[mobile] mobile macaroons support
This commit is contained in:
commit
773212bdf8
@ -109,6 +109,10 @@ func GenCertPair(org, certFile, keyFile string, tlsExtraIPs,
|
||||
// verification will fail in the client.
|
||||
dnsNames = append(dnsNames, "unix", "unixpacket")
|
||||
|
||||
// Also add hostnames for 'bufconn' which is the hostname used for the
|
||||
// in-memory connections used on mobile.
|
||||
dnsNames = append(dnsNames, "bufconn")
|
||||
|
||||
// Generate a private key for the certificate.
|
||||
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
|
97
lnd.go
97
lnd.go
@ -22,6 +22,7 @@ import (
|
||||
_ "net/http/pprof"
|
||||
|
||||
"gopkg.in/macaroon-bakery.v2/bakery"
|
||||
"gopkg.in/macaroon.v2"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
@ -59,6 +60,45 @@ var (
|
||||
networkDir string
|
||||
)
|
||||
|
||||
// AdminAuthOptions returns a list of DialOptions that can be used to
|
||||
// authenticate with the RPC server with admin capabilities.
|
||||
//
|
||||
// NOTE: This should only be called after the RPCListener has signaled it is
|
||||
// ready.
|
||||
func AdminAuthOptions() ([]grpc.DialOption, error) {
|
||||
creds, err := credentials.NewClientTLSFromFile(cfg.TLSCertPath, "")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read TLS cert: %v", err)
|
||||
}
|
||||
|
||||
// Create a dial options array.
|
||||
opts := []grpc.DialOption{
|
||||
grpc.WithTransportCredentials(creds),
|
||||
}
|
||||
|
||||
// Get the admin macaroon if macaroons are active.
|
||||
if !cfg.NoMacaroons {
|
||||
// Load the adming macaroon file.
|
||||
macBytes, err := ioutil.ReadFile(cfg.AdminMacPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read macaroon "+
|
||||
"path (check the network setting!): %v", err)
|
||||
}
|
||||
|
||||
mac := &macaroon.Macaroon{}
|
||||
if err = mac.UnmarshalBinary(macBytes); err != nil {
|
||||
return nil, fmt.Errorf("unable to decode macaroon: %v",
|
||||
err)
|
||||
}
|
||||
|
||||
// Now we append the macaroon credentials to the dial options.
|
||||
cred := macaroons.NewMacaroonCredential(mac)
|
||||
opts = append(opts, grpc.WithPerRPCCredentials(cred))
|
||||
}
|
||||
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
// ListnerWithSignal is a net.Listner that has an additional Ready channel that
|
||||
// will be closed when a server starts listening.
|
||||
type ListenerWithSignal struct {
|
||||
@ -81,12 +121,11 @@ type ListenerCfg struct {
|
||||
}
|
||||
|
||||
// rpcListeners is a function type used for closures that fetches a set of RPC
|
||||
// listeners for the current configuration, and the GRPC server options to use
|
||||
// with these listeners. If no custom listeners are present, this should return
|
||||
// normal listeners from the RPC endpoints defined in the config, and server
|
||||
// options specifying TLS.
|
||||
type rpcListeners func() ([]*ListenerWithSignal, func(), []grpc.ServerOption,
|
||||
error)
|
||||
// listeners for the current configuration. If no custom listeners are present,
|
||||
// this should return normal listeners from the RPC endpoints defined in the
|
||||
// config. The second return value us a closure that will close the fetched
|
||||
// listeners.
|
||||
type rpcListeners func() ([]*ListenerWithSignal, func(), error)
|
||||
|
||||
// Main is the true entry point for lnd. This function is required since defers
|
||||
// created in the top-level scope of a main method aren't executed if os.Exit()
|
||||
@ -245,9 +284,7 @@ func Main(lisCfg ListenerCfg) error {
|
||||
// getListeners is a closure that creates listeners from the
|
||||
// RPCListeners defined in the config. It also returns a cleanup
|
||||
// closure and the server options to use for the GRPC server.
|
||||
getListeners := func() ([]*ListenerWithSignal, func(),
|
||||
[]grpc.ServerOption, error) {
|
||||
|
||||
getListeners := func() ([]*ListenerWithSignal, func(), error) {
|
||||
var grpcListeners []*ListenerWithSignal
|
||||
for _, grpcEndpoint := range cfg.RPCListeners {
|
||||
// Start a gRPC server listening for HTTP/2
|
||||
@ -256,7 +293,7 @@ func Main(lisCfg ListenerCfg) error {
|
||||
if err != nil {
|
||||
ltndLog.Errorf("unable to listen on %s",
|
||||
grpcEndpoint)
|
||||
return nil, nil, nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
grpcListeners = append(
|
||||
grpcListeners, &ListenerWithSignal{
|
||||
@ -270,23 +307,20 @@ func Main(lisCfg ListenerCfg) error {
|
||||
lis.Close()
|
||||
}
|
||||
}
|
||||
return grpcListeners, cleanup, serverOpts, nil
|
||||
return grpcListeners, cleanup, nil
|
||||
}
|
||||
|
||||
// walletUnlockerListeners is a closure we'll hand to the wallet
|
||||
// unlocker, that will be called when it needs listeners for its GPRC
|
||||
// server.
|
||||
walletUnlockerListeners := func() ([]*ListenerWithSignal, func(),
|
||||
[]grpc.ServerOption, error) {
|
||||
error) {
|
||||
|
||||
// If we have chosen to start with a dedicated listener for the
|
||||
// wallet unlocker, we return it directly, and empty server
|
||||
// options to deactivate TLS.
|
||||
// TODO(halseth): any point in adding TLS support for custom
|
||||
// listeners?
|
||||
// wallet unlocker, we return it directly.
|
||||
if lisCfg.WalletUnlocker != nil {
|
||||
return []*ListenerWithSignal{lisCfg.WalletUnlocker},
|
||||
func() {}, []grpc.ServerOption{}, nil
|
||||
func() {}, nil
|
||||
}
|
||||
|
||||
// Otherwise we'll return the regular listeners.
|
||||
@ -298,8 +332,8 @@ func Main(lisCfg ListenerCfg) error {
|
||||
// for wallet encryption.
|
||||
if !cfg.NoSeedBackup {
|
||||
params, err := waitForWalletPassword(
|
||||
cfg.RESTListeners, restDialOpts, restProxyDest, tlsCfg,
|
||||
walletUnlockerListeners,
|
||||
cfg.RESTListeners, serverOpts, restDialOpts,
|
||||
restProxyDest, tlsCfg, walletUnlockerListeners,
|
||||
)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Unable to set up wallet password "+
|
||||
@ -515,17 +549,12 @@ func Main(lisCfg ListenerCfg) error {
|
||||
|
||||
// rpcListeners is a closure we'll hand to the rpc server, that will be
|
||||
// called when it needs listeners for its GPRC server.
|
||||
rpcListeners := func() ([]*ListenerWithSignal, func(),
|
||||
[]grpc.ServerOption, error) {
|
||||
|
||||
rpcListeners := func() ([]*ListenerWithSignal, func(), error) {
|
||||
// If we have chosen to start with a dedicated listener for the
|
||||
// rpc server, we return it directly, and empty server options
|
||||
// to deactivate TLS.
|
||||
// TODO(halseth): any point in adding TLS support for custom
|
||||
// listeners?
|
||||
// rpc server, we return it directly.
|
||||
if lisCfg.RPCListener != nil {
|
||||
return []*ListenerWithSignal{lisCfg.RPCListener},
|
||||
func() {}, []grpc.ServerOption{}, nil
|
||||
func() {}, nil
|
||||
}
|
||||
|
||||
// Otherwise we'll return the regular listeners.
|
||||
@ -535,9 +564,9 @@ func Main(lisCfg ListenerCfg) error {
|
||||
// Initialize, and register our implementation of the gRPC interface
|
||||
// exported by the rpcServer.
|
||||
rpcServer, err := newRPCServer(
|
||||
server, macaroonService, cfg.SubRPCServers, restDialOpts,
|
||||
restProxyDest, atplManager, server.invoices, tower, tlsCfg,
|
||||
rpcListeners, chainedAcceptor,
|
||||
server, macaroonService, cfg.SubRPCServers, serverOpts,
|
||||
restDialOpts, restProxyDest, atplManager, server.invoices,
|
||||
tower, tlsCfg, rpcListeners, chainedAcceptor,
|
||||
)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Unable to create RPC server: %v", err)
|
||||
@ -813,13 +842,13 @@ type WalletUnlockParams struct {
|
||||
// WalletUnlocker server, and block until a password is provided by
|
||||
// the user to this RPC server.
|
||||
func waitForWalletPassword(restEndpoints []net.Addr,
|
||||
restDialOpts []grpc.DialOption, restProxyDest string,
|
||||
tlsConf *tls.Config, getListeners rpcListeners) (
|
||||
*WalletUnlockParams, error) {
|
||||
serverOpts []grpc.ServerOption, restDialOpts []grpc.DialOption,
|
||||
restProxyDest string, tlsConf *tls.Config,
|
||||
getListeners rpcListeners) (*WalletUnlockParams, error) {
|
||||
|
||||
// Start a gRPC server listening for HTTP/2 connections, solely used
|
||||
// for getting the encryption password from the client.
|
||||
listeners, cleanup, serverOpts, err := getListeners()
|
||||
listeners, cleanup, err := getListeners()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -79,6 +79,19 @@ func Start(extraArgs string, unlockerReady, rpcReady Callback) {
|
||||
|
||||
go func() {
|
||||
<-rpcListening
|
||||
|
||||
// Now that the RPC server is ready, we can get the needed
|
||||
// authentication options, and add them to the global dial
|
||||
// options.
|
||||
auth, err := lnd.AdminAuthOptions()
|
||||
if err != nil {
|
||||
rpcReady.OnError(err)
|
||||
return
|
||||
}
|
||||
|
||||
// Add the auth options to the listener's dial options.
|
||||
addLightningLisDialOption(auth...)
|
||||
|
||||
rpcReady.OnResponse([]byte{})
|
||||
}()
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
mkdir -p build
|
||||
|
||||
# Check falafel version.
|
||||
falafelVersion="0.5"
|
||||
falafelVersion="0.6"
|
||||
falafel=$(which falafel)
|
||||
if [ $falafel ]
|
||||
then
|
||||
|
@ -1,6 +1,5 @@
|
||||
[Application Options]
|
||||
debuglevel=info
|
||||
no-macaroons=1
|
||||
maxbackoff=2s
|
||||
nolisten=1
|
||||
norest=1
|
||||
|
11
rpcserver.go
11
rpcserver.go
@ -508,10 +508,11 @@ var _ lnrpc.LightningServer = (*rpcServer)(nil)
|
||||
// base level options passed to the grPC server. This typically includes things
|
||||
// like requiring TLS, etc.
|
||||
func newRPCServer(s *server, macService *macaroons.Service,
|
||||
subServerCgs *subRPCServerConfigs, restDialOpts []grpc.DialOption,
|
||||
restProxyDest string, atpl *autopilot.Manager,
|
||||
invoiceRegistry *invoices.InvoiceRegistry, tower *watchtower.Standalone,
|
||||
tlsCfg *tls.Config, getListeners rpcListeners,
|
||||
subServerCgs *subRPCServerConfigs, serverOpts []grpc.ServerOption,
|
||||
restDialOpts []grpc.DialOption, restProxyDest string,
|
||||
atpl *autopilot.Manager, invoiceRegistry *invoices.InvoiceRegistry,
|
||||
tower *watchtower.Standalone, tlsCfg *tls.Config,
|
||||
getListeners rpcListeners,
|
||||
chanPredicate *chanacceptor.ChainedAcceptor) (*rpcServer, error) {
|
||||
|
||||
// Set up router rpc backend.
|
||||
@ -643,7 +644,7 @@ func newRPCServer(s *server, macService *macaroons.Service,
|
||||
)
|
||||
|
||||
// Get the listeners and server options to use for this rpc server.
|
||||
listeners, cleanup, serverOpts, err := getListeners()
|
||||
listeners, cleanup, err := getListeners()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user