Skip to content

Commit f554957

Browse files
committed
tapcfg: add price oracle TLS config
We don't skip certificate verification by default, and also default to trusting the operating system's root CA list.
1 parent 2557d9d commit f554957

File tree

5 files changed

+92
-16
lines changed

5 files changed

+92
-16
lines changed

rfq/cli.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ const (
2222
type CliConfig struct {
2323
PriceOracleAddress string `long:"priceoracleaddress" description:"Price oracle gRPC server address (rfqrpc://<hostname>:<port>). To use the integrated mock, use the following value: use_mock_price_oracle_service_promise_to_not_use_on_mainnet"`
2424

25+
PriceOracleTLS bool `long:"priceoracletls" description:"Enable TLS for communication with a price oracle."`
26+
27+
PriceOracleTLSInsecure bool `long:"priceoracletlsinsecure" description:"Disable verification of price oracle certificates."`
28+
29+
PriceOracleTLSNoSystemCAs bool `long:"priceoracletlsnosystemcas" description:"Disable use of the operating system's list of root CA's when verifiying price oracle certificates."`
30+
31+
PriceOracleTLSCertPath string `long:"priceoracletlscertpath" description:"Path to a PEM-encoded x509 certificate to use when constructing a TLS connection with a price oracle."`
32+
2533
SendPriceHint bool `long:"sendpricehint" description:"Send a price hint from the local price oracle to the RFQ peer when requesting a quote. For privacy reasons, this should only be turned on for self-hosted or trusted price oracles."`
2634

2735
PriceOracleSendPeerId bool `long:"priceoraclesendpeerid" description:"Send the peer ID (public key of the peer) to the price oracle when requesting a price rate. For privacy reasons, this should only be turned on for self-hosted or trusted price oracles."`

rfq/tls.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,6 @@ type TLSConfig struct {
2525
CustomCertificates []byte
2626
}
2727

28-
// DefaultTLSConfig returns a default TLS configuration.
29-
func DefaultTLSConfig() *TLSConfig {
30-
return &TLSConfig{
31-
InsecureSkipVerify: true,
32-
}
33-
}
34-
3528
// configureTransportCredentials configures the TLS transport credentials to
3629
// be used for RPC connections.
3730
func configureTransportCredentials(

sample-tapd.conf

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
; always set to false.
1212

1313
; If only one value is specified for an option, then this is also the
14-
; default value used by tapd. In case of multiple (example) values, the default
15-
; is explicitly mentioned.
14+
; default value used by tapd. In case of multiple (example) values, the default
15+
; is explicitly mentioned.
1616
; If the part after the equal sign is empty then tapd has no default for this
1717
; option.
1818

@@ -446,6 +446,21 @@
446446
; use_mock_price_oracle_service_promise_to_not_use_on_mainnet
447447
; experimental.rfq.priceoracleaddress=
448448

449+
; Enable TLS for price oracle communication.
450+
; experimental.rfq.priceoracletls=true
451+
452+
; Skip price oracle certificate verification, yielding an insecure (cleartext)
453+
; channel with the price oracle. Should only be used for testing.
454+
; experimental.rfq.priceoracletlsinsecure=false
455+
456+
; Disable use of the operating system's root CA list when verifying a
457+
; price oracle's certificate.
458+
; experimental.rfq.priceoracletlsnosystemcas=false
459+
460+
; Path to a custom certificate (root CA or self-signed) to be used to
461+
; secure communication with a price oracle.
462+
; experimental.rfq.priceoracletlscertpath=
463+
449464
; Send a price hint from the local price oracle to the RFQ peer when requesting
450465
; a quote. For privacy reasons, this should only be turned on for self-hosted or
451466
; trusted price oracles.
@@ -456,7 +471,7 @@
456471
; self-hosted or trusted price oracles.
457472
; experimental.rfq.priceoraclesendpeerid=false
458473

459-
; The default price deviation inparts per million that is accepted by
474+
; The default price deviation inparts per million that is accepted by
460475
; the RFQ negotiator.
461476
; Example: 50,000 ppm => price deviation is set to 5% .
462477
; experimental.rfq.acceptpricedeviationppm=50000

tapcfg/config.go

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,24 @@ const (
148148
// DefaultPsbtMaxFeeRatio is the default maximum for fees to total
149149
// output amount ratio to use when funding PSBTs.
150150
DefaultPsbtMaxFeeRatio = lndservices.DefaultPsbtMaxFeeRatio
151+
152+
// defaultPriceOracleTLS is the default TLS setting to use when
153+
// communicating with price oracles.
154+
defaultPriceOracleTLS = true
155+
156+
// defaultPriceOracleTLSInsecure is the default value we'll use for
157+
// deciding to verify certificates in TLS connections with price
158+
// oracles.
159+
defaultPriceOracleTLSInsecure = false
160+
161+
// defaultPriceOracleNoSystemCAs is the default value we'll use
162+
// regarding trust of the operating system's root CA list. We'll use
163+
// 'false', i.e. we will trust the OS root CA list by default.
164+
defaultPriceOracleTLSNoSystemCAs = false
165+
166+
// defaultPriceOracleTLSCertPath is the default (empty) path to a
167+
// certificate to use for securing price oracle communication.
168+
defaultPriceOracleTLSCertPath = ""
151169
)
152170

153171
var (
@@ -335,8 +353,11 @@ type ExperimentalConfig struct {
335353
Rfq rfq.CliConfig `group:"rfq" namespace:"rfq"`
336354
}
337355

338-
// Validate returns an error if the configuration is invalid.
339-
func (c *ExperimentalConfig) Validate() error {
356+
// CleanAndValidate performs final processing on the ExperimentalConfig,
357+
// returning an error if the configuration is invalid.
358+
func (c *ExperimentalConfig) CleanAndValidate() error {
359+
c.Rfq.PriceOracleTLSCertPath = CleanAndExpandPath(
360+
c.Rfq.PriceOracleTLSCertPath)
340361
return c.Rfq.Validate()
341362
}
342363

@@ -502,7 +523,11 @@ func DefaultConfig() Config {
502523
},
503524
Experimental: &ExperimentalConfig{
504525
Rfq: rfq.CliConfig{
505-
AcceptPriceDeviationPpm: rfq.DefaultAcceptPriceDeviationPpm,
526+
AcceptPriceDeviationPpm: rfq.DefaultAcceptPriceDeviationPpm,
527+
PriceOracleTLS: defaultPriceOracleTLS,
528+
PriceOracleTLSInsecure: defaultPriceOracleTLSInsecure,
529+
PriceOracleTLSNoSystemCAs: defaultPriceOracleTLSNoSystemCAs,
530+
PriceOracleTLSCertPath: defaultPriceOracleTLSCertPath,
506531
},
507532
},
508533
}
@@ -938,8 +963,8 @@ func ValidateConfig(cfg Config, cfgLogger btclog.Logger) (*Config, error) {
938963
}
939964
}
940965

941-
// Validate the experimental command line config.
942-
err = cfg.Experimental.Validate()
966+
// Clean and validate the experimental command line config.
967+
err = cfg.Experimental.CleanAndValidate()
943968
if err != nil {
944969
return nil, fmt.Errorf("error in experimental command line "+
945970
"config: %w", err)
@@ -1184,6 +1209,35 @@ func getCertificateConfig(cfg *Config, cfgLogger btclog.Logger) (*tls.Config,
11841209
return tlsCfg, restCreds, nil
11851210
}
11861211

1212+
// getPriceOracleTLSConfig returns a TLS configuration for a price oracle,
1213+
// given a valid RFQ CLI configuration.
1214+
func getPriceOracleTLSConfig(rfqCfg rfq.CliConfig) (*rfq.TLSConfig, error) {
1215+
var certBytes []byte
1216+
1217+
// Read any specified certificate data.
1218+
if rfqCfg.PriceOracleTLSCertPath != "" {
1219+
var err error
1220+
certBytes, err = os.ReadFile(
1221+
rfqCfg.PriceOracleTLSCertPath)
1222+
if err != nil {
1223+
return nil, fmt.Errorf("unable to read "+
1224+
"price oracle certificate: %w", err)
1225+
}
1226+
}
1227+
1228+
// Construct the oracle's TLS configuration.
1229+
tlsConfig := &rfq.TLSConfig{
1230+
Enabled: rfqCfg.PriceOracleTLS,
1231+
InsecureSkipVerify: rfqCfg.PriceOracleTLSInsecure,
1232+
// Note the subtle flip on the flag, since the user has
1233+
// configured whether to *not* trust the system CA's.
1234+
TrustSystemRootCAs: !rfqCfg.PriceOracleTLSNoSystemCAs,
1235+
CustomCertificates: certBytes,
1236+
}
1237+
1238+
return tlsConfig, nil
1239+
}
1240+
11871241
// fileExists reports whether the named file or directory exists.
11881242
// This function is taken from https://github.com/btcsuite/btcd
11891243
func fileExists(name string) bool {

tapcfg/server.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,8 +482,14 @@ func genServerConfig(cfg *Config, cfgLogger btclog.Logger,
482482
// skip setting suggested prices for outgoing quote requests.
483483

484484
default:
485+
tlsConfig, err := getPriceOracleTLSConfig(rfqCfg)
486+
if err != nil {
487+
return nil, fmt.Errorf("couldn't construct price "+
488+
"oracle configuration: %w", err)
489+
}
490+
485491
priceOracle, err = rfq.NewRpcPriceOracle(
486-
rfqCfg.PriceOracleAddress, rfq.DefaultTLSConfig(),
492+
rfqCfg.PriceOracleAddress, tlsConfig,
487493
)
488494
if err != nil {
489495
return nil, fmt.Errorf("unable to create price "+

0 commit comments

Comments
 (0)