Commit 12225341 authored by Joshua Gutow's avatar Joshua Gutow Committed by GitHub

op-service: Add optional headers to the signer client (#12407)

* op-service: Add optional headers to the signer client

* Explain flag usage
parent bb2c99c8
......@@ -2,6 +2,8 @@ package signer
import (
"errors"
"net/http"
"strings"
"github.com/urfave/cli/v2"
......@@ -12,6 +14,7 @@ import (
const (
EndpointFlagName = "signer.endpoint"
AddressFlagName = "signer.address"
HeadersFlagName = "signer.header"
)
func CLIFlags(envPrefix string) []cli.Flag {
......@@ -27,6 +30,11 @@ func CLIFlags(envPrefix string) []cli.Flag {
Usage: "Address the signer is signing transactions for",
EnvVars: opservice.PrefixEnvVar(envPrefix, "ADDRESS"),
},
&cli.StringSliceFlag{
Name: HeadersFlagName,
Usage: "Headers to pass to the remote signer. Format `key=value`. Value can contain any character allowed in a HTTP header. When using env vars, split with commas. When using flags one key value pair per flag.",
EnvVars: opservice.PrefixEnvVar(envPrefix, "HEADER"),
},
}
flags = append(flags, optls.CLIFlagsWithFlagPrefix(envPrefix, "signer")...)
return flags
......@@ -35,11 +43,13 @@ func CLIFlags(envPrefix string) []cli.Flag {
type CLIConfig struct {
Endpoint string
Address string
Headers http.Header
TLSConfig optls.CLIConfig
}
func NewCLIConfig() CLIConfig {
return CLIConfig{
Headers: http.Header{},
TLSConfig: optls.NewCLIConfig(),
}
}
......@@ -62,9 +72,20 @@ func (c CLIConfig) Enabled() bool {
}
func ReadCLIConfig(ctx *cli.Context) CLIConfig {
var headers = http.Header{}
if ctx.StringSlice(HeadersFlagName) != nil {
for _, header := range ctx.StringSlice(HeadersFlagName) {
args := strings.SplitN(header, "=", 2)
if len(args) == 2 {
headers.Set(args[0], args[1])
}
}
}
cfg := CLIConfig{
Endpoint: ctx.String(EndpointFlagName),
Address: ctx.String(AddressFlagName),
Headers: headers,
TLSConfig: optls.ReadCLIConfigWithPrefix(ctx, "signer"),
}
return cfg
......
package signer
import (
"net/http"
"testing"
"github.com/stretchr/testify/require"
......@@ -18,6 +19,37 @@ func TestDefaultConfigIsValid(t *testing.T) {
require.NoError(t, err)
}
func TestHeaderParsing(t *testing.T) {
testHeaders := []string{
"test-key=this:is:a:value",
"b64-test-key=value:dGVzdCBkYXRhIDE=$",
}
args := []string{"app", "--signer.header", testHeaders[0], "--signer.header", testHeaders[1]}
cfg := configForArgs(args...)
expectedHeaders := http.Header{}
expectedHeaders.Set("test-key", "this:is:a:value")
expectedHeaders.Set("b64-test-key", "value:dGVzdCBkYXRhIDE=$")
require.Equal(t, expectedHeaders, cfg.Headers)
}
func TestHeaderParsingWithComma(t *testing.T) {
testHeaders := []string{
"test-key=this:is:a:value,b64-test-key=value:dGVzdCBkYXRhIDE=$",
}
args := []string{"app", "--signer.header", testHeaders[0]}
cfg := configForArgs(args...)
expectedHeaders := http.Header{}
expectedHeaders.Set("test-key", "this:is:a:value")
expectedHeaders.Set("b64-test-key", "value:dGVzdCBkYXRhIDE=$")
require.Equal(t, expectedHeaders, cfg.Headers)
}
func TestInvalidConfig(t *testing.T) {
tests := []struct {
name string
......@@ -29,6 +61,7 @@ func TestInvalidConfig(t *testing.T) {
expected: "signer endpoint and address must both be set or not set",
configChange: func(config *CLIConfig) {
config.Address = "0x1234"
config.TLSConfig.Enabled = true
},
},
{
......@@ -36,6 +69,7 @@ func TestInvalidConfig(t *testing.T) {
expected: "signer endpoint and address must both be set or not set",
configChange: func(config *CLIConfig) {
config.Endpoint = "http://localhost"
config.TLSConfig.Enabled = true
},
},
{
......@@ -43,6 +77,7 @@ func TestInvalidConfig(t *testing.T) {
expected: "all tls flags must be set if at least one is set",
configChange: func(config *CLIConfig) {
config.TLSConfig.TLSKey = ""
config.TLSConfig.Enabled = true
},
},
}
......
......@@ -25,9 +25,9 @@ type SignerClient struct {
logger log.Logger
}
func NewSignerClient(logger log.Logger, endpoint string, tlsConfig optls.CLIConfig) (*SignerClient, error) {
func NewSignerClient(logger log.Logger, endpoint string, headers http.Header, tlsConfig optls.CLIConfig) (*SignerClient, error) {
var httpClient *http.Client
if tlsConfig.TLSCaCert != "" {
if tlsConfig.Enabled {
logger.Info("tlsConfig specified, loading tls config")
caCert, err := os.ReadFile(tlsConfig.TLSCaCert)
if err != nil {
......@@ -63,7 +63,7 @@ func NewSignerClient(logger log.Logger, endpoint string, tlsConfig optls.CLIConf
httpClient = http.DefaultClient
}
rpcClient, err := rpc.DialOptions(context.Background(), endpoint, rpc.WithHTTPClient(httpClient))
rpcClient, err := rpc.DialOptions(context.Background(), endpoint, rpc.WithHTTPClient(httpClient), rpc.WithHeaders(headers))
if err != nil {
return nil, err
}
......@@ -79,7 +79,7 @@ func NewSignerClient(logger log.Logger, endpoint string, tlsConfig optls.CLIConf
}
func NewSignerClientFromConfig(logger log.Logger, config CLIConfig) (*SignerClient, error) {
return NewSignerClient(logger, config.Endpoint, config.TLSConfig)
return NewSignerClient(logger, config.Endpoint, config.Headers, config.TLSConfig)
}
func (s *SignerClient) pingVersion() (string, error) {
......
......@@ -64,6 +64,7 @@ type CLIConfig struct {
TLSCaCert string
TLSCert string
TLSKey string
Enabled bool
}
func NewCLIConfig() CLIConfig {
......@@ -71,6 +72,7 @@ func NewCLIConfig() CLIConfig {
TLSCaCert: defaultTLSCaCert,
TLSCert: defaultTLSCert,
TLSKey: defaultTLSKey,
Enabled: false,
}
}
......@@ -83,7 +85,7 @@ func (c CLIConfig) Check() error {
}
func (c CLIConfig) TLSEnabled() bool {
return !(c.TLSCaCert == "" && c.TLSCert == "" && c.TLSKey == "")
return c.Enabled
}
// ReadCLIConfig reads tls cli configs
......@@ -93,6 +95,7 @@ func ReadCLIConfig(ctx *cli.Context) CLIConfig {
TLSCaCert: ctx.String(TLSCaCertFlagName),
TLSCert: ctx.String(TLSCertFlagName),
TLSKey: ctx.String(TLSKeyFlagName),
Enabled: ctx.IsSet(TLSCaCertFlagName) || ctx.IsSet(TLSCertFlagName) || ctx.IsSet(TLSKeyFlagName),
}
}
......@@ -106,5 +109,6 @@ func ReadCLIConfigWithPrefix(ctx *cli.Context, flagPrefix string) CLIConfig {
TLSCaCert: ctx.String(prefixFunc(TLSCaCertFlagName)),
TLSCert: ctx.String(prefixFunc(TLSCertFlagName)),
TLSKey: ctx.String(prefixFunc(TLSKeyFlagName)),
Enabled: ctx.IsSet(TLSCaCertFlagName) || ctx.IsSet(TLSCertFlagName) || ctx.IsSet(TLSKeyFlagName),
}
}
......@@ -36,6 +36,7 @@ func TestInvalidConfig(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
cfg := NewCLIConfig()
cfg.Enabled = true
test.configChange(&cfg)
err := cfg.Check()
require.ErrorContains(t, err, "all tls flags must be set if at least one is set")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment