Merge branch 'master' into feature/static_password_env
This commit is contained in:
@@ -161,6 +161,8 @@ func testAuthRequestCRUD(t *testing.T, s storage.Storage) {
|
||||
t.Fatalf("failed to delete auth request: %v", err)
|
||||
}
|
||||
|
||||
_, err = s.GetAuthRequest(a1.ID)
|
||||
mustBeErrNotFound(t, "auth request", err)
|
||||
}
|
||||
|
||||
func testAuthCodeCRUD(t *testing.T, s storage.Storage) {
|
||||
@@ -214,7 +216,7 @@ func testAuthCodeCRUD(t *testing.T, s storage.Storage) {
|
||||
|
||||
got, err := s.GetAuthCode(a1.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get auth req: %v", err)
|
||||
t.Fatalf("failed to get auth code: %v", err)
|
||||
}
|
||||
if a1.Expiry.Unix() != got.Expiry.Unix() {
|
||||
t.Errorf("auth code expiry did not match want=%s vs got=%s", a1.Expiry, got.Expiry)
|
||||
@@ -509,7 +511,6 @@ func testPasswordCRUD(t *testing.T, s storage.Storage) {
|
||||
|
||||
_, err = s.GetPassword(password1.Email)
|
||||
mustBeErrNotFound(t, "password", err)
|
||||
|
||||
}
|
||||
|
||||
func testOfflineSessionCRUD(t *testing.T, s storage.Storage) {
|
||||
@@ -814,7 +815,7 @@ func testGC(t *testing.T, s storage.Storage) {
|
||||
}
|
||||
}
|
||||
if _, err := s.GetAuthRequest(a.ID); err != nil {
|
||||
t.Errorf("expected to be able to get auth code after GC: %v", err)
|
||||
t.Errorf("expected to be able to get auth request after GC: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -825,7 +826,7 @@ func testGC(t *testing.T, s storage.Storage) {
|
||||
}
|
||||
|
||||
if _, err := s.GetAuthRequest(a.ID); err == nil {
|
||||
t.Errorf("expected auth code to be GC'd")
|
||||
t.Errorf("expected auth request to be GC'd")
|
||||
} else if err != storage.ErrNotFound {
|
||||
t.Errorf("expected storage.ErrNotFound, got %v", err)
|
||||
}
|
||||
|
||||
@@ -135,8 +135,8 @@ func testKeysConcurrentUpdate(t *testing.T, s storage.Storage) {
|
||||
for i := 0; i < 2; i++ {
|
||||
n := time.Now().UTC().Round(time.Second)
|
||||
keys1 := storage.Keys{
|
||||
SigningKey: jsonWebKeys[0].Private,
|
||||
SigningKeyPub: jsonWebKeys[0].Public,
|
||||
SigningKey: jsonWebKeys[i].Private,
|
||||
SigningKeyPub: jsonWebKeys[i].Public,
|
||||
NextRotation: n,
|
||||
}
|
||||
|
||||
|
||||
@@ -156,7 +156,7 @@ func (c *conn) UpdateRefreshToken(id string, updater func(old storage.RefreshTok
|
||||
return c.txnUpdate(ctx, keyID(refreshTokenPrefix, id), func(currentValue []byte) ([]byte, error) {
|
||||
var current RefreshToken
|
||||
if len(currentValue) > 0 {
|
||||
if err := json.Unmarshal([]byte(currentValue), ¤t); err != nil {
|
||||
if err := json.Unmarshal(currentValue, ¤t); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,14 +55,14 @@ type client struct {
|
||||
}
|
||||
|
||||
// idToName maps an arbitrary ID, such as an email or client ID to a Kubernetes object name.
|
||||
func (c *client) idToName(s string) string {
|
||||
return idToName(s, c.hash)
|
||||
func (cli *client) idToName(s string) string {
|
||||
return idToName(s, cli.hash)
|
||||
}
|
||||
|
||||
// offlineTokenName maps two arbitrary IDs, to a single Kubernetes object name.
|
||||
// This is used when more than one field is used to uniquely identify the object.
|
||||
func (c *client) offlineTokenName(userID string, connID string) string {
|
||||
return offlineTokenName(userID, connID, c.hash)
|
||||
func (cli *client) offlineTokenName(userID string, connID string) string {
|
||||
return offlineTokenName(userID, connID, cli.hash)
|
||||
}
|
||||
|
||||
// Kubernetes names must match the regexp '[a-z0-9]([-a-z0-9]*[a-z0-9])?'.
|
||||
@@ -79,7 +79,7 @@ func offlineTokenName(userID string, connID string, h func() hash.Hash) string {
|
||||
return strings.TrimRight(encoding.EncodeToString(hash.Sum(nil)), "=")
|
||||
}
|
||||
|
||||
func (c *client) urlFor(apiVersion, namespace, resource, name string) string {
|
||||
func (cli *client) urlFor(apiVersion, namespace, resource, name string) string {
|
||||
basePath := "apis/"
|
||||
if apiVersion == "v1" {
|
||||
basePath = "api/"
|
||||
@@ -91,10 +91,10 @@ func (c *client) urlFor(apiVersion, namespace, resource, name string) string {
|
||||
} else {
|
||||
p = path.Join(basePath, apiVersion, resource, name)
|
||||
}
|
||||
if strings.HasSuffix(c.baseURL, "/") {
|
||||
return c.baseURL + p
|
||||
if strings.HasSuffix(cli.baseURL, "/") {
|
||||
return cli.baseURL + p
|
||||
}
|
||||
return c.baseURL + "/" + p
|
||||
return cli.baseURL + "/" + p
|
||||
}
|
||||
|
||||
// Define an error interface so we can get at the underlying status code if it's
|
||||
@@ -156,13 +156,13 @@ func closeResp(r *http.Response) {
|
||||
r.Body.Close()
|
||||
}
|
||||
|
||||
func (c *client) get(resource, name string, v interface{}) error {
|
||||
return c.getResource(c.apiVersion, c.namespace, resource, name, v)
|
||||
func (cli *client) get(resource, name string, v interface{}) error {
|
||||
return cli.getResource(cli.apiVersion, cli.namespace, resource, name, v)
|
||||
}
|
||||
|
||||
func (c *client) getResource(apiVersion, namespace, resource, name string, v interface{}) error {
|
||||
url := c.urlFor(apiVersion, namespace, resource, name)
|
||||
resp, err := c.client.Get(url)
|
||||
func (cli *client) getResource(apiVersion, namespace, resource, name string, v interface{}) error {
|
||||
url := cli.urlFor(apiVersion, namespace, resource, name)
|
||||
resp, err := cli.client.Get(url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -173,22 +173,22 @@ func (c *client) getResource(apiVersion, namespace, resource, name string, v int
|
||||
return json.NewDecoder(resp.Body).Decode(v)
|
||||
}
|
||||
|
||||
func (c *client) list(resource string, v interface{}) error {
|
||||
return c.get(resource, "", v)
|
||||
func (cli *client) list(resource string, v interface{}) error {
|
||||
return cli.get(resource, "", v)
|
||||
}
|
||||
|
||||
func (c *client) post(resource string, v interface{}) error {
|
||||
return c.postResource(c.apiVersion, c.namespace, resource, v)
|
||||
func (cli *client) post(resource string, v interface{}) error {
|
||||
return cli.postResource(cli.apiVersion, cli.namespace, resource, v)
|
||||
}
|
||||
|
||||
func (c *client) postResource(apiVersion, namespace, resource string, v interface{}) error {
|
||||
func (cli *client) postResource(apiVersion, namespace, resource string, v interface{}) error {
|
||||
body, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshal object: %v", err)
|
||||
}
|
||||
|
||||
url := c.urlFor(apiVersion, namespace, resource, "")
|
||||
resp, err := c.client.Post(url, "application/json", bytes.NewReader(body))
|
||||
url := cli.urlFor(apiVersion, namespace, resource, "")
|
||||
resp, err := cli.client.Post(url, "application/json", bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -196,13 +196,13 @@ func (c *client) postResource(apiVersion, namespace, resource string, v interfac
|
||||
return checkHTTPErr(resp, http.StatusCreated)
|
||||
}
|
||||
|
||||
func (c *client) delete(resource, name string) error {
|
||||
url := c.urlFor(c.apiVersion, c.namespace, resource, name)
|
||||
func (cli *client) delete(resource, name string) error {
|
||||
url := cli.urlFor(cli.apiVersion, cli.namespace, resource, name)
|
||||
req, err := http.NewRequest("DELETE", url, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create delete request: %v", err)
|
||||
}
|
||||
resp, err := c.client.Do(req)
|
||||
resp, err := cli.client.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete request: %v", err)
|
||||
}
|
||||
@@ -210,7 +210,7 @@ func (c *client) delete(resource, name string) error {
|
||||
return checkHTTPErr(resp, http.StatusOK)
|
||||
}
|
||||
|
||||
func (c *client) deleteAll(resource string) error {
|
||||
func (cli *client) deleteAll(resource string) error {
|
||||
var list struct {
|
||||
k8sapi.TypeMeta `json:",inline"`
|
||||
k8sapi.ListMeta `json:"metadata,omitempty"`
|
||||
@@ -219,24 +219,24 @@ func (c *client) deleteAll(resource string) error {
|
||||
k8sapi.ObjectMeta `json:"metadata,omitempty"`
|
||||
} `json:"items"`
|
||||
}
|
||||
if err := c.list(resource, &list); err != nil {
|
||||
if err := cli.list(resource, &list); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, item := range list.Items {
|
||||
if err := c.delete(resource, item.Name); err != nil {
|
||||
if err := cli.delete(resource, item.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *client) put(resource, name string, v interface{}) error {
|
||||
func (cli *client) put(resource, name string, v interface{}) error {
|
||||
body, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshal object: %v", err)
|
||||
}
|
||||
|
||||
url := c.urlFor(c.apiVersion, c.namespace, resource, name)
|
||||
url := cli.urlFor(cli.apiVersion, cli.namespace, resource, name)
|
||||
req, err := http.NewRequest("PUT", url, bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return fmt.Errorf("create patch request: %v", err)
|
||||
@@ -244,7 +244,7 @@ func (c *client) put(resource, name string, v interface{}) error {
|
||||
|
||||
req.Header.Set("Content-Length", strconv.Itoa(len(body)))
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
resp, err := cli.client.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("patch request: %v", err)
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ type CustomResourceDefinitionNames struct {
|
||||
ListKind string `json:"listKind,omitempty" protobuf:"bytes,5,opt,name=listKind"`
|
||||
}
|
||||
|
||||
// ResourceScope is an enum defining the different scopes availabe to a custom resource
|
||||
// ResourceScope is an enum defining the different scopes available to a custom resource
|
||||
type ResourceScope string
|
||||
|
||||
const (
|
||||
|
||||
@@ -1,39 +1,104 @@
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"sigs.k8s.io/testing_frameworks/integration"
|
||||
|
||||
"github.com/dexidp/dex/storage"
|
||||
"github.com/dexidp/dex/storage/conformance"
|
||||
)
|
||||
|
||||
const testKubeConfigEnv = "DEX_KUBECONFIG"
|
||||
const kubeconfigTemplate = `apiVersion: v1
|
||||
kind: Config
|
||||
clusters:
|
||||
- name: local
|
||||
cluster:
|
||||
server: SERVERURL
|
||||
users:
|
||||
- name: local
|
||||
user:
|
||||
contexts:
|
||||
- context:
|
||||
cluster: local
|
||||
user: local
|
||||
`
|
||||
|
||||
func TestLoadClient(t *testing.T) {
|
||||
loadClient(t)
|
||||
func TestStorage(t *testing.T) {
|
||||
if os.Getenv("TEST_ASSET_KUBE_APISERVER") == "" || os.Getenv("TEST_ASSET_ETCD") == "" {
|
||||
t.Skip("control plane binaries are missing")
|
||||
}
|
||||
|
||||
suite.Run(t, new(StorageTestSuite))
|
||||
}
|
||||
|
||||
func loadClient(t *testing.T) *client {
|
||||
type StorageTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
controlPlane *integration.ControlPlane
|
||||
|
||||
client *client
|
||||
}
|
||||
|
||||
func (s *StorageTestSuite) SetupSuite() {
|
||||
s.controlPlane = &integration.ControlPlane{}
|
||||
|
||||
err := s.controlPlane.Start()
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
func (s *StorageTestSuite) TearDownSuite() {
|
||||
s.controlPlane.Stop()
|
||||
}
|
||||
|
||||
func (s *StorageTestSuite) SetupTest() {
|
||||
f, err := ioutil.TempFile("", "dex-kubeconfig-*")
|
||||
s.Require().NoError(err)
|
||||
defer f.Close()
|
||||
|
||||
_, err = f.WriteString(strings.ReplaceAll(kubeconfigTemplate, "SERVERURL", s.controlPlane.APIURL().String()))
|
||||
s.Require().NoError(err)
|
||||
|
||||
config := Config{
|
||||
KubeConfigFile: os.Getenv(testKubeConfigEnv),
|
||||
}
|
||||
if config.KubeConfigFile == "" {
|
||||
t.Skipf("test environment variable %q not set, skipping", testKubeConfigEnv)
|
||||
KubeConfigFile: f.Name(),
|
||||
}
|
||||
|
||||
logger := &logrus.Logger{
|
||||
Out: os.Stderr,
|
||||
Formatter: &logrus.TextFormatter{DisableColors: true},
|
||||
Level: logrus.DebugLevel,
|
||||
}
|
||||
s, err := config.open(logger, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
client, err := config.open(logger, true)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.client = client
|
||||
}
|
||||
|
||||
func (s *StorageTestSuite) TestStorage() {
|
||||
newStorage := func() storage.Storage {
|
||||
for _, resource := range []string{
|
||||
resourceAuthCode,
|
||||
resourceAuthRequest,
|
||||
resourceClient,
|
||||
resourceRefreshToken,
|
||||
resourceKeys,
|
||||
resourcePassword,
|
||||
} {
|
||||
if err := s.client.deleteAll(resource); err != nil {
|
||||
s.T().Fatalf("delete all %q failed: %v", resource, err)
|
||||
}
|
||||
}
|
||||
return s.client
|
||||
}
|
||||
return s
|
||||
|
||||
conformance.RunTests(s.T(), newStorage)
|
||||
conformance.RunTransactionTests(s.T(), newStorage)
|
||||
}
|
||||
|
||||
func TestURLFor(t *testing.T) {
|
||||
@@ -83,27 +148,3 @@ func TestURLFor(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStorage(t *testing.T) {
|
||||
client := loadClient(t)
|
||||
newStorage := func() storage.Storage {
|
||||
for _, resource := range []string{
|
||||
resourceAuthCode,
|
||||
resourceAuthRequest,
|
||||
resourceClient,
|
||||
resourceRefreshToken,
|
||||
resourceKeys,
|
||||
resourcePassword,
|
||||
} {
|
||||
if err := client.deleteAll(resource); err != nil {
|
||||
// Fatalf sometimes doesn't print the error message.
|
||||
fmt.Fprintf(os.Stderr, "delete all %q failed: %v\n", resource, err)
|
||||
t.Fatalf("delete all %q failed: %v", resource, err)
|
||||
}
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
conformance.RunTests(t, newStorage)
|
||||
conformance.RunTransactionTests(t, newStorage)
|
||||
}
|
||||
|
||||
@@ -308,10 +308,17 @@ func (s *MySQL) open(logger log.Logger) (*conn, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if s.MaxIdleConns == 0 {
|
||||
/*Override default behaviour to fix https://github.com/dexidp/dex/issues/1608*/
|
||||
db.SetMaxIdleConns(0)
|
||||
} else {
|
||||
db.SetMaxIdleConns(s.MaxIdleConns)
|
||||
}
|
||||
|
||||
err = db.Ping()
|
||||
if err != nil {
|
||||
if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == mysqlErrUnknownSysVar {
|
||||
logger.Info("reconnecting with MySQL pre-5.7.20 compatibilty mode")
|
||||
logger.Info("reconnecting with MySQL pre-5.7.20 compatibility mode")
|
||||
|
||||
// MySQL 5.7.20 introduced transaction_isolation and deprecated tx_isolation.
|
||||
// MySQL 8.0 doesn't have tx_isolation at all.
|
||||
|
||||
@@ -169,7 +169,6 @@ func (c *conn) UpdateAuthRequest(id string, updater func(a storage.AuthRequest)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func (c *conn) GetAuthRequest(id string) (storage.AuthRequest, error) {
|
||||
|
||||
Reference in New Issue
Block a user