11package config
22
33import (
4+ "crypto/x509"
45 "encoding/hex"
56 "fmt"
7+ "log/slog"
8+ "os"
69 "strings"
710 "time"
811
912 "github.com/spf13/afero"
1013 "github.com/spf13/viper"
14+
15+ tlsprovider "github.com/jshufro/remote-signer-dirk-interop/pkg/tls"
1116)
1217
1318// Config holds application configuration.
@@ -30,8 +35,18 @@ type Config struct {
3035 RootCA string `mapstructure:"root_ca"` // optional
3136 RefreshThreshold time.Duration `mapstructure:"refresh_threshold"`
3237 RefreshRetry time.Duration `mapstructure:"refresh_retry"`
38+
39+ CertPool * x509.CertPool `mapstructure:"-"`
40+ TLSProvider tlsprovider.TLSProvider `mapstructure:"-"`
3341 }
3442
43+ OTLP struct {
44+ TraceRecipient string `mapstructure:"trace_recipient"`
45+ Secure bool `mapstructure:"secure"`
46+ HostnameOverride string `mapstructure:"hostname_override"`
47+ ServiceInstanceIDOverride string `mapstructure:"service_instance_id_override"`
48+ } `mapstructure:"otlp"`
49+
3550 Metrics struct {
3651 ListenAddress string `mapstructure:"listen_address"`
3752 ListenPort uint16 `mapstructure:"listen_port"`
@@ -40,12 +55,57 @@ type Config struct {
4055 // Network is either mainnet or hoodi
4156 Network string `mapstructure:"network"`
4257 genesisForkVersion []byte
58+
59+ Log * slog.Logger
60+ ParsedLogLevel slog.Level
4361}
4462
45- func (c * Config ) Populate (v * viper.Viper ) error {
46- if err := v .Unmarshal (c ); err != nil {
63+ func (c * Config ) populate (v * viper.Viper ) error {
64+ if c == nil {
65+ return fmt .Errorf ("unmarshaling config: nil config" )
66+ }
67+ err := v .Unmarshal (c )
68+ if err != nil {
4769 return fmt .Errorf ("unmarshaling config: %w" , err )
4870 }
71+
72+ c .SSL .CertPool , err = x509 .SystemCertPool ()
73+ if err != nil {
74+ return fmt .Errorf ("failed to get system cert pool: %w" , err )
75+ }
76+
77+ if c .SSL .RootCA != "" {
78+ rootCABytes , err := os .ReadFile (c .SSL .RootCA )
79+ if err != nil {
80+ return fmt .Errorf ("failed to read root CA: %w" , err )
81+ }
82+ c .SSL .CertPool .AppendCertsFromPEM (rootCABytes )
83+ }
84+
85+ c .ParsedLogLevel = parseLogLevel (c .LogLevel )
86+ if c .LogFormat == "json" {
87+ c .Log = slog .New (slog .NewJSONHandler (os .Stderr , & slog.HandlerOptions {
88+ Level : c .ParsedLogLevel ,
89+ }))
90+ } else {
91+ c .Log = slog .New (slog .NewTextHandler (os .Stderr , & slog.HandlerOptions {
92+ Level : c .ParsedLogLevel ,
93+ }))
94+ }
95+
96+ return nil
97+ }
98+
99+ func (c * Config ) initClientTLS () error {
100+ tlsProvider := tlsprovider .NewTLSProvider (c .SSL .Cert , c .SSL .PrivKey )
101+ tlsProvider .SetThreshold (c .SSL .RefreshThreshold )
102+ tlsProvider .SetRetry (c .SSL .RefreshRetry )
103+ tlsProvider .SetLogger (c .Log )
104+
105+ if err := tlsProvider .LoadCertificate (); err != nil {
106+ return fmt .Errorf ("failed to load certificate: %w" , err )
107+ }
108+ c .SSL .TLSProvider = tlsProvider
49109 return nil
50110}
51111
@@ -62,6 +122,7 @@ func newViper(fs afero.Fs) *viper.Viper {
62122 v .SetDefault ("listen_address" , "0.0.0.0" )
63123 v .SetDefault ("listen_port" , 9090 )
64124 v .SetDefault ("network" , "mainnet" )
125+ v .SetDefault ("otlp.secure" , true )
65126 return v
66127
67128}
@@ -78,20 +139,24 @@ func Load(cfgFile string, fs afero.Fs) (*Config, error) {
78139 }
79140
80141 cfg := & Config {}
81- if err := cfg .Populate (v ); err != nil {
142+ if err := cfg .populate (v ); err != nil {
82143 return nil , fmt .Errorf ("populating config: %w" , err )
83144 }
84145
85- if err := cfg .Validate (); err != nil {
146+ if err := cfg .validate (); err != nil {
86147 return nil , fmt .Errorf ("validating config: %w" , err )
87148 }
88149
150+ if err := cfg .initClientTLS (); err != nil {
151+ return nil , fmt .Errorf ("loading tls credentials: %w" , err )
152+ }
153+
89154 return cfg , nil
90155}
91156
92157// Validate performs basic validation of the configuration and returns an error
93158// if any required fields are missing or invalid.
94- func (c * Config ) Validate () error {
159+ func (c * Config ) validate () error {
95160 if len (c .Dirk .Endpoints ) == 0 {
96161 return fmt .Errorf ("at least one dirk endpoint is required" )
97162 }
@@ -142,3 +207,18 @@ func (c *Config) setGenesisForkVersion() error {
142207func (c * Config ) GenesisForkVersion () []byte {
143208 return c .genesisForkVersion
144209}
210+
211+ func parseLogLevel (level string ) slog.Level {
212+ switch level {
213+ case "debug" :
214+ return slog .LevelDebug
215+ case "info" :
216+ return slog .LevelInfo
217+ case "warn" :
218+ return slog .LevelWarn
219+ case "error" :
220+ return slog .LevelError
221+ }
222+ fmt .Fprintf (os .Stderr , "invalid log level %s, defaulting to info\n " , level )
223+ return slog .LevelInfo
224+ }
0 commit comments