mirror of
https://github.com/netbirdio/dex.git
synced 2026-05-22 18:43:53 -07:00
feat: Disallow unknown config fields (#4531)
Signed-off-by: maksim.nabokikh <max.nabokih@gmail.com>
This commit is contained in:
+17
-7
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -23,6 +24,15 @@ import (
|
||||
"github.com/dexidp/dex/storage/sql"
|
||||
)
|
||||
|
||||
func configUnmarshaller(b []byte, v interface{}) error {
|
||||
if featureflags.ConfigDisallowUnknownFields.Enabled() {
|
||||
return json.Unmarshal(b, v)
|
||||
}
|
||||
dec := json.NewDecoder(bytes.NewReader(b))
|
||||
dec.DisallowUnknownFields()
|
||||
return dec.Decode(v)
|
||||
}
|
||||
|
||||
// Config is the config format for the main application.
|
||||
type Config struct {
|
||||
Issuer string `json:"issuer"`
|
||||
@@ -109,7 +119,7 @@ func (p *password) UnmarshalJSON(b []byte) error {
|
||||
HashFromEnv string `json:"hashFromEnv"`
|
||||
Groups []string `json:"groups"`
|
||||
}
|
||||
if err := json.Unmarshal(b, &data); err != nil {
|
||||
if err := configUnmarshaller(b, &data); err != nil {
|
||||
return err
|
||||
}
|
||||
*p = password(storage.Password{
|
||||
@@ -333,7 +343,7 @@ func (s *Storage) UnmarshalJSON(b []byte) error {
|
||||
Type string `json:"type"`
|
||||
Config json.RawMessage `json:"config"`
|
||||
}
|
||||
if err := json.Unmarshal(b, &store); err != nil {
|
||||
if err := configUnmarshaller(b, &store); err != nil {
|
||||
return fmt.Errorf("parse storage: %v", err)
|
||||
}
|
||||
f, ok := storages[store.Type]
|
||||
@@ -346,7 +356,7 @@ func (s *Storage) UnmarshalJSON(b []byte) error {
|
||||
data := []byte(store.Config)
|
||||
if featureflags.ExpandEnv.Enabled() {
|
||||
var rawMap map[string]interface{}
|
||||
if err := json.Unmarshal(store.Config, &rawMap); err != nil {
|
||||
if err := configUnmarshaller(store.Config, &rawMap); err != nil {
|
||||
return fmt.Errorf("unmarshal config for env expansion: %v", err)
|
||||
}
|
||||
|
||||
@@ -363,7 +373,7 @@ func (s *Storage) UnmarshalJSON(b []byte) error {
|
||||
data = expandedData
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, storageConfig); err != nil {
|
||||
if err := configUnmarshaller(data, storageConfig); err != nil {
|
||||
return fmt.Errorf("parse storage config: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -462,7 +472,7 @@ func (c *Connector) UnmarshalJSON(b []byte) error {
|
||||
|
||||
Config json.RawMessage `json:"config"`
|
||||
}
|
||||
if err := json.Unmarshal(b, &conn); err != nil {
|
||||
if err := configUnmarshaller(b, &conn); err != nil {
|
||||
return fmt.Errorf("parse connector: %v", err)
|
||||
}
|
||||
f, ok := server.ConnectorsConfig[conn.Type]
|
||||
@@ -475,7 +485,7 @@ func (c *Connector) UnmarshalJSON(b []byte) error {
|
||||
data := []byte(conn.Config)
|
||||
if featureflags.ExpandEnv.Enabled() {
|
||||
var rawMap map[string]interface{}
|
||||
if err := json.Unmarshal(conn.Config, &rawMap); err != nil {
|
||||
if err := configUnmarshaller(conn.Config, &rawMap); err != nil {
|
||||
return fmt.Errorf("unmarshal config for env expansion: %v", err)
|
||||
}
|
||||
|
||||
@@ -492,7 +502,7 @@ func (c *Connector) UnmarshalJSON(b []byte) error {
|
||||
data = expandedData
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, connConfig); err != nil {
|
||||
if err := configUnmarshaller(data, connConfig); err != nil {
|
||||
return fmt.Errorf("parse connector config: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -97,10 +97,16 @@ func runServe(options serveOptions) error {
|
||||
}
|
||||
|
||||
var c Config
|
||||
if err := yaml.Unmarshal(configData, &c); err != nil {
|
||||
|
||||
jsonConfigData, err := yaml.YAMLToJSON(configData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parse config file %s: %v", configFile, err)
|
||||
}
|
||||
|
||||
if err := configUnmarshaller(jsonConfigData, &c); err != nil {
|
||||
return fmt.Errorf("error unmarshalling config file %s: %v", configFile, err)
|
||||
}
|
||||
|
||||
applyConfigOverrides(options, &c)
|
||||
|
||||
logger, err := newLogger(c.Logger.Level, c.Logger.Format)
|
||||
|
||||
@@ -14,4 +14,7 @@ var (
|
||||
|
||||
// ContinueOnConnectorFailure allows the server to start even if some connectors fail to initialize.
|
||||
ContinueOnConnectorFailure = newFlag("continue_on_connector_failure", true)
|
||||
|
||||
// ConfigDisallowUnknownFields enables to forbid unknown fields in the config while unmarshaling.
|
||||
ConfigDisallowUnknownFields = newFlag("config_disallow_unknown_fields", false)
|
||||
)
|
||||
|
||||
@@ -15,10 +15,10 @@ var defaultDialTimeout = 2 * time.Second
|
||||
|
||||
// SSL represents SSL options for etcd databases.
|
||||
type SSL struct {
|
||||
ServerName string `json:"serverName" yaml:"serverName"`
|
||||
CAFile string `json:"caFile" yaml:"caFile"`
|
||||
KeyFile string `json:"keyFile" yaml:"keyFile"`
|
||||
CertFile string `json:"certFile" yaml:"certFile"`
|
||||
ServerName string `json:"serverName"`
|
||||
CAFile string `json:"caFile"`
|
||||
KeyFile string `json:"keyFile"`
|
||||
CertFile string `json:"certFile"`
|
||||
}
|
||||
|
||||
// Etcd options for connecting to etcd databases.
|
||||
@@ -26,11 +26,11 @@ type SSL struct {
|
||||
// configure an etcd namespace either via Namespace field or using `etcd grpc-proxy
|
||||
// --namespace=<prefix>`
|
||||
type Etcd struct {
|
||||
Endpoints []string `json:"endpoints" yaml:"endpoints"`
|
||||
Namespace string `json:"namespace" yaml:"namespace"`
|
||||
Username string `json:"username" yaml:"username"`
|
||||
Password string `json:"password" yaml:"password"`
|
||||
SSL SSL `json:"ssl" yaml:"ssl"`
|
||||
Endpoints []string `json:"endpoints"`
|
||||
Namespace string `json:"namespace"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
SSL SSL `json:"ssl"`
|
||||
}
|
||||
|
||||
// Open creates a new storage implementation backed by Etcd
|
||||
|
||||
@@ -78,7 +78,7 @@ type SSL struct {
|
||||
type Postgres struct {
|
||||
NetworkDB
|
||||
|
||||
SSL SSL `json:"ssl" yaml:"ssl"`
|
||||
SSL SSL `json:"ssl"`
|
||||
}
|
||||
|
||||
// Open creates a new storage implementation backed by Postgres.
|
||||
@@ -206,7 +206,7 @@ func (p *Postgres) open(logger *slog.Logger) (*conn, error) {
|
||||
type MySQL struct {
|
||||
NetworkDB
|
||||
|
||||
SSL SSL `json:"ssl" yaml:"ssl"`
|
||||
SSL SSL `json:"ssl"`
|
||||
|
||||
// TODO(pborzenkov): used by tests to reduce lock wait timeout. Should
|
||||
// we make it exported and allow users to provide arbitrary params?
|
||||
|
||||
+9
-9
@@ -149,28 +149,28 @@ type Storage interface {
|
||||
// - Public clients: https://developers.google.com/api-client-library/python/auth/installed-app
|
||||
type Client struct {
|
||||
// Client ID and secret used to identify the client.
|
||||
ID string `json:"id" yaml:"id"`
|
||||
IDEnv string `json:"idEnv" yaml:"idEnv"`
|
||||
Secret string `json:"secret" yaml:"secret"`
|
||||
SecretEnv string `json:"secretEnv" yaml:"secretEnv"`
|
||||
ID string `json:"id"`
|
||||
IDEnv string `json:"idEnv"`
|
||||
Secret string `json:"secret"`
|
||||
SecretEnv string `json:"secretEnv"`
|
||||
|
||||
// A registered set of redirect URIs. When redirecting from dex to the client, the URI
|
||||
// requested to redirect to MUST match one of these values, unless the client is "public".
|
||||
RedirectURIs []string `json:"redirectURIs" yaml:"redirectURIs"`
|
||||
RedirectURIs []string `json:"redirectURIs"`
|
||||
|
||||
// TrustedPeers are a list of peers which can issue tokens on this client's behalf using
|
||||
// the dynamic "oauth2:server:client_id:(client_id)" scope. If a peer makes such a request,
|
||||
// this client's ID will appear as the ID Token's audience.
|
||||
//
|
||||
// Clients inherently trust themselves.
|
||||
TrustedPeers []string `json:"trustedPeers" yaml:"trustedPeers"`
|
||||
TrustedPeers []string `json:"trustedPeers"`
|
||||
|
||||
// Public clients must use either use a redirectURL 127.0.0.1:X or "urn:ietf:wg:oauth:2.0:oob"
|
||||
Public bool `json:"public" yaml:"public"`
|
||||
Public bool `json:"public"`
|
||||
|
||||
// Name and LogoURL used when displaying this client to the end user.
|
||||
Name string `json:"name" yaml:"name"`
|
||||
LogoURL string `json:"logoURL" yaml:"logoURL"`
|
||||
Name string `json:"name"`
|
||||
LogoURL string `json:"logoURL"`
|
||||
}
|
||||
|
||||
// Claims represents the ID Token claims supported by the server.
|
||||
|
||||
Reference in New Issue
Block a user