|
|
|
|
@ -3,16 +3,13 @@ package functional
|
|
|
|
|
import ( |
|
|
|
|
"fmt" |
|
|
|
|
"html/template" |
|
|
|
|
"net" |
|
|
|
|
"net/url" |
|
|
|
|
"os" |
|
|
|
|
"strconv" |
|
|
|
|
"strings" |
|
|
|
|
"testing" |
|
|
|
|
|
|
|
|
|
"github.com/coreos/dex/connector" |
|
|
|
|
"github.com/coreos/dex/db" |
|
|
|
|
"github.com/coreos/dex/repo" |
|
|
|
|
"github.com/coreos/go-oidc/oidc" |
|
|
|
|
"gopkg.in/ldap.v2" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
@ -23,202 +20,106 @@ var (
|
|
|
|
|
ldapBindPw string |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
func init() { |
|
|
|
|
ldapuri := os.Getenv("DEX_TEST_LDAP_URI") |
|
|
|
|
if ldapuri == "" { |
|
|
|
|
fmt.Println("Unable to proceed with empty env var " + |
|
|
|
|
"DEX_TEST_LDAP_URI") |
|
|
|
|
os.Exit(1) |
|
|
|
|
} |
|
|
|
|
u, err := url.Parse(ldapuri) |
|
|
|
|
if err != nil { |
|
|
|
|
fmt.Println("Unable to parse DEX_TEST_LDAP_URI") |
|
|
|
|
os.Exit(1) |
|
|
|
|
} |
|
|
|
|
if strings.Index(u.RawQuery, "?") < 0 { |
|
|
|
|
fmt.Println("Unable to parse DEX_TEST_LDAP_URI") |
|
|
|
|
os.Exit(1) |
|
|
|
|
} |
|
|
|
|
extentions := make(map[string]string) |
|
|
|
|
kvs := strings.Split(strings.TrimLeft(u.RawQuery, "?"), ",") |
|
|
|
|
for i := range kvs { |
|
|
|
|
fmt.Println(kvs[i]) |
|
|
|
|
kv := strings.Split(kvs[i], "=") |
|
|
|
|
if len(kv) < 2 { |
|
|
|
|
fmt.Println("Unable to parse DEX_TEST_LDAP_URI") |
|
|
|
|
os.Exit(1) |
|
|
|
|
} |
|
|
|
|
extentions[kv[0]] = kv[1] |
|
|
|
|
} |
|
|
|
|
hostport := strings.Split(u.Host, ":") |
|
|
|
|
port := 389 |
|
|
|
|
if len(hostport) > 1 { |
|
|
|
|
port, _ = strconv.Atoi(hostport[1]) |
|
|
|
|
} |
|
|
|
|
type LDAPServer struct { |
|
|
|
|
Host string |
|
|
|
|
Port uint16 |
|
|
|
|
BindDN string |
|
|
|
|
BindPw string |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ldapHost = hostport[0] |
|
|
|
|
ldapPort = uint16(port) |
|
|
|
|
const ( |
|
|
|
|
ldapEnvHost = "DEX_TEST_LDAP_HOST" |
|
|
|
|
ldapEnvBindName = "DEX_TEST_LDAP_BINDNAME" |
|
|
|
|
ldapEnvBindPass = "DEX_TEST_LDAP_BINDPASS" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
if len(extentions["bindname"]) > 0 { |
|
|
|
|
ldapBindDN, err = url.QueryUnescape(extentions["bindname"]) |
|
|
|
|
func ldapServer(t *testing.T) LDAPServer { |
|
|
|
|
host := os.Getenv(ldapEnvHost) |
|
|
|
|
if host == "" { |
|
|
|
|
t.Fatalf("%s not set", ldapEnvHost) |
|
|
|
|
} |
|
|
|
|
var port uint64 = 389 |
|
|
|
|
if h, p, err := net.SplitHostPort(host); err == nil { |
|
|
|
|
port, err = strconv.ParseUint(p, 10, 16) |
|
|
|
|
if err != nil { |
|
|
|
|
fmt.Println("Unable to parse DEX_TEST_LDAP_URI") |
|
|
|
|
os.Exit(1) |
|
|
|
|
t.Fatalf("failed to parse port: %v", err) |
|
|
|
|
} |
|
|
|
|
host = h |
|
|
|
|
} |
|
|
|
|
if len(extentions["X-BINDPW"]) > 0 { |
|
|
|
|
ldapBindPw = extentions["X-BINDPW"] |
|
|
|
|
} |
|
|
|
|
return LDAPServer{host, uint16(port), os.Getenv(ldapEnvBindName), os.Getenv(ldapEnvBindPass)} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestLDAPConnect(t *testing.T) { |
|
|
|
|
fmt.Println("ldapHost: ", ldapHost) |
|
|
|
|
fmt.Println("ldapPort: ", ldapPort) |
|
|
|
|
fmt.Println("ldapBindDN: ", ldapBindDN) |
|
|
|
|
fmt.Println("ldapBindPw: ", ldapBindPw) |
|
|
|
|
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapHost, ldapPort)) |
|
|
|
|
server := ldapServer(t) |
|
|
|
|
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", server.Host, server.Port)) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
err = l.Bind(ldapBindDN, ldapBindPw) |
|
|
|
|
err = l.Bind(server.BindDN, server.BindPw) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
l.Close() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestConnectorLDAPConnectFail(t *testing.T) { |
|
|
|
|
var tx repo.Transaction |
|
|
|
|
var lf oidc.LoginFunc |
|
|
|
|
var ns url.URL |
|
|
|
|
|
|
|
|
|
templates := template.New(connector.LDAPLoginPageTemplateName) |
|
|
|
|
|
|
|
|
|
ccr := db.NewConnectorConfigRepo(db.NewMemDB()) |
|
|
|
|
err := ccr.Set( |
|
|
|
|
[]connector.ConnectorConfig{&connector.LDAPConnectorConfig{ |
|
|
|
|
ID: "ldap", |
|
|
|
|
ServerHost: ldapHost, |
|
|
|
|
ServerPort: ldapPort + 1, |
|
|
|
|
}}, |
|
|
|
|
) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
cc, err := ccr.GetConnectorByID(tx, "ldap") |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
c, err := cc.Connector(ns, lf, templates) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
err = c.Healthy() |
|
|
|
|
if err == nil { |
|
|
|
|
t.Fatal(fmt.Errorf("LDAPConnector.Healty() supposed to fail, but succeeded!")) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestConnectorLDAPConnectSuccess(t *testing.T) { |
|
|
|
|
var tx repo.Transaction |
|
|
|
|
var lf oidc.LoginFunc |
|
|
|
|
var ns url.URL |
|
|
|
|
|
|
|
|
|
templates := template.New(connector.LDAPLoginPageTemplateName) |
|
|
|
|
|
|
|
|
|
ccr := db.NewConnectorConfigRepo(db.NewMemDB()) |
|
|
|
|
err := ccr.Set( |
|
|
|
|
[]connector.ConnectorConfig{&connector.LDAPConnectorConfig{ |
|
|
|
|
ID: "ldap", |
|
|
|
|
ServerHost: ldapHost, |
|
|
|
|
ServerPort: ldapPort, |
|
|
|
|
}}, |
|
|
|
|
) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
cc, err := ccr.GetConnectorByID(tx, "ldap") |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
c, err := cc.Connector(ns, lf, templates) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
err = c.Healthy() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestConnectorLDAPcaFilecertFileConnectTLS(t *testing.T) { |
|
|
|
|
var tx repo.Transaction |
|
|
|
|
var lf oidc.LoginFunc |
|
|
|
|
var ns url.URL |
|
|
|
|
|
|
|
|
|
templates := template.New(connector.LDAPLoginPageTemplateName) |
|
|
|
|
|
|
|
|
|
ccr := db.NewConnectorConfigRepo(db.NewMemDB()) |
|
|
|
|
err := ccr.Set( |
|
|
|
|
[]connector.ConnectorConfig{&connector.LDAPConnectorConfig{ |
|
|
|
|
ID: "ldap", |
|
|
|
|
ServerHost: ldapHost, |
|
|
|
|
ServerPort: ldapPort, |
|
|
|
|
UseTLS: true, |
|
|
|
|
CertFile: "/tmp/ldap.crt", |
|
|
|
|
KeyFile: "/tmp/ldap.key", |
|
|
|
|
CaFile: "/tmp/openldap-ca.pem", |
|
|
|
|
}}, |
|
|
|
|
) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
cc, err := ccr.GetConnectorByID(tx, "ldap") |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
c, err := cc.Connector(ns, lf, templates) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
err = c.Healthy() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestConnectorLDAPcaFilecertFileConnectSSL(t *testing.T) { |
|
|
|
|
var tx repo.Transaction |
|
|
|
|
var lf oidc.LoginFunc |
|
|
|
|
var ns url.URL |
|
|
|
|
|
|
|
|
|
templates := template.New(connector.LDAPLoginPageTemplateName) |
|
|
|
|
|
|
|
|
|
ccr := db.NewConnectorConfigRepo(db.NewMemDB()) |
|
|
|
|
err := ccr.Set( |
|
|
|
|
[]connector.ConnectorConfig{&connector.LDAPConnectorConfig{ |
|
|
|
|
ID: "ldap", |
|
|
|
|
ServerHost: ldapHost, |
|
|
|
|
ServerPort: ldapPort + 247, // 636
|
|
|
|
|
UseSSL: true, |
|
|
|
|
CertFile: "/tmp/ldap.crt", |
|
|
|
|
KeyFile: "/tmp/ldap.key", |
|
|
|
|
CaFile: "/tmp/openldap-ca.pem", |
|
|
|
|
}}, |
|
|
|
|
) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
cc, err := ccr.GetConnectorByID(tx, "ldap") |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
c, err := cc.Connector(ns, lf, templates) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
err = c.Healthy() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
func TestConnectorLDAPHealthy(t *testing.T) { |
|
|
|
|
server := ldapServer(t) |
|
|
|
|
|
|
|
|
|
tests := []struct { |
|
|
|
|
config connector.LDAPConnectorConfig |
|
|
|
|
wantErr bool |
|
|
|
|
}{ |
|
|
|
|
{ |
|
|
|
|
config: connector.LDAPConnectorConfig{ |
|
|
|
|
ID: "ldap", |
|
|
|
|
ServerHost: server.Host, |
|
|
|
|
ServerPort: server.Port + 1, |
|
|
|
|
}, |
|
|
|
|
wantErr: true, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
config: connector.LDAPConnectorConfig{ |
|
|
|
|
ID: "ldap", |
|
|
|
|
ServerHost: server.Host, |
|
|
|
|
ServerPort: server.Port, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
config: connector.LDAPConnectorConfig{ |
|
|
|
|
ID: "ldap", |
|
|
|
|
ServerHost: server.Host, |
|
|
|
|
ServerPort: server.Port, |
|
|
|
|
UseTLS: true, |
|
|
|
|
CertFile: "/tmp/ldap.crt", |
|
|
|
|
KeyFile: "/tmp/ldap.key", |
|
|
|
|
CaFile: "/tmp/openldap-ca.pem", |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
config: connector.LDAPConnectorConfig{ |
|
|
|
|
ID: "ldap", |
|
|
|
|
ServerHost: server.Host, |
|
|
|
|
ServerPort: server.Port + 247, // 636
|
|
|
|
|
UseSSL: true, |
|
|
|
|
CertFile: "/tmp/ldap.crt", |
|
|
|
|
KeyFile: "/tmp/ldap.key", |
|
|
|
|
CaFile: "/tmp/openldap-ca.pem", |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
for i, tt := range tests { |
|
|
|
|
templates := template.New(connector.LDAPLoginPageTemplateName) |
|
|
|
|
c, err := tt.config.Connector(url.URL{}, nil, templates) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Errorf("case %d: failed to create connector: %v", i, err) |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
if err := c.Healthy(); err != nil { |
|
|
|
|
if !tt.wantErr { |
|
|
|
|
t.Errorf("case %d: Healthy() returned error: %v", i, err) |
|
|
|
|
} |
|
|
|
|
} else if tt.wantErr { |
|
|
|
|
t.Errorf("case %d: expected Healthy() to fail", i) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|