Skip to content

Commit 08dc215

Browse files
authored
Merge pull request lightninglabs#58 from carlaKC/configfile-flag
aperture: allow command line flags and add config file
2 parents 83a657d + 0b81282 commit 08dc215

File tree

3 files changed

+118
-19
lines changed

3 files changed

+118
-19
lines changed

aperture.go

Lines changed: 69 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package aperture
22

33
import (
44
"crypto/tls"
5+
"errors"
56
"fmt"
67
"io"
78
"io/ioutil"
@@ -11,9 +12,11 @@ import (
1112
"sync"
1213
"time"
1314

15+
flags "github.com/jessevdk/go-flags"
1416
"github.com/lightninglabs/aperture/auth"
1517
"github.com/lightninglabs/aperture/mint"
1618
"github.com/lightninglabs/aperture/proxy"
19+
"github.com/lightningnetwork/lnd"
1720
"github.com/lightningnetwork/lnd/build"
1821
"github.com/lightningnetwork/lnd/cert"
1922
"github.com/lightningnetwork/lnd/lnrpc"
@@ -71,10 +74,21 @@ var (
7174
func Main() {
7275
// TODO: Prevent from running twice.
7376
err := run()
74-
if err != nil {
75-
_, _ = fmt.Fprintln(os.Stderr, err)
76-
os.Exit(1)
77+
78+
// Unwrap our error and check whether help was requested from our flag
79+
// library. If the error is not wrapped, Unwrap returns nil. It is
80+
// still safe to check the type of this nil error.
81+
flagErr, isFlagErr := errors.Unwrap(err).(*flags.Error)
82+
isHelpErr := isFlagErr && flagErr.Type == flags.ErrHelp
83+
84+
// If we got a nil error, or help was requested, just exit.
85+
if err == nil || isHelpErr {
86+
os.Exit(0)
7787
}
88+
89+
// Print any other non-help related errors.
90+
_, _ = fmt.Fprintln(os.Stderr, err)
91+
os.Exit(1)
7892
}
7993

8094
// run sets up the proxy server and runs it. This function blocks until a
@@ -88,10 +102,9 @@ func run() error {
88102
}
89103

90104
// Next, parse configuration file and set up logging.
91-
configFile := filepath.Join(apertureDataDir, defaultConfigFilename)
92-
cfg, err := getConfig(configFile)
105+
cfg, err := getConfig()
93106
if err != nil {
94-
return fmt.Errorf("unable to parse config file: %v", err)
107+
return fmt.Errorf("unable to parse config file: %w", err)
95108
}
96109
err = setupLogging(cfg, interceptor)
97110
if err != nil {
@@ -305,22 +318,66 @@ func fileExists(name string) bool {
305318

306319
// getConfig loads and parses the configuration file then checks it for valid
307320
// content.
308-
func getConfig(configFile string) (*Config, error) {
321+
func getConfig() (*Config, error) {
322+
// Pre-parse command line flags to determine whether we've been pointed
323+
// to a custom config file.
309324
cfg := &Config{}
325+
if _, err := flags.Parse(cfg); err != nil {
326+
return nil, err
327+
}
328+
329+
// If a custom config file is provided, we require that it exists.
330+
var mustExist bool
331+
332+
configFile := filepath.Join(apertureDataDir, defaultConfigFilename)
333+
if cfg.ConfigFile != "" {
334+
configFile = lnd.CleanAndExpandPath(cfg.ConfigFile)
335+
mustExist = true
336+
}
337+
338+
// Read our config file, either from the custom path provided or our
339+
// default location.
310340
b, err := ioutil.ReadFile(configFile)
311-
if err != nil {
341+
switch {
342+
// If the file was found, unmarshal it.
343+
case err == nil:
344+
err = yaml.Unmarshal(b, cfg)
345+
if err != nil {
346+
return nil, err
347+
}
348+
349+
// If the error is unrelated to the existence of the file, we must
350+
// always return it.
351+
case !os.IsNotExist(err):
312352
return nil, err
353+
354+
// If we require that the config file exists and we got an error
355+
// related to file existence, we must fail.
356+
case mustExist && os.IsNotExist(err):
357+
return nil, fmt.Errorf("config file: %v must exist: %w",
358+
configFile, err)
313359
}
314-
err = yaml.Unmarshal(b, cfg)
315-
if err != nil {
360+
361+
// Finally, parse the remaining command line options again to ensure
362+
// they take precedence.
363+
if _, err := flags.Parse(cfg); err != nil {
316364
return nil, err
317365
}
318366

367+
// Clean and expand our cert and macaroon paths.
368+
cfg.Authenticator.TLSPath = lnd.CleanAndExpandPath(
369+
cfg.Authenticator.TLSPath,
370+
)
371+
cfg.Authenticator.MacDir = lnd.CleanAndExpandPath(
372+
cfg.Authenticator.MacDir,
373+
)
374+
319375
// Then check the configuration that we got from the config file, all
320376
// required values need to be set at this point.
321-
if cfg.ListenAddr == "" {
322-
return nil, fmt.Errorf("missing listen address for server")
377+
if err := cfg.validate(); err != nil {
378+
return nil, err
323379
}
380+
324381
return cfg, nil
325382
}
326383

config.go

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package aperture
22

33
import (
4+
"errors"
5+
"fmt"
6+
47
"github.com/btcsuite/btcutil"
58
"github.com/lightninglabs/aperture/proxy"
69
)
@@ -26,13 +29,34 @@ type AuthConfig struct {
2629
// LndHost is the hostname of the LND instance to connect to.
2730
LndHost string `long:"lndhost" description:"Hostname of the LND instance to connect to"`
2831

29-
TLSPath string `long:"tlspath"`
32+
TLSPath string `long:"tlspath" description:"Path to LND instance's tls certificate"`
33+
34+
MacDir string `long:"macdir" description:"Directory containing LND instance's macaroons"`
35+
36+
Network string `long:"network" description:"The network LND is connected to." choice:"regtest" choice:"simnet" choice:"testnet" choice:"mainnet"`
37+
38+
Disable bool `long:"disable" description:"Whether to disable LND auth."`
39+
}
40+
41+
func (a *AuthConfig) validate() error {
42+
// If we're disabled, we don't mind what these values are.
43+
if a.Disable {
44+
return nil
45+
}
3046

31-
MacDir string `long:"macdir"`
47+
if a.LndHost == "" {
48+
return errors.New("lnd host required")
49+
}
3250

33-
Network string `long:"network"`
51+
if a.TLSPath == "" {
52+
return errors.New("lnd tls required")
53+
}
3454

35-
Disable bool `long:"disable"`
55+
if a.MacDir == "" {
56+
return errors.New("lnd mac dir required")
57+
}
58+
59+
return nil
3660
}
3761

3862
type TorConfig struct {
@@ -67,11 +91,11 @@ type Config struct {
6791
// directory defined by StaticRoot.
6892
ServeStatic bool `long:"servestatic" description:"Flag to enable or disable static content serving."`
6993

70-
Etcd *EtcdConfig `long:"etcd" description:"Configuration for the etcd instance backing the proxy."`
94+
Etcd *EtcdConfig `group:"etcd" namespace:"etcd"`
7195

72-
Authenticator *AuthConfig `long:"authenticator" description:"Configuration for the authenticator."`
96+
Authenticator *AuthConfig `group:"authenticator" namespace:"authenticator"`
7397

74-
Tor *TorConfig `long:"tor" description:"Configuration for the Tor instance backing the proxy."`
98+
Tor *TorConfig `group:"tor" namespace:"tor"`
7599

76100
// Services is a list of JSON objects in string format, which specify
77101
// each backend service to Aperture.
@@ -80,4 +104,21 @@ type Config struct {
80104
// DebugLevel is a string defining the log level for the service either
81105
// for all subsystems the same or individual level by subsystem.
82106
DebugLevel string `long:"debuglevel" description:"Debug level for the Aperture application and its subsystems."`
107+
108+
// ConfigFile points aperture to an alternative config file.
109+
ConfigFile string `long:"configfile" description:"Custom path to a config file."`
110+
}
111+
112+
func (c *Config) validate() error {
113+
if c.Authenticator != nil {
114+
if err := c.Authenticator.validate(); err != nil {
115+
return err
116+
}
117+
}
118+
119+
if c.ListenAddr == "" {
120+
return fmt.Errorf("missing listen address for server")
121+
}
122+
123+
return nil
83124
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/btcsuite/btcwallet/wtxmgr v1.3.1-0.20210706234807-aaf03fee735a
1010
github.com/fortytw2/leaktest v1.3.0
1111
github.com/golang/protobuf v1.5.2
12+
github.com/jessevdk/go-flags v1.4.0
1213
github.com/lightninglabs/lndclient v0.12.0-9
1314
github.com/lightningnetwork/lnd v0.13.0-beta.rc5.0.20210728112744-ebabda671786
1415
github.com/lightningnetwork/lnd/cert v1.0.3

0 commit comments

Comments
 (0)