forked from mystiq/dex
connector/ldap: support the StartTLS flow for secure connections
When connecting to an LDAP server, there are three ways to connect: 1. Insecurely through port 389 (LDAP). 2. Securely through port 696 (LDAPS). 3. Insecurely through port 389 then negotiate TLS (StartTLS). This PR adds support for the 3rd flow, letting dex connect to the standard LDAP port then negotiating TLS through the LDAP protocol itself. See a writeup here: http://www.openldap.org/faq/data/cache/185.html
This commit is contained in:
parent
9b0af83604
commit
74f5eaf47e
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-----
|
Loading…
Reference in a new issue