server: account for dynamically changing connector object in storage.
This commit is contained in:
@@ -9,13 +9,6 @@ import (
|
||||
"github.com/Sirupsen/logrus"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"github.com/coreos/dex/connector"
|
||||
"github.com/coreos/dex/connector/github"
|
||||
"github.com/coreos/dex/connector/gitlab"
|
||||
"github.com/coreos/dex/connector/ldap"
|
||||
"github.com/coreos/dex/connector/mock"
|
||||
"github.com/coreos/dex/connector/oidc"
|
||||
"github.com/coreos/dex/connector/saml"
|
||||
"github.com/coreos/dex/server"
|
||||
"github.com/coreos/dex/storage"
|
||||
"github.com/coreos/dex/storage/kubernetes"
|
||||
@@ -25,17 +18,20 @@ import (
|
||||
|
||||
// Config is the config format for the main application.
|
||||
type Config struct {
|
||||
Issuer string `json:"issuer"`
|
||||
Storage Storage `json:"storage"`
|
||||
Connectors []Connector `json:"connectors"`
|
||||
Web Web `json:"web"`
|
||||
OAuth2 OAuth2 `json:"oauth2"`
|
||||
GRPC GRPC `json:"grpc"`
|
||||
Expiry Expiry `json:"expiry"`
|
||||
Logger Logger `json:"logger"`
|
||||
Issuer string `json:"issuer"`
|
||||
Storage Storage `json:"storage"`
|
||||
Web Web `json:"web"`
|
||||
OAuth2 OAuth2 `json:"oauth2"`
|
||||
GRPC GRPC `json:"grpc"`
|
||||
Expiry Expiry `json:"expiry"`
|
||||
Logger Logger `json:"logger"`
|
||||
|
||||
Frontend server.WebConfig `json:"frontend"`
|
||||
|
||||
// StaticConnectors are user defined connectors specified in the ConfigMap
|
||||
// Write operations, like updating a connector, will fail.
|
||||
StaticConnectors []Connector `json:"connectors"`
|
||||
|
||||
// StaticClients cause the server to use this list of clients rather than
|
||||
// querying the storage. Write operations, like creating a client, will fail.
|
||||
StaticClients []storage.Client `json:"staticClients"`
|
||||
@@ -170,24 +166,7 @@ type Connector struct {
|
||||
Name string `json:"name"`
|
||||
ID string `json:"id"`
|
||||
|
||||
Config ConnectorConfig `json:"config"`
|
||||
}
|
||||
|
||||
// ConnectorConfig is a configuration that can open a connector.
|
||||
type ConnectorConfig interface {
|
||||
Open(logrus.FieldLogger) (connector.Connector, error)
|
||||
}
|
||||
|
||||
var connectors = map[string]func() ConnectorConfig{
|
||||
"mockCallback": func() ConnectorConfig { return new(mock.CallbackConfig) },
|
||||
"mockPassword": func() ConnectorConfig { return new(mock.PasswordConfig) },
|
||||
"ldap": func() ConnectorConfig { return new(ldap.Config) },
|
||||
"github": func() ConnectorConfig { return new(github.Config) },
|
||||
"gitlab": func() ConnectorConfig { return new(gitlab.Config) },
|
||||
"oidc": func() ConnectorConfig { return new(oidc.Config) },
|
||||
"saml": func() ConnectorConfig { return new(saml.Config) },
|
||||
// Keep around for backwards compatibility.
|
||||
"samlExperimental": func() ConnectorConfig { return new(saml.Config) },
|
||||
Config server.ConnectorConfig `json:"config"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON allows Connector to implement the unmarshaler interface to
|
||||
@@ -203,7 +182,7 @@ func (c *Connector) UnmarshalJSON(b []byte) error {
|
||||
if err := json.Unmarshal(b, &conn); err != nil {
|
||||
return fmt.Errorf("parse connector: %v", err)
|
||||
}
|
||||
f, ok := connectors[conn.Type]
|
||||
f, ok := server.ConnectorsConfig[conn.Type]
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown connector type %q", conn.Type)
|
||||
}
|
||||
@@ -224,6 +203,21 @@ func (c *Connector) UnmarshalJSON(b []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToStorageConnector converts an object to storage connector type.
|
||||
func ToStorageConnector(c Connector) (storage.Connector, error) {
|
||||
data, err := json.Marshal(c.Config)
|
||||
if err != nil {
|
||||
return storage.Connector{}, fmt.Errorf("failed to marshal connector config: %v", err)
|
||||
}
|
||||
|
||||
return storage.Connector{
|
||||
ID: c.ID,
|
||||
Type: c.Type,
|
||||
Name: c.Name,
|
||||
Config: data,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Expiry holds configuration for the validity period of components.
|
||||
type Expiry struct {
|
||||
// SigningKeys defines the duration of time after which the SigningKeys will be rotated.
|
||||
|
@@ -86,7 +86,7 @@ logger:
|
||||
},
|
||||
},
|
||||
},
|
||||
Connectors: []Connector{
|
||||
StaticConnectors: []Connector{
|
||||
{
|
||||
Type: "mockCallback",
|
||||
ID: "mock",
|
||||
|
@@ -74,7 +74,6 @@ func serve(cmd *cobra.Command, args []string) error {
|
||||
errMsg string
|
||||
}{
|
||||
{c.Issuer == "", "no issuer specified in config file"},
|
||||
{len(c.Connectors) == 0 && !c.EnablePasswordDB, "no connectors supplied in config file"},
|
||||
{!c.EnablePasswordDB && len(c.StaticPasswords) != 0, "cannot specify static passwords without enabling password db"},
|
||||
{c.Storage.Config == nil, "no storage suppied in config file"},
|
||||
{c.Web.HTTP == "" && c.Web.HTTPS == "", "must supply a HTTP/HTTPS address to listen on"},
|
||||
@@ -128,34 +127,6 @@ func serve(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
connectors := make([]server.Connector, len(c.Connectors))
|
||||
for i, conn := range c.Connectors {
|
||||
if conn.ID == "" {
|
||||
return fmt.Errorf("invalid config: no ID field for connector %d", i)
|
||||
}
|
||||
if conn.Config == nil {
|
||||
return fmt.Errorf("invalid config: no config field for connector %q", conn.ID)
|
||||
}
|
||||
if conn.Name == "" {
|
||||
return fmt.Errorf("invalid config: no Name field for connector %q", conn.ID)
|
||||
}
|
||||
logger.Infof("config connector: %s", conn.ID)
|
||||
|
||||
connectorLogger := logger.WithField("connector", conn.Name)
|
||||
c, err := conn.Config.Open(connectorLogger)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create connector %s: %v", conn.ID, err)
|
||||
}
|
||||
connectors[i] = server.Connector{
|
||||
ID: conn.ID,
|
||||
DisplayName: conn.Name,
|
||||
Connector: c,
|
||||
}
|
||||
}
|
||||
if c.EnablePasswordDB {
|
||||
logger.Infof("config connector: local passwords enabled")
|
||||
}
|
||||
|
||||
s, err := c.Storage.Config.Open(logger)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize storage: %v", err)
|
||||
@@ -176,6 +147,35 @@ func serve(cmd *cobra.Command, args []string) error {
|
||||
s = storage.WithStaticPasswords(s, passwords)
|
||||
}
|
||||
|
||||
if c.EnablePasswordDB {
|
||||
c.StaticConnectors = append(c.StaticConnectors, Connector{
|
||||
ID: server.LocalConnector,
|
||||
Name: "Email",
|
||||
Type: server.LocalConnector,
|
||||
})
|
||||
logger.Infof("config connector: local passwords enabled")
|
||||
}
|
||||
|
||||
storageConnectors := make([]storage.Connector, len(c.StaticConnectors))
|
||||
for i, c := range c.StaticConnectors {
|
||||
if c.ID == "" || c.Name == "" || c.Type == "" {
|
||||
return fmt.Errorf("invalid config: ID, Type and Name fields are required for a connector")
|
||||
}
|
||||
if c.Config == nil {
|
||||
return fmt.Errorf("invalid config: no config field for connector %q", c.ID)
|
||||
}
|
||||
logger.Infof("config connector: %s", c.ID)
|
||||
|
||||
// convert to a storage connector object
|
||||
conn, err := ToStorageConnector(c)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize storage connectors: %v", err)
|
||||
}
|
||||
storageConnectors[i] = conn
|
||||
|
||||
}
|
||||
s = storage.WithStaticConnectors(s, storageConnectors)
|
||||
|
||||
if len(c.OAuth2.ResponseTypes) > 0 {
|
||||
logger.Infof("config response types accepted: %s", c.OAuth2.ResponseTypes)
|
||||
}
|
||||
@@ -194,10 +194,8 @@ func serve(cmd *cobra.Command, args []string) error {
|
||||
SkipApprovalScreen: c.OAuth2.SkipApprovalScreen,
|
||||
AllowedOrigins: c.Web.AllowedOrigins,
|
||||
Issuer: c.Issuer,
|
||||
Connectors: connectors,
|
||||
Storage: s,
|
||||
Web: c.Frontend,
|
||||
EnablePasswordDB: c.EnablePasswordDB,
|
||||
Logger: logger,
|
||||
Now: now,
|
||||
}
|
||||
|
Reference in New Issue
Block a user