server: account for dynamically changing connector object in storage.

This commit is contained in:
rithu john
2017-04-17 15:41:41 -07:00
parent 2b8caf9b39
commit 8c9c2518f5
10 changed files with 400 additions and 137 deletions

View File

@@ -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.

View File

@@ -86,7 +86,7 @@ logger:
},
},
},
Connectors: []Connector{
StaticConnectors: []Connector{
{
Type: "mockCallback",
ID: "mock",

View File

@@ -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,
}