diff --git a/op-signer/app.go b/op-signer/app.go index 50c8b561..380e58dd 100644 --- a/op-signer/app.go +++ b/op-signer/app.go @@ -113,6 +113,7 @@ func (s *SignerApp) initMetrics(cfg *Config) error { func (s *SignerApp) initRPC(cfg *Config) error { var httpOptions = []httputil.Option{} + var authMiddleware oprpc.Middleware if cfg.TLSConfig.Enabled { caCert, err := os.ReadFile(cfg.TLSConfig.TLSCaCert) @@ -141,8 +142,13 @@ func (s *SignerApp) initRPC(cfg *Config) error { } httpOptions = append(httpOptions, httputil.WithServerTLS(serverTlsConfig)) + + // Set the auth middleware to the default auth middleware + authMiddleware = service.NewAuthMiddleware() } else { - s.log.Warn("TLS disabled. This is insecure and only supported for local development. Please enable TLS in production environments!") + s.log.Warn("TLS disabled. This disables authentication and is INSECURE! Please enable TLS in production environments!") + s.log.Info("Using anonymous authentication. You must explicitly set the 'auth[].name' config field to 'anonymous' to allow unauthenticated anonymous usage.") + authMiddleware = service.NewAnonMiddleware() } rpcCfg := cfg.RPCConfig @@ -152,7 +158,7 @@ func (s *SignerApp) initRPC(cfg *Config) error { Host: rpcCfg.ListenAddr, Port: rpcCfg.ListenPort, RpcOptions: []oprpc.Option{ - oprpc.WithMiddleware(service.NewAuthMiddleware()), + oprpc.WithMiddleware(authMiddleware), oprpc.WithHTTPRecorder(opmetrics.NewPromHTTPRecorder(s.registry, "signer")), oprpc.WithLogger(s.log), }, diff --git a/op-signer/provider/config.go b/op-signer/provider/config.go index 64182060..03760d5a 100644 --- a/op-signer/provider/config.go +++ b/op-signer/provider/config.go @@ -49,7 +49,8 @@ func ReadConfig(path string) (ProviderConfig, error) { } if !config.ProviderType.IsValid() { - return config, fmt.Errorf("invalid provider '%s' in config. Must be 'AWS', 'GCP', or 'LOCAL'", config.ProviderType) + providerTypesStr := GetAllProviderTypesString() + return config, fmt.Errorf("invalid provider '%s' in config. Must be %s", config.ProviderType, providerTypesStr) } for _, authConfig := range config.Auth { diff --git a/op-signer/provider/provider.go b/op-signer/provider/provider.go index 0a0137e8..4e0f38e7 100644 --- a/op-signer/provider/provider.go +++ b/op-signer/provider/provider.go @@ -4,6 +4,8 @@ package provider import ( "context" "fmt" + "slices" + "strings" "github.com/ethereum/go-ethereum/log" ) @@ -13,7 +15,7 @@ type SignatureProvider interface { GetPublicKey(ctx context.Context, keyName string) ([]byte, error) } -// ProviderType represents the provider for the key management service +// ProviderType represents the provider for the key management service. type ProviderType string const ( @@ -22,14 +24,28 @@ const ( KeyProviderLocal ProviderType = "LOCAL" ) +func GetAllProviderTypes() []ProviderType { + return []ProviderType{KeyProviderAWS, KeyProviderGCP, KeyProviderLocal} +} + +// GetAllProviderTypesString returns a string of all the provider types separated +// by commas and wrapped in single quotes. This is useful for logging the available +// provider types. +func GetAllProviderTypesString() string { + types := GetAllProviderTypes() + result := make([]string, len(types)) + for i, t := range types { + result[i] = string(t) + } + if len(result) == 1 { + return result[0] + } + return fmt.Sprintf("'%s' or '%s'", strings.Join(result[:len(result)-1], "', '"), result[len(result)-1]) +} + // IsValid checks if the KeyProvider value is valid func (k ProviderType) IsValid() bool { - switch k { - case KeyProviderAWS, KeyProviderGCP, KeyProviderLocal: - return true - default: - return false - } + return slices.Contains(GetAllProviderTypes(), k) } // NewSignatureProvider creates a new SignatureProvider based on the provider type diff --git a/op-signer/service/auth.go b/op-signer/service/auth.go index ffba405c..ea800512 100644 --- a/op-signer/service/auth.go +++ b/op-signer/service/auth.go @@ -38,6 +38,21 @@ func NewAuthMiddleware() oprpc.Middleware { } } +// NewAnonMiddleware is a middleware that sets the client info to "anonymous". This is applied when mTLS is disabled to +// ensure a value is set for the ClientInfo.ClientName, but should only be used for local development. This effectively +// disables authentication. +func NewAnonMiddleware() oprpc.Middleware { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + clientInfo := ClientInfo{ + ClientName: "anonymous", + } + ctx := context.WithValue(r.Context(), clientInfoContextKey{}, clientInfo) + next.ServeHTTP(w, r.WithContext(ctx)) + }) + } +} + func ClientInfoFromContext(ctx context.Context) ClientInfo { info, _ := ctx.Value(clientInfoContextKey{}).(ClientInfo) return info