Skip to content

basic_client: make latest change non-breaking #76

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 65 additions & 29 deletions basic_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,24 @@ import (
macaroon "gopkg.in/macaroon.v2"
)

// BasicClientOption is a functional option argument that allows adding arbitrary
// lnd basic client configuration overrides, without forcing existing users of
// NewBasicClient to update their invocation. These are always processed in
// order, with later options overriding earlier ones.
// BasicClientOption is a functional option argument that allows adding
// arbitrary lnd basic client configuration overrides, without forcing existing
// users of NewBasicClient to update their invocation. These are always
// processed in order, with later options overriding earlier ones.
type BasicClientOption func(*basicClientOptions)

// basicClientOptions is a set of options that can configure the lnd client
// returned by NewBasicClient.
type basicClientOptions struct {
macFilename string
tlsData string
macData string
insecure bool
systemCerts bool
}

// defaultBasicClientOptions returns a basicClientOptions set to lnd basic client
// defaults.
// defaultBasicClientOptions returns a basicClientOptions set to lnd basic
// client defaults.
func defaultBasicClientOptions() *basicClientOptions {
return &basicClientOptions{
macFilename: adminMacFilename,
Expand All @@ -42,9 +46,43 @@ func MacFilename(macFilename string) BasicClientOption {
}
}

// TLSData is a basic client option that sets TLS data (encoded in PEM format)
// directly instead of loading them from a file.
func TLSData(tlsData string) BasicClientOption {
return func(bc *basicClientOptions) {
bc.tlsData = tlsData
}
}

// MacaroonData is a basic client option that sets macaroon data (encoded as hex
// string) directly instead of loading it from a file.
func MacaroonData(macData string) BasicClientOption {
return func(bc *basicClientOptions) {
bc.macData = macData
}
}

// Insecure allows the basic client to establish an insecure (non-TLS)
// connection to the RPC server.
func Insecure() BasicClientOption {
return func(bc *basicClientOptions) {
bc.insecure = true
}
}

// SystemCerts instructs the basic client to use the system's certificate trust
// store for verifying the TLS certificate of the RPC server.
func SystemCerts() BasicClientOption {
return func(bc *basicClientOptions) {
bc.systemCerts = true
}
}

// applyBasicClientOptions updates a basicClientOptions set with functional
// options.
func (bc *basicClientOptions) applyBasicClientOptions(options ...BasicClientOption) {
func (bc *basicClientOptions) applyBasicClientOptions(
options ...BasicClientOption) {

for _, option := range options {
option(bc)
}
Expand All @@ -53,14 +91,11 @@ func (bc *basicClientOptions) applyBasicClientOptions(options ...BasicClientOpti
// NewBasicClient creates a new basic gRPC client to lnd. We call this client
// "basic" as it falls back to expected defaults if the arguments aren't
// provided.
func NewBasicClient(lndHost, tlsPath, macDir, tlsData, macData, network string,
insecure, systemCert bool, basicOptions ...BasicClientOption) (

lnrpc.LightningClient, error) {
func NewBasicClient(lndHost, tlsPath, macDir, network string,
basicOptions ...BasicClientOption) (lnrpc.LightningClient, error) {

conn, err := NewBasicConn(
lndHost, tlsPath, macDir, tlsData, macData, network, insecure,
systemCert, basicOptions...,
lndHost, tlsPath, macDir, network, basicOptions...,
)
if err != nil {
return nil, err
Expand All @@ -72,15 +107,13 @@ func NewBasicClient(lndHost, tlsPath, macDir, tlsData, macData, network string,
// NewBasicConn creates a new basic gRPC connection to lnd. We call this
// connection "basic" as it falls back to expected defaults if the arguments
// aren't provided.
func NewBasicConn(lndHost string, tlsPath, macDir, tlsData, macData,
network string, insecure, systemCert bool,
func NewBasicConn(lndHost string, tlsPath, macDir, network string,
basicOptions ...BasicClientOption) (

*grpc.ClientConn, error) {

creds, mac, err := parseTLSAndMacaroon(
tlsPath, macDir, tlsData, macData, network, insecure,
systemCert, basicOptions...,
tlsPath, macDir, network, basicOptions...,
)
if err != nil {
return nil, err
Expand All @@ -105,33 +138,36 @@ func NewBasicConn(lndHost string, tlsPath, macDir, tlsData, macData,
)
conn, err := grpc.Dial(lndHost, opts...)
if err != nil {
return nil, fmt.Errorf("unable to connect to RPC server: %v", err)
return nil, fmt.Errorf("unable to connect to RPC server: %v",
err)
}

return conn, nil
}

// parseTLSAndMacaroon looks to see if the TLS certificate and macaroon were
// passed in as a path or as straight-up data, and processes it accordingly so
// passed in as a path or as straight-up data, and processes it accordingly, so
// it can be passed into grpc to establish a connection with LND.
func parseTLSAndMacaroon(tlsPath, macDir, tlsData, macData, network string,
insecure, systemCert bool, basicOptions ...BasicClientOption) (
credentials.TransportCredentials, *macaroon.Macaroon, error) {

creds, err := GetTLSCredentials(tlsData, tlsPath, insecure, systemCert)
if err != nil {
return nil, nil, err
}
func parseTLSAndMacaroon(tlsPath, macDir, network string,
basicOptions ...BasicClientOption) (credentials.TransportCredentials,
*macaroon.Macaroon, error) {

// Starting with the set of default options, we'll apply any specified
// functional options to the basic client.
bco := defaultBasicClientOptions()
bco.applyBasicClientOptions(basicOptions...)

creds, err := GetTLSCredentials(
bco.tlsData, tlsPath, bco.insecure, bco.systemCerts,
)
if err != nil {
return nil, nil, err
}

var macBytes []byte
mac := &macaroon.Macaroon{}
if macData != "" {
macBytes, err = hex.DecodeString(macData)
if bco.macData != "" {
macBytes, err = hex.DecodeString(bco.macData)
if err != nil {
return nil, nil, err
}
Expand Down
7 changes: 3 additions & 4 deletions basic_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ XhkpT5dliEGFLNe6OOgeWTU1JpEXfCud/GImtNMHQi4EDWQfvWuCNGhOoQ==

// Make sure it works when data is passed in.
_, _, err := parseTLSAndMacaroon(
"", "", tlsData, macData, "mainnet", false, false,
MacFilename(""),
"", "", "mainnet", MacFilename(""), TLSData(tlsData),
MacaroonData(macData),
)
require.NoError(t, err)

Expand All @@ -65,8 +65,7 @@ XhkpT5dliEGFLNe6OOgeWTU1JpEXfCud/GImtNMHQi4EDWQfvWuCNGhOoQ==
require.NoError(t, err)

_, _, err = parseTLSAndMacaroon(
certPath, macPath, "", "", "mainnet", false, false,
MacFilename(""),
certPath, macPath, "mainnet", MacFilename(""),
)
require.NoError(t, err)
}
48 changes: 26 additions & 22 deletions lnd_services.go
Original file line number Diff line number Diff line change
Expand Up @@ -784,20 +784,21 @@ func getClientConn(cfg *LndServicesConfig) (*grpc.ClientConn, error) {

// GetTLSCredentials gets the tls credentials, whether provided as straight-up
// data or a path to a certificate file.
func GetTLSCredentials(tlsData, tlsPath string, insecure, systemCert bool) (
credentials.TransportCredentials, error) {

if tlsPath != "" && tlsData != "" {
return nil, fmt.Errorf("must set only one: TLSPath or TLSData")
}

var creds credentials.TransportCredentials
var err error
func GetTLSCredentials(tlsData, tlsPath string, insecure,
systemCert bool) (credentials.TransportCredentials, error) {

// We'll determine if the tls certificate is passed in directly as
// data, by a path, or try the system's certificate chain, and then
// load it.
var creds credentials.TransportCredentials
switch {
case tlsPath != "" && tlsData != "":
return nil, fmt.Errorf("must set only one: TLSPath or TLSData")

case insecure && systemCert:
return nil, fmt.Errorf("cannot set insecure and system cert " +
"at the same time")

case insecure:
// If we don't need to use tls, such as if we're connecting to
// lnd via a bufconn, then we'll skip verification.
Expand Down Expand Up @@ -833,26 +834,29 @@ func GetTLSCredentials(tlsData, tlsPath string, insecure, systemCert bool) (
creds = credentials.NewClientTLSFromCert(pool, "")

case tlsPath != "":
var err error
creds, err = credentials.NewClientTLSFromFile(tlsPath, "")
if err != nil {
return nil, err
}

default:
// If neither tlsData nor tlsPath were set, we'll try the default
// lnd tls cert path.
if _, err := os.Stat(defaultTLSCertPath); err == nil {
creds, err = credentials.NewClientTLSFromFile(
defaultTLSCertPath, "",
)
if err != nil {
return nil, err
}

} else {
return nil, err
// If neither tlsData nor tlsPath were set, we'll try the
// default lnd tls cert path.
_, err := os.Stat(defaultTLSCertPath)
if err != nil {
return nil, fmt.Errorf("couldn't find out if default "+
"lnd TLS cert at %s exists: %v",
defaultTLSCertPath, err)
}
creds, err = credentials.NewClientTLSFromFile(
defaultTLSCertPath, "",
)
if err != nil {
return nil, fmt.Errorf("couldn't load default lnd "+
"TLS cert at %s: %v", defaultTLSCertPath, err)
}
}

return creds, err
return creds, nil
}