Skip to content

Commit 3e9152f

Browse files
committed
tapcfg: add price oracle TLS config
We remain insecure by default, for now, and also default to trusting the operating system's root CA list.
1 parent 97cf0a9 commit 3e9152f

File tree

4 files changed

+68
-13
lines changed

4 files changed

+68
-13
lines changed

rfq/cli.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ 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+
PriceOracleTLSInsecure bool `long:"priceoracletlsinsecure" description:"Disable verification of price oracle certificates. Communication with the price oracle will be in cleartext over HTTP, so should only be used for testing."`
26+
27+
PriceOracleTLSNoSystemCAs bool `long:"priceoracletlsnosystemcas" description:"Disable use of the operating system's list of root certificate authorities."`
28+
29+
PriceOracleTLSCertPath string `long:"priceoracletlscertpath" description:"Path to a PEM-encoded x509 certificate that will be used to construct a TLS connection with the price oracle."`
30+
2531
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."`
2632

2733
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
@@ -21,13 +21,6 @@ type TLSConfig struct {
2121
CustomCertificates []byte
2222
}
2323

24-
// DefaultTLSConfig returns a default TLS configuration.
25-
func DefaultTLSConfig() *TLSConfig {
26-
return &TLSConfig{
27-
InsecureSkipVerify: true,
28-
}
29-
}
30-
3124
// configureTransportCredentials configures the TLS transport credentials to
3225
// be used for RPC connections.
3326
func configureTransportCredentials(

tapcfg/config.go

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,21 @@ const (
143143
// defaultMailboxAuthTimeout is the default timeout we'll use for
144144
// mailbox message retrieval client authentication.
145145
defaultMailboxAuthTimeout = 10 * time.Second
146+
147+
// defaultPriceOracleTLSInsecure is the default value we'll use for
148+
// constructing TLS connections with price oracles. It is 'true' for
149+
// now, but ought be changed to 'false' before any major feature
150+
// release.
151+
defaultPriceOracleTLSInsecure = true
152+
153+
// defaultPriceOracleNoSystemCAs is the default value we'll use
154+
// regarding trust of the operating system's root CA list. We'll use
155+
// 'false', i.e. we will trust the OS root CA list by default.
156+
defaultPriceOracleTLSNoSystemCAs = false
157+
158+
// defaultPriceOracleTLSCertPath is the default (empty) path to a
159+
// certificate to use for securing price oracle communication.
160+
defaultPriceOracleTLSCertPath = ""
146161
)
147162

148163
var (
@@ -317,8 +332,11 @@ type ExperimentalConfig struct {
317332
Rfq rfq.CliConfig `group:"rfq" namespace:"rfq"`
318333
}
319334

320-
// Validate returns an error if the configuration is invalid.
321-
func (c *ExperimentalConfig) Validate() error {
335+
// CleanAndValidate performs final processing on the ExperimentalConfig,
336+
// returning an error if the configuration is invalid.
337+
func (c *ExperimentalConfig) CleanAndValidate() error {
338+
c.Rfq.PriceOracleTLSCertPath = CleanAndExpandPath(
339+
c.Rfq.PriceOracleTLSCertPath)
322340
return c.Rfq.Validate()
323341
}
324342

@@ -478,7 +496,10 @@ func DefaultConfig() Config {
478496
},
479497
Experimental: &ExperimentalConfig{
480498
Rfq: rfq.CliConfig{
481-
AcceptPriceDeviationPpm: rfq.DefaultAcceptPriceDeviationPpm,
499+
AcceptPriceDeviationPpm: rfq.DefaultAcceptPriceDeviationPpm,
500+
PriceOracleTLSInsecure: defaultPriceOracleTLSInsecure,
501+
PriceOracleTLSNoSystemCAs: defaultPriceOracleTLSNoSystemCAs,
502+
PriceOracleTLSCertPath: defaultPriceOracleTLSCertPath,
482503
},
483504
},
484505
}
@@ -914,8 +935,8 @@ func ValidateConfig(cfg Config, cfgLogger btclog.Logger) (*Config, error) {
914935
}
915936
}
916937

917-
// Validate the experimental command line config.
918-
err = cfg.Experimental.Validate()
938+
// Clean and validate the experimental command line config.
939+
err = cfg.Experimental.CleanAndValidate()
919940
if err != nil {
920941
return nil, fmt.Errorf("error in experimental command line "+
921942
"config: %w", err)
@@ -1150,6 +1171,35 @@ func getCertificateConfig(cfg *Config, cfgLogger btclog.Logger) (*tls.Config,
11501171
return tlsCfg, restCreds, nil
11511172
}
11521173

1174+
// getPriceOracleTLSConfig returns a TLS configuration for a price oracle,
1175+
// given a valid RFQ CLI configuration.
1176+
func getPriceOracleTLSConfig(rfqCfg rfq.CliConfig) (*rfq.TLSConfig, error) {
1177+
var certBytes []byte
1178+
1179+
// Read any specified certificate data.
1180+
if rfqCfg.PriceOracleTLSCertPath != "" {
1181+
var err error
1182+
certBytes, err = os.ReadFile(
1183+
rfqCfg.PriceOracleTLSCertPath)
1184+
if err != nil {
1185+
return nil, fmt.Errorf("unable to read "+
1186+
"price oracle certificate: %w", err)
1187+
}
1188+
}
1189+
1190+
// Construct the oracle's TLS configuration.
1191+
tlsConfig := &rfq.TLSConfig{
1192+
InsecureSkipVerify: rfqCfg.PriceOracleTLSInsecure,
1193+
// Note the subtle flip on the flag, since the user has
1194+
// configured whether or not to *not* trust the system
1195+
// CA's.
1196+
TrustSystemRootCAs: !rfqCfg.PriceOracleTLSNoSystemCAs,
1197+
CustomCertificates: certBytes,
1198+
}
1199+
1200+
return tlsConfig, nil
1201+
}
1202+
11531203
// fileExists reports whether the named file or directory exists.
11541204
// This function is taken from https://github.com/btcsuite/btcd
11551205
func fileExists(name string) bool {

tapcfg/server.go

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

463463
default:
464+
tlsConfig, err := getPriceOracleTLSConfig(rfqCfg)
465+
if err != nil {
466+
return nil, fmt.Errorf("couldn't construct price "+
467+
"oracle configuration: %w", err)
468+
}
469+
464470
priceOracle, err = rfq.NewRpcPriceOracle(
465-
rfqCfg.PriceOracleAddress, rfq.DefaultTLSConfig(),
471+
rfqCfg.PriceOracleAddress, tlsConfig,
466472
)
467473
if err != nil {
468474
return nil, fmt.Errorf("unable to create price "+

0 commit comments

Comments
 (0)