dex/server/testutil_test.go

299 lines
7.5 KiB
Go

package server
import (
"encoding/base64"
"fmt"
"net/url"
"time"
"github.com/coreos/go-oidc/key"
"github.com/coreos/go-oidc/oidc"
"github.com/coreos/dex/client"
clientmanager "github.com/coreos/dex/client/manager"
"github.com/coreos/dex/connector"
"github.com/coreos/dex/db"
"github.com/coreos/dex/email"
"github.com/coreos/dex/refresh/refreshtest"
sessionmanager "github.com/coreos/dex/session/manager"
"github.com/coreos/dex/user"
useremail "github.com/coreos/dex/user/email"
usermanager "github.com/coreos/dex/user/manager"
)
const (
templatesLocation = "../static/html"
emailTemplatesLocation = "../static/email"
)
var (
testUserID1 = "ID-1"
testUserEmail1 = "Email-1@example.com"
testUserRemoteID1 = "RID-1"
testIssuerURL = url.URL{Scheme: "http", Host: "server.example.com"}
testClientID = "client.example.com"
clientTestSecret = base64.URLEncoding.EncodeToString([]byte("secret"))
testClientCredentials = oidc.ClientCredentials{
ID: testClientID,
Secret: clientTestSecret,
}
testPublicClientID = "publicclient.example.com"
publicClientTestSecret = base64.URLEncoding.EncodeToString([]byte("secret"))
testPublicClientCredentials = oidc.ClientCredentials{
ID: testPublicClientID,
Secret: publicClientTestSecret,
}
testClients = []client.LoadableClient{
{
Client: client.Client{
Credentials: testClientCredentials,
Metadata: oidc.ClientMetadata{
RedirectURIs: []url.URL{
testRedirectURL,
},
},
},
},
{
Client: client.Client{
Credentials: testPublicClientCredentials,
Public: true,
},
},
}
testConnectorID1 = "IDPC-1"
testConnectorIDOpenID = "oidc"
testConnectorIDOpenIDTrusted = "oidc-trusted"
testConnectorLocalID = "local"
testRedirectURL = url.URL{Scheme: "http", Host: "client.example.com", Path: "/callback"}
testUsers = []user.UserWithRemoteIdentities{
{
User: user.User{
ID: testUserID1,
Email: testUserEmail1,
},
RemoteIdentities: []user.RemoteIdentity{
{
ConnectorID: testConnectorID1,
ID: testUserRemoteID1,
},
},
},
{
User: user.User{
ID: "ID-Verified",
Email: "Email-Verified@example.com",
EmailVerified: true,
},
RemoteIdentities: []user.RemoteIdentity{
{
ConnectorID: "IDPC-1",
ID: "RID-2",
},
},
},
}
testPasswordInfos = []user.PasswordInfo{
{
UserID: "ID-1",
Password: []byte("password"),
},
{
UserID: "ID-Verified",
Password: []byte("password"),
},
}
testPrivKey, _ = key.GeneratePrivateKey()
testClientCreds = oidc.ClientCredentials{
ID: testClientID,
Secret: base64.URLEncoding.EncodeToString([]byte("secret")),
}
)
type testFixtures struct {
srv *Server
userRepo user.UserRepo
sessionManager *sessionmanager.SessionManager
emailer *email.TemplatizedEmailer
redirectURL url.URL
clientRepo client.ClientRepo
clientManager *clientmanager.ClientManager
clientCreds map[string]oidc.ClientCredentials
}
type testFixtureOptions struct {
clients []client.LoadableClient
}
func sequentialGenerateCodeFunc() sessionmanager.GenerateCodeFunc {
x := 0
return func() (string, error) {
x += 1
return fmt.Sprintf("code-%d", x), nil
}
}
func makeTestFixtures() (*testFixtures, error) {
return makeTestFixturesWithOptions(testFixtureOptions{})
}
func makeTestFixturesWithOptions(options testFixtureOptions) (*testFixtures, error) {
dbMap := db.NewMemDB()
userRepo, err := db.NewUserRepoFromUsers(dbMap, testUsers)
if err != nil {
return nil, err
}
pwRepo, err := db.NewPasswordInfoRepoFromPasswordInfos(dbMap, testPasswordInfos)
if err != nil {
return nil, err
}
connConfigs := []connector.ConnectorConfig{
&connector.OIDCConnectorConfig{
ID: testConnectorIDOpenID,
IssuerURL: testIssuerURL.String(),
ClientID: "12345",
ClientSecret: "567789",
},
&connector.OIDCConnectorConfig{
ID: testConnectorIDOpenIDTrusted,
IssuerURL: testIssuerURL.String(),
ClientID: "12345-trusted",
ClientSecret: "567789-trusted",
TrustedEmailProvider: true,
},
&connector.OIDCConnectorConfig{
ID: testConnectorID1,
IssuerURL: testIssuerURL.String(),
ClientID: testConnectorID1 + "_client_id",
ClientSecret: testConnectorID1 + "_client_secret",
TrustedEmailProvider: true,
},
&connector.LocalConnectorConfig{
ID: testConnectorLocalID,
},
}
connCfgRepo := db.NewConnectorConfigRepo(dbMap)
if err := connCfgRepo.Set(connConfigs); err != nil {
return nil, err
}
userManager := usermanager.NewUserManager(userRepo, pwRepo, connCfgRepo, db.TransactionFactory(dbMap), usermanager.ManagerOptions{})
sessionManager := sessionmanager.NewSessionManager(db.NewSessionRepo(db.NewMemDB()), db.NewSessionKeyRepo(db.NewMemDB()))
sessionManager.GenerateCode = sequentialGenerateCodeFunc()
refreshTokenRepo := refreshtest.NewTestRefreshTokenRepo()
emailer, err := email.NewTemplatizedEmailerFromGlobs(
emailTemplatesLocation+"/*.txt",
emailTemplatesLocation+"/*.html",
&email.FakeEmailer{},
"admin@example.com")
if err != nil {
return nil, err
}
var clients []client.LoadableClient
if options.clients == nil {
clients = testClients
} else {
clients = options.clients
}
clientIDGenerator := func(hostport string) (string, error) {
return hostport, nil
}
secGen := func() ([]byte, error) {
return []byte("secret"), nil
}
clientRepo, err := db.NewClientRepoFromClients(dbMap, clients)
if err != nil {
return nil, err
}
clientManager := clientmanager.NewClientManager(clientRepo, db.TransactionFactory(dbMap), clientmanager.ManagerOptions{ClientIDGenerator: clientIDGenerator, SecretGenerator: secGen})
km := key.NewPrivateKeyManager()
err = km.Set(key.NewPrivateKeySet([]*key.PrivateKey{testPrivKey}, time.Now().Add(time.Minute)))
if err != nil {
return nil, err
}
tpl, err := getTemplates("dex",
"https://coreos.com/assets/images/brand/coreos-mark-30px.png",
true, templatesLocation)
if err != nil {
return nil, err
}
srv := &Server{
IssuerURL: testIssuerURL,
SessionManager: sessionManager,
ClientRepo: clientRepo,
Templates: tpl,
UserRepo: userRepo,
PasswordInfoRepo: pwRepo,
UserManager: userManager,
ClientManager: clientManager,
KeyManager: km,
RefreshTokenRepo: refreshTokenRepo,
}
err = setTemplates(srv, tpl)
if err != nil {
return nil, err
}
for _, config := range connConfigs {
if err := srv.AddConnector(config); err != nil {
return nil, err
}
}
srv.UserEmailer = useremail.NewUserEmailer(srv.UserRepo,
srv.PasswordInfoRepo,
srv.KeyManager.Signer,
srv.SessionManager.ValidityWindow,
srv.IssuerURL,
emailer,
srv.absURL(httpPathResetPassword),
srv.absURL(httpPathEmailVerify),
srv.absURL(httpPathAcceptInvitation),
)
clientCreds := map[string]oidc.ClientCredentials{}
for _, c := range clients {
clientCreds[c.Client.Credentials.ID] = c.Client.Credentials
}
return &testFixtures{
srv: srv,
redirectURL: testRedirectURL,
userRepo: userRepo,
sessionManager: sessionManager,
emailer: emailer,
clientRepo: clientRepo,
clientManager: clientManager,
clientCreds: clientCreds,
}, nil
}
func clientsToLoadableClients(cs []client.Client) []client.LoadableClient {
lcs := make([]client.LoadableClient, len(cs), len(cs))
for i, c := range cs {
lcs[i] = client.LoadableClient{
Client: c,
}
}
return lcs
}