Merge pull request #908 from ericchiang/start-tls
connector/ldap: support the StartTLS flow for secure connections
This commit is contained in:
commit
e609de5018
8 changed files with 334 additions and 27 deletions
|
@ -30,20 +30,28 @@ connectors:
|
|||
name: LDAP
|
||||
config:
|
||||
# Host and optional port of the LDAP server in the form "host:port".
|
||||
# If the port is not supplied, it will be guessed based on "insecureNoSSL".
|
||||
# 389 for insecure connections, 636 otherwise.
|
||||
# If the port is not supplied, it will be guessed based on "insecureNoSSL",
|
||||
# and "startTLS" flags. 389 for insecure or StartTLS connections, 636
|
||||
# otherwise.
|
||||
host: ldap.example.com:636
|
||||
|
||||
# Following field is required if the LDAP host is not using TLS (port 389).
|
||||
# Because this option inherently leaks passwords to anyone on the same network
|
||||
# as dex, THIS OPTION MAY BE REMOVED WITHOUT WARNING IN A FUTURE RELEASE.
|
||||
#
|
||||
# insecureNoSSL: true
|
||||
|
||||
# If a custom certificate isn't provide, this option can be used to turn on
|
||||
# TLS certificate checks. As noted, it is insecure and shouldn't be used outside
|
||||
# of explorative phases.
|
||||
#
|
||||
# insecureSkipVerify: true
|
||||
|
||||
# When connecting to the server, connect using the ldap:// protocol then issue
|
||||
# a StartTLS command. If unspecified, connections will use the ldaps:// protocol
|
||||
#
|
||||
# startTLS: true
|
||||
|
||||
# Path to a trusted root certificate file. Default: use the host's root CA.
|
||||
rootCA: /etc/dex/ldap.ca
|
||||
|
||||
|
|
49
connector/ldap/gen-certs.sh
Executable file
49
connector/ldap/gen-certs.sh
Executable file
|
@ -0,0 +1,49 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
# Stolen from the coreos/matchbox repo.
|
||||
|
||||
echo "
|
||||
[req]
|
||||
req_extensions = v3_req
|
||||
distinguished_name = req_distinguished_name
|
||||
|
||||
[req_distinguished_name]
|
||||
|
||||
[ v3_req ]
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[alt_names]
|
||||
DNS.101 = localhost
|
||||
" > openssl.config
|
||||
|
||||
openssl genrsa -out testdata/ca.key 2048
|
||||
openssl genrsa -out testdata/server.key 2048
|
||||
|
||||
openssl req \
|
||||
-x509 -new -nodes \
|
||||
-key testdata/ca.key \
|
||||
-days 10000 -out testdata/ca.crt \
|
||||
-subj "/CN=ldap-tests"
|
||||
|
||||
openssl req \
|
||||
-new \
|
||||
-key testdata/server.key \
|
||||
-out testdata/server.csr \
|
||||
-subj "/CN=localhost" \
|
||||
-config openssl.config
|
||||
|
||||
openssl x509 -req \
|
||||
-in testdata/server.csr \
|
||||
-CA testdata/ca.crt \
|
||||
-CAkey testdata/ca.key \
|
||||
-CAcreateserial \
|
||||
-out testdata/server.crt \
|
||||
-days 10000 \
|
||||
-extensions v3_req \
|
||||
-extfile openssl.config
|
||||
|
||||
rm testdata/server.csr
|
||||
rm testdata/ca.srl
|
||||
rm openssl.config
|
|
@ -61,6 +61,11 @@ type Config struct {
|
|||
// Don't verify the CA.
|
||||
InsecureSkipVerify bool `json:"insecureSkipVerify"`
|
||||
|
||||
// Connect to the insecure port then issue a StartTLS command to negotiate a
|
||||
// secure connection. If unsupplied secure connections will use the LDAPS
|
||||
// protocol.
|
||||
StartTLS bool `json:"startTLS"`
|
||||
|
||||
// Path to a trusted root certificate file.
|
||||
RootCA string `json:"rootCA"`
|
||||
|
||||
|
@ -238,9 +243,18 @@ func (c *ldapConnector) do(ctx context.Context, f func(c *ldap.Conn) error) erro
|
|||
conn *ldap.Conn
|
||||
err error
|
||||
)
|
||||
if c.InsecureNoSSL {
|
||||
switch {
|
||||
case c.InsecureNoSSL:
|
||||
conn, err = ldap.Dial("tcp", c.Host)
|
||||
} else {
|
||||
case c.StartTLS:
|
||||
conn, err = ldap.Dial("tcp", c.Host)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect: %v", err)
|
||||
}
|
||||
if err := conn.StartTLS(c.tlsConfig); err != nil {
|
||||
return fmt.Errorf("start TLS failed: %v", err)
|
||||
}
|
||||
default:
|
||||
conn, err = ldap.DialTLS("tcp", c.Host, c.tlsConfig)
|
||||
}
|
||||
if err != nil {
|
||||
|
|
|
@ -21,6 +21,15 @@ import (
|
|||
|
||||
const envVar = "DEX_LDAP_TESTS"
|
||||
|
||||
// connectionMethod indicates how the test should connect to the LDAP server.
|
||||
type connectionMethod int32
|
||||
|
||||
const (
|
||||
connectStartTLS connectionMethod = iota
|
||||
connectLDAPS
|
||||
connectLDAP
|
||||
)
|
||||
|
||||
// subtest is a login test against a given schema.
|
||||
type subtest struct {
|
||||
// Name of the sub-test.
|
||||
|
@ -110,7 +119,7 @@ userpassword: bar
|
|||
},
|
||||
}
|
||||
|
||||
runTests(t, schema, c, tests)
|
||||
runTests(t, schema, connectLDAP, c, tests)
|
||||
}
|
||||
|
||||
func TestGroupQuery(t *testing.T) {
|
||||
|
@ -198,7 +207,7 @@ member: cn=jane,ou=People,dc=example,dc=org
|
|||
},
|
||||
}
|
||||
|
||||
runTests(t, schema, c, tests)
|
||||
runTests(t, schema, connectLDAP, c, tests)
|
||||
}
|
||||
|
||||
func TestGroupsOnUserEntity(t *testing.T) {
|
||||
|
@ -295,7 +304,93 @@ gidNumber: 1002
|
|||
},
|
||||
},
|
||||
}
|
||||
runTests(t, schema, c, tests)
|
||||
runTests(t, schema, connectLDAP, c, tests)
|
||||
}
|
||||
|
||||
func TestStartTLS(t *testing.T) {
|
||||
schema := `
|
||||
dn: dc=example,dc=org
|
||||
objectClass: dcObject
|
||||
objectClass: organization
|
||||
o: Example Company
|
||||
dc: example
|
||||
|
||||
dn: ou=People,dc=example,dc=org
|
||||
objectClass: organizationalUnit
|
||||
ou: People
|
||||
|
||||
dn: cn=jane,ou=People,dc=example,dc=org
|
||||
objectClass: person
|
||||
objectClass: inetOrgPerson
|
||||
sn: doe
|
||||
cn: jane
|
||||
mail: janedoe@example.com
|
||||
userpassword: foo
|
||||
`
|
||||
c := &Config{}
|
||||
c.UserSearch.BaseDN = "ou=People,dc=example,dc=org"
|
||||
c.UserSearch.NameAttr = "cn"
|
||||
c.UserSearch.EmailAttr = "mail"
|
||||
c.UserSearch.IDAttr = "DN"
|
||||
c.UserSearch.Username = "cn"
|
||||
|
||||
tests := []subtest{
|
||||
{
|
||||
name: "validpassword",
|
||||
username: "jane",
|
||||
password: "foo",
|
||||
want: connector.Identity{
|
||||
UserID: "cn=jane,ou=People,dc=example,dc=org",
|
||||
Username: "jane",
|
||||
Email: "janedoe@example.com",
|
||||
EmailVerified: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
runTests(t, schema, connectStartTLS, c, tests)
|
||||
}
|
||||
|
||||
func TestLDAPS(t *testing.T) {
|
||||
schema := `
|
||||
dn: dc=example,dc=org
|
||||
objectClass: dcObject
|
||||
objectClass: organization
|
||||
o: Example Company
|
||||
dc: example
|
||||
|
||||
dn: ou=People,dc=example,dc=org
|
||||
objectClass: organizationalUnit
|
||||
ou: People
|
||||
|
||||
dn: cn=jane,ou=People,dc=example,dc=org
|
||||
objectClass: person
|
||||
objectClass: inetOrgPerson
|
||||
sn: doe
|
||||
cn: jane
|
||||
mail: janedoe@example.com
|
||||
userpassword: foo
|
||||
`
|
||||
c := &Config{}
|
||||
c.UserSearch.BaseDN = "ou=People,dc=example,dc=org"
|
||||
c.UserSearch.NameAttr = "cn"
|
||||
c.UserSearch.EmailAttr = "mail"
|
||||
c.UserSearch.IDAttr = "DN"
|
||||
c.UserSearch.Username = "cn"
|
||||
|
||||
tests := []subtest{
|
||||
{
|
||||
name: "validpassword",
|
||||
username: "jane",
|
||||
password: "foo",
|
||||
want: connector.Identity{
|
||||
UserID: "cn=jane,ou=People,dc=example,dc=org",
|
||||
Username: "jane",
|
||||
Email: "janedoe@example.com",
|
||||
EmailVerified: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
runTests(t, schema, connectLDAPS, c, tests)
|
||||
}
|
||||
|
||||
// runTests runs a set of tests against an LDAP schema. It does this by
|
||||
|
@ -305,7 +400,7 @@ gidNumber: 1002
|
|||
// machine's PATH.
|
||||
//
|
||||
// The DEX_LDAP_TESTS must be set to "1"
|
||||
func runTests(t *testing.T, schema string, config *Config, tests []subtest) {
|
||||
func runTests(t *testing.T, schema string, connMethod connectionMethod, config *Config, tests []subtest) {
|
||||
if os.Getenv(envVar) != "1" {
|
||||
t.Skipf("%s not set. Skipping test (run 'export %s=1' to run tests)", envVar, envVar)
|
||||
}
|
||||
|
@ -316,6 +411,11 @@ func runTests(t *testing.T, schema string, config *Config, tests []subtest) {
|
|||
}
|
||||
}
|
||||
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tempDir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -324,7 +424,13 @@ func runTests(t *testing.T, schema string, config *Config, tests []subtest) {
|
|||
|
||||
configBytes := new(bytes.Buffer)
|
||||
|
||||
if err := slapdConfigTmpl.Execute(configBytes, tmplData{tempDir, includes(t)}); err != nil {
|
||||
data := tmplData{
|
||||
TempDir: tempDir,
|
||||
Includes: includes(t, wd),
|
||||
}
|
||||
data.TLSCertPath, data.TLSKeyPath = tlsAssets(t, wd)
|
||||
|
||||
if err := slapdConfigTmpl.Execute(configBytes, data); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -344,7 +450,7 @@ func runTests(t *testing.T, schema string, config *Config, tests []subtest) {
|
|||
cmd := exec.Command(
|
||||
"slapd",
|
||||
"-d", "any",
|
||||
"-h", "ldap://localhost:10363/ ldaps://localhost:10636/ ldapi://"+socketPath,
|
||||
"-h", "ldap://localhost:10389/ ldaps://localhost:10636/ ldapi://"+socketPath,
|
||||
"-f", configPath,
|
||||
)
|
||||
cmd.Stdout = slapdOut
|
||||
|
@ -385,18 +491,30 @@ func runTests(t *testing.T, schema string, config *Config, tests []subtest) {
|
|||
wg.Wait()
|
||||
}()
|
||||
|
||||
// Wait for slapd to come up.
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
// Try a few times to connect to the LDAP server. On slower machines
|
||||
// it can take a while for it to come up.
|
||||
connected := false
|
||||
wait := 100 * time.Millisecond
|
||||
for i := 0; i < 5; i++ {
|
||||
time.Sleep(wait)
|
||||
|
||||
ldapadd := exec.Command(
|
||||
"ldapadd", "-x",
|
||||
"-D", "cn=admin,dc=example,dc=org",
|
||||
"-w", "admin",
|
||||
"-f", schemaPath,
|
||||
"-H", "ldap://localhost:10363/",
|
||||
)
|
||||
if out, err := ldapadd.CombinedOutput(); err != nil {
|
||||
t.Errorf("ldapadd: %s", out)
|
||||
ldapadd := exec.Command(
|
||||
"ldapadd", "-x",
|
||||
"-D", "cn=admin,dc=example,dc=org",
|
||||
"-w", "admin",
|
||||
"-f", schemaPath,
|
||||
"-H", "ldap://localhost:10389/",
|
||||
)
|
||||
if out, err := ldapadd.CombinedOutput(); err != nil {
|
||||
t.Logf("ldapadd: %s", out)
|
||||
wait = wait * 2 // backoff
|
||||
continue
|
||||
}
|
||||
connected = true
|
||||
break
|
||||
}
|
||||
if !connected {
|
||||
t.Errorf("ldapadd command failed")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -405,8 +523,19 @@ func runTests(t *testing.T, schema string, config *Config, tests []subtest) {
|
|||
|
||||
// We need to configure host parameters but don't want to overwrite user or
|
||||
// group search configuration.
|
||||
c.Host = "localhost:10363"
|
||||
c.InsecureNoSSL = true
|
||||
switch connMethod {
|
||||
case connectStartTLS:
|
||||
c.Host = "localhost:10389"
|
||||
c.RootCA = "testdata/ca.crt"
|
||||
c.StartTLS = true
|
||||
case connectLDAPS:
|
||||
c.Host = "localhost:10636"
|
||||
c.RootCA = "testdata/ca.crt"
|
||||
case connectLDAP:
|
||||
c.Host = "localhost:10389"
|
||||
c.InsecureNoSSL = true
|
||||
}
|
||||
|
||||
c.BindDN = "cn=admin,dc=example,dc=org"
|
||||
c.BindPW = "admin"
|
||||
|
||||
|
@ -488,10 +617,16 @@ type tmplData struct {
|
|||
TempDir string
|
||||
// List of schema files to include.
|
||||
Includes []string
|
||||
// TLS assets for LDAPS.
|
||||
TLSKeyPath string
|
||||
TLSCertPath string
|
||||
}
|
||||
|
||||
// Config template copied from:
|
||||
// http://www.zytrax.com/books/ldap/ch5/index.html#step1-slapd
|
||||
//
|
||||
// TLS instructions found here:
|
||||
// http://www.openldap.org/doc/admin24/tls.html
|
||||
var slapdConfigTmpl = template.Must(template.New("").Parse(`
|
||||
{{ range $i, $include := .Includes }}
|
||||
include {{ $include }}
|
||||
|
@ -511,6 +646,9 @@ rootpw admin
|
|||
# change path as necessary
|
||||
directory {{ .TempDir }}
|
||||
|
||||
TLSCertificateFile {{ .TLSCertPath }}
|
||||
TLSCertificateKeyFile {{ .TLSKeyPath }}
|
||||
|
||||
# Indices to maintain for this directory
|
||||
# unique id so equality match only
|
||||
index uid eq
|
||||
|
@ -534,11 +672,18 @@ cachesize 10000
|
|||
checkpoint 128 15
|
||||
`))
|
||||
|
||||
func includes(t *testing.T) (paths []string) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("getting working directory: %v", err)
|
||||
func tlsAssets(t *testing.T, wd string) (certPath, keyPath string) {
|
||||
certPath = filepath.Join(wd, "testdata", "server.crt")
|
||||
keyPath = filepath.Join(wd, "testdata", "server.key")
|
||||
for _, p := range []string{certPath, keyPath} {
|
||||
if _, err := os.Stat(p); err != nil {
|
||||
t.Fatalf("failed to find TLS asset file: %s %v", p, err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func includes(t *testing.T, wd string) (paths []string) {
|
||||
for _, f := range includeFiles {
|
||||
p := filepath.Join(wd, "testdata", f)
|
||||
if _, err := os.Stat(p); err != nil {
|
||||
|
|
19
connector/ldap/testdata/ca.crt
vendored
Normal file
19
connector/ldap/testdata/ca.crt
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIC/TCCAeWgAwIBAgIJAIrt+AlVUsXKMA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV
|
||||
BAMMCmxkYXAtdGVzdHMwHhcNMTcwNDEyMjAxNzI5WhcNNDQwODI4MjAxNzI5WjAV
|
||||
MRMwEQYDVQQDDApsZGFwLXRlc3RzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||
CgKCAQEAzKJkt2WsALUDA3tQsedx7UJKIxis05+dU5FbBxf/BMSch8gCNh/cWErH
|
||||
IDljWGwLKbc9UefIz3BzbcNBPLgLGMp7t9Pf9HCBNf7lShLZB2BEGpgpCpd0urox
|
||||
xTqMEfchssJj75HOZRweHfBDDHk8LMHQYUBn5qTiuMYvBUbPVq69argE/kt5yAEW
|
||||
COZzzx38a11iY0gtPjY4Tc9vICsLHhTssNn/1wf+GFNzSTHqijC7NKW0txUneFQJ
|
||||
h6LAmKV/uZC84W1tqMDZKKpABiTpB+JbDvwsb9eXJ6YG6TgbKcrXjLy4ogbIrIRA
|
||||
s2DqMih792mxusIl6lRf3hTtCdyodwIDAQABo1AwTjAdBgNVHQ4EFgQUnfj9sAq4
|
||||
2xBbV4rf5FNvYaE2Bg0wHwYDVR0jBBgwFoAUnfj9sAq42xBbV4rf5FNvYaE2Bg0w
|
||||
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAFGnBH1qpLJLvrLWKNI5w
|
||||
u8pFYO3RGqmfJ3BGf60MQxdUaTIUNQxPfPATbth7t8GRJwpWESRDlaXWq9fM9rkt
|
||||
fbmuqjAMGTFloNd9ra6e2F0CKjwZWcn/3eG/mVw/5d1Ku9Ow8luKrZuzNzVJd13r
|
||||
hoNc1wYXN0pHWkNiRUuR/E4fE/sn+tYOpJ4XYQvKAcSrNrq8m5O9VG5gLvlTeNno
|
||||
6q9hBy+5XKYUdHlzbAGm9QL0e1R45Mu4qxcFluKEmzS1rXlLsLs4/pqHgreXlYgL
|
||||
f7K0cFvaJGnFRKaxa6Bpf1EPNtqSc/pQZh01Ww8CUu1xh2+5KufgJQjAHVG3a1ow
|
||||
dQ==
|
||||
-----END CERTIFICATE-----
|
27
connector/ldap/testdata/ca.key
vendored
Normal file
27
connector/ldap/testdata/ca.key
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAzKJkt2WsALUDA3tQsedx7UJKIxis05+dU5FbBxf/BMSch8gC
|
||||
Nh/cWErHIDljWGwLKbc9UefIz3BzbcNBPLgLGMp7t9Pf9HCBNf7lShLZB2BEGpgp
|
||||
Cpd0uroxxTqMEfchssJj75HOZRweHfBDDHk8LMHQYUBn5qTiuMYvBUbPVq69argE
|
||||
/kt5yAEWCOZzzx38a11iY0gtPjY4Tc9vICsLHhTssNn/1wf+GFNzSTHqijC7NKW0
|
||||
txUneFQJh6LAmKV/uZC84W1tqMDZKKpABiTpB+JbDvwsb9eXJ6YG6TgbKcrXjLy4
|
||||
ogbIrIRAs2DqMih792mxusIl6lRf3hTtCdyodwIDAQABAoIBAHQpEucQbe0Q058c
|
||||
VxhF+2PlJ1R441JV3ubbMkL6mibIvNpO7QJwX5I3EIX4Ta6Z1lRd0g82dcVbXgrG
|
||||
tbeT+aie+E/Hk++cFZzjDqFXxZ7sRHycN1/tzbNZknsU2wIvuQ9STYxmxjSbG3V/
|
||||
N3BTOZdmhbVO7Cv/GTwuM+7Y3UWkc74HaXfAgo1UIO9MtqgqP3H1Tv6ZIeKzl+mP
|
||||
wrvei0eQe6jI4W6+vUOX3SlrlrMxMTLK/Ce2MP1pJx++m8Ga23+vtna+lkOWnwcD
|
||||
NmhYl4dL31sDcE6Hz/T6Wwfdlfyugw8vi3a3GEYGMIwy27CFf/ccYnWPOI3oIHDe
|
||||
RwlXLCECgYEA595xJmfUpwqgYY80pT3JG3+64NWJ7f/gH0Ey9fivZfnTegjkI2Kc
|
||||
Uf7+odCq9I1TFtx10M72N4pXT1uLzJtINYty4ZIfOLG7jSraVbOuf9AvMNCYw+cT
|
||||
Fcf/HGUJEE95TKYDrGfklOYFNs3ZCcKOCYJOWCuwki8Vm2vtJpV6gnkCgYEA4e5b
|
||||
DI+YworLjokY8eP4aOF5BMuiFdGkYDjVQZG45RwjJdLwBjaf+HA4pAuJAr2LWiLX
|
||||
cdKpk+3AlJ8UMLIM+hBP4hBqnrPaRTkEhTXpbUA1lvL9o0mVDFgNh90guu5TeJza
|
||||
sW7JLaStmAyCxYGxbW4LTjR8GX9DPOPmLs5ZRm8CgYAyFW5DaXIZksYJzLEGcE4c
|
||||
Tn7DSdy9N+PlXGPxlYHteQUg+wKsUgSKAZZmxXfn0w77hSs9qzar0IoDbjbIP1Jd
|
||||
nn12E+YCjQGCAJugn2s12HYZCTW2Oxd4QPbt3zUR/NiqocFxYA+TygueRuB2pzue
|
||||
+jKKAQXmzZzRMYLMLsWDoQKBgAnrCcoyX5VivG7ka9jqlhQcmdBxFAt7KYkj1ZDM
|
||||
Ud6U7qIRcYIEUd95JbNl4jzhj0WEtAqGIfWhgUvE9ADzQAiWQLt+1v9ii9lwGFe0
|
||||
tyuZnwCiaCoL5+Qj1Ww6c95g6f8oe51AbMp5KTm8it0axWw1YX+sZCpGYPBCXO9/
|
||||
FYI3AoGBAMacjjbPjjfOXxBRhRz1rEDTrIStDj5KM4fgslKVGysqpH/mw7gSC8SK
|
||||
qn0anL2s3SAe9PQpOzM3pFFRZx4XMOk4ojYRZtp3FjPFDRnYuYzkfkbU7eV04awO
|
||||
6nrua8KNLNK+ir9iCi46tP6Zr3F81zWGUoVArVUgCRDbA9e0swB0
|
||||
-----END RSA PRIVATE KEY-----
|
18
connector/ldap/testdata/server.crt
vendored
Normal file
18
connector/ldap/testdata/server.crt
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIC3DCCAcSgAwIBAgIJANsmsx7hUWnHMA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV
|
||||
BAMMCmxkYXAtdGVzdHMwHhcNMTcwNDEyMjAxNzI5WhcNNDQwODI4MjAxNzI5WjAU
|
||||
MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
||||
AoIBAQDlWGC5X/TWgysEimM7n0hSkXRCITwAFxKG0C4EeppmL42DBcjQa0xrElRF
|
||||
h57EBZltbSfvTMDBZAyhx5oZKoETDfwy5jFzf4L4PazSkvfn4qWmCnrq4HNO5Vl7
|
||||
GBsW93bljsh2nfvoKDX2vBpEUe0qrZzJtRHq0ytfd6zXZ9+WFMsmhD9poADrH4hB
|
||||
/UOV3uCJPybOoy/WsANQpSgJPD886zakmF+54XQ3tExKzFA1rR4HJbU26h99U5kH
|
||||
346sV7/xKJLENQVIH1qsqyA1UPDZRWusABjdIPc9Racy0/MxTVE0k5lQbBvz9QSe
|
||||
HZvW+ct/aZX5tjxr9JlSY7tK2I9FAgMBAAGjMDAuMAkGA1UdEwQCMAAwCwYDVR0P
|
||||
BAQDAgXgMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEA
|
||||
RZp/fNjoQNaO6KW0Ay0aaPW6jPrcqGjzFgeIXaw/0UaWm5jhptWtjOAILV+afIrd
|
||||
4cKDg65o4xRdQYYbqmutFMAO/DeyDyMi3IL60qk0osipPDIORx5Ai2ZBQvUsGtwV
|
||||
np9UwQGNO5AGeR9N5kndyldbpxaIJFhsKOV8uRSi+4PRbMH3G0kJIX6wwZU4Ri/k
|
||||
3lWJQfqULH0vtMQCWSJuaYHxWYFq4AM+H/zpLwg1WG2eKVgSMWotxMRi5LOFSBbG
|
||||
XuOxAb0SNBcXl6kjRYbQyHBxIJMsB1lk64g7dTJqXuYFUwmIGL/vTr6PL6EKYk65
|
||||
/aWO8cvwXOrYaf9umgcqvg==
|
||||
-----END CERTIFICATE-----
|
27
connector/ldap/testdata/server.key
vendored
Normal file
27
connector/ldap/testdata/server.key
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEA5VhguV/01oMrBIpjO59IUpF0QiE8ABcShtAuBHqaZi+NgwXI
|
||||
0GtMaxJURYeexAWZbW0n70zAwWQMoceaGSqBEw38MuYxc3+C+D2s0pL35+Klpgp6
|
||||
6uBzTuVZexgbFvd25Y7Idp376Cg19rwaRFHtKq2cybUR6tMrX3es12fflhTLJoQ/
|
||||
aaAA6x+IQf1Dld7giT8mzqMv1rADUKUoCTw/POs2pJhfueF0N7RMSsxQNa0eByW1
|
||||
NuoffVOZB9+OrFe/8SiSxDUFSB9arKsgNVDw2UVrrAAY3SD3PUWnMtPzMU1RNJOZ
|
||||
UGwb8/UEnh2b1vnLf2mV+bY8a/SZUmO7StiPRQIDAQABAoIBAQDHBbKqK4MkxB8I
|
||||
ia8jhk4UmPTyjjSrP1pscyv75wkltA5xrQtfEj32jKlkzRQRt2o1c4w8NbbwHAp6
|
||||
OeSYAjKQfoplAS3YtMbK9XqMIc3QBPcK5/1S5gQqaw0DrR+VBpq/CvEbPm3kQUDT
|
||||
JNkGgLH3X0G4KNGrniT9a7UqGJIGgdBAr7bPESiDi9wuOwfhm/9TB8LOG8wB9cn4
|
||||
NcUipvjOcRxMFkyYtq056ZfGeoK2ooFe0lHi4j8sWXfII789OqN0plecAg8NGZsl
|
||||
klSncpTObE6eTXo9Jncio3pftvszEctKssK7vuL6opajtppT6C5FnKLb6NIAOo7j
|
||||
CPk1BRPhAoGBAPf8TMTr+l8MHRuVXEx52E1dBH46ZB8bMfvwb7cZ31Fn0EEmygCj
|
||||
wP9eKZ8MKmHVBbU6CbxYQMICTTwRrw9H0tNoaZBwzWMz/JDHcACfsPKtfrX8T4UQ
|
||||
wmVwbLctdC1Cbaxn1jYeSLoLfSe8IGPDnLpsMCzpRcQIgPS+gO69zr8vAoGBAOzB
|
||||
254TKd2OQPnvUvmAVYGRYyTu/+ShH9fZyDJYtjhQbuxt6eqh3poneWJOW+KPlqDd
|
||||
J0a8yv1pDXmCy5k1Oo8Nubt7cPI0y2z0nm5LvAaqPaFdUJs9nq9umH3svJh6du6Z
|
||||
+TZ6MDU/eyJRq7Mc5SQrssziJidS3cU21b560xvLAoGBAPYpZY9Ia7Uz0iUSY5eq
|
||||
j7Nj9VTT45UZKsnbRxnrvckSEyDJP1XZN3iG4Sv3KI8KpWrbHNTwif/Lxx0stKin
|
||||
dDjU+Y0e3FJwRXL19lE4M68B17kQp2MAWufU7KX8oclXmoS8YmBAOZMsWmU6ErDV
|
||||
eVt4j23VdaJ9inzoKhZTJcqTAoGAH9znJZsGo16lt/1ReWqgF1Ptt+bCYY6drnsM
|
||||
ylnODD4m74LLXFx0jOKLH4PUMeWJLBUXWBnIZ9pfid7kb7YOL3p1aJnwVWhtiDhT
|
||||
qhxfLbZznOfmFT5xwMJtm2Tk7NBueSYXuBExs7jbZX8AUJau7/NBmPlGkTxBxGzg
|
||||
z0XQa4kCgYBxYBXwFpLLjBO+bMMkoVOlMDj7feCOWP9CsnKQSHYqPbmmb+8mA7pN
|
||||
mIWfjSVynVe+Ncn0I5Uijbs9QDYqcfApJQ+iXeb+VGrg4QkLHHGd/5kIY28Evc6A
|
||||
KVyRIuiYNmgOXGpaFpMXSw718N4U7jWW7lqUxK2rvEupFhaL52oJFQ==
|
||||
-----END RSA PRIVATE KEY-----
|
Reference in a new issue