Skip to content

Commit

Permalink
Merge pull request #1022 from ericchiang/ldap-example
Browse files Browse the repository at this point in the history
*: add "getting started" example for LDAP
  • Loading branch information
rithujohn191 committed Aug 22, 2017
2 parents 9b46267 + 50f2905 commit e40c01e
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 2 deletions.
13 changes: 11 additions & 2 deletions Documentation/dev-integration-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,16 @@ $ sudo ./storage/sql/standup.sh destroy postgres

## LDAP

To run LDAP tests locally, you require a container running OpenLDAP.
The LDAP integration tests require [OpenLDAP][openldap] installed on the host machine. To run them, use `go test`:

Run OpenLDAP docker image:
```
export DEX_LDAP_TESTS=1
go test -v ./connector/ldap/
```

To quickly stand up a LDAP server for development, see the LDAP [_"Getting started"_][ldap-getting-started] example. This also requires OpenLDAP installed on the host.

To stand up a containerized LDAP server run the OpenLDAP docker image:

```
$ sudo docker run --hostname ldap.example.org --name openldap-container --detach osixia/openldap:1.1.6
Expand Down Expand Up @@ -136,3 +143,5 @@ connectors:
Start both dex and the example app, and try logging in (requires not requesting a refresh token).
[okta-sign-up]: https://www.okta.com/developer/signup/
[openldap]: https://www.openldap.org/
[ldap-getting-started]: ldap-connector.md#getting-started
3 changes: 3 additions & 0 deletions Documentation/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@ Login to dex through the example app using the following steps.

Dex is generally used as a building block to drive authentication for other apps. See [_"Writing apps that use dex"_][using-dex] for an overview of instrumenting apps to work with dex.

For a primer on using LDAP to back dex's user store, see the OpenLDAP [_"Getting started"_][ldap-getting-started] example.

Check out the Documentation directory for further reading on setting up different storages, interacting with the dex API, intros for OpenID Connect, and logging in through other identity providers such as Google, GitHub, or LDAP.

[go-setup]: https://golang.org/doc/install
[example-config]: ../examples/config-dev.yaml
[oidc-discovery]: https://openid.net/specs/openid-connect-discovery-1_0-17.html#ProviderMetadata
[using-dex]: using-dex.md
[ldap-getting-started]: ldap-connector.md#getting-started
26 changes: 26 additions & 0 deletions Documentation/ldap-connector.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,30 @@ The connector executes two primary queries:
1. Finding the user based on the end user's credentials.
2. Searching for groups using the user entry.

## Getting started

The dex repo contains a basic LDAP setup using [OpenLDAP][openldap].

First start the LDAP server using the example script. This will run the OpenLDAP daemon and seed it with a initial set of users.

```
./scripts/slapd.sh
```

This script sets the LDAP daemon to debug mode, and is expected to print several error messages which are normal. Once the server is up, run dex.

```
./bin/dex serve examples/config-ldap.yaml
```

Then run the OAuth client in another terminal.

```
./bin/example-app
```

Go to [http://localhost:5555](http://localhost:5555), login and enter the username and password of the LDAP user: `janedoe@example.com`/`foo`. Add the "groups" scope as part of the initial redirect to add group information from the LDAP server.

## Security considerations

Dex attempts to bind with the backing LDAP server using the end user's _plain text password_. Though some LDAP implementations allow passing hashed passwords, dex doesn't support hashing and instead _strongly recommends that all administrators just use TLS_. This can often be achieved by using port 636 instead of 389, and administrators that choose 389 are actively leaking passwords.
Expand Down Expand Up @@ -252,3 +276,5 @@ connectors:
```
If the search finds an entry, it will attempt to use the provided password to bind as that user entry.
[openldap]: https://www.openldap.org/
42 changes: 42 additions & 0 deletions examples/config-ldap.ldif
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
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

dn: cn=john,ou=People,dc=example,dc=org
objectClass: person
objectClass: inetOrgPerson
sn: doe
cn: john
mail: johndoe@example.com
userpassword: bar

# Group definitions.

dn: ou=Groups,dc=example,dc=org
objectClass: organizationalUnit
ou: Groups

dn: cn=admins,ou=Groups,dc=example,dc=org
objectClass: groupOfNames
cn: admins
member: cn=john,ou=People,dc=example,dc=org
member: cn=jane,ou=People,dc=example,dc=org

dn: cn=developers,ou=Groups,dc=example,dc=org
objectClass: groupOfNames
cn: developers
member: cn=jane,ou=People,dc=example,dc=org
51 changes: 51 additions & 0 deletions examples/config-ldap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
issuer: http://127.0.0.1:5556/dex
storage:
type: sqlite3
config:
file: examples/dex.db
web:
http: 0.0.0.0:5556

connectors:
- type: ldap
name: OpenLDAP
id: ldap
config:
host: localhost:10389

# No TLS for this setup.
insecureNoSSL: true

# This would normally be a read-only user.
bindDN: cn=admin,dc=example,dc=org
bindPW: admin

userSearch:
baseDN: ou=People,dc=example,dc=org
filter: "(objectClass=person)"
username: mail
# "DN" (case sensitive) is a special attribute name. It indicates that
# this value should be taken from the entity's DN not an attribute on
# the entity.
idAttr: DN
emailAttr: mail
nameAttr: cn

groupSearch:
baseDN: ou=Groups,dc=example,dc=org
filter: "(objectClass=groupOfNames)"

# A user is a member of a group when their DN matches
# the value of a "member" attribute on the group entity.
userAttr: DN
groupAttr: member

# The group name should be the "cn" value.
nameAttr: cn

staticClients:
- id: example-app
redirectURIs:
- 'http://127.0.0.1:5555/callback'
name: 'Example App'
secret: ZXhhbXBsZS1hcHAtc2VjcmV0
98 changes: 98 additions & 0 deletions scripts/slapd.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#!/bin/bash -e

if ! [[ "$0" =~ "scripts/slapd.sh" ]]; then
echo "This script must be run in a toplevel dex directory"
exit 255
fi

command -v slapd >/dev/null 2>&1 || {
echo >&2 "OpenLDAP not installed. Install using one of the following commands:
brew install openldap
sudo dnf -y install openldap-servers openldap-clients
sudo apt-get install slapd ldap-utils
"; exit 1;
}

TEMPDIR=$( mktemp -d )

trap "{ rm -r $TEMPDIR ; exit 255; }" EXIT

CONFIG_DIR=$PWD/connector/ldap/testdata

# Include the schema files in the connector test directory. Installing OpenLDAP installs
# these in /etc somewhere, but the path isn't reliable across installs. Easier to ship
# the schema files directly.
for config in $( ls $CONFIG_DIR/*.schema ); do
echo "include $config" >> $TEMPDIR/config
done

DATA_DIR=$TEMPDIR/data
mkdir $DATA_DIR

# Config template copied from:
# http://www.zytrax.com/books/ldap/ch5/index.html#step1-slapd
cat << EOF >> $TEMPDIR/config
# MODULELOAD definitions
# not required (comment out) before version 2.3
moduleload back_bdb.la
database bdb
suffix "dc=example,dc=org"
# root or superuser
rootdn "cn=admin,dc=example,dc=org"
rootpw admin
# The database directory MUST exist prior to running slapd AND
# change path as necessary
directory $DATA_DIR
# Indices to maintain for this directory
# unique id so equality match only
index uid eq
# allows general searching on commonname, givenname and email
index cn,gn,mail eq,sub
# allows multiple variants on surname searching
index sn eq,sub
# sub above includes subintial,subany,subfinal
# optimise department searches
index ou eq
# if searches will include objectClass uncomment following
# index objectClass eq
# shows use of default index parameter
index default eq,sub
# indices missing - uses default eq,sub
index telephonenumber
# other database parameters
# read more in slapd.conf reference section
cachesize 10000
checkpoint 128 15
EOF

SLAPD_PID=""
trap "kill $SLAPD_PID" SIGINT

# Background the LDAP daemon so we can run an LDAP add command.
slapd \
-d any \
-h "ldap://localhost:10389/" \
-f $TEMPDIR/config &
SLAPD_PID=$!

# Wait for server to come up.
time sleep 1

# Seed the initial set of users. Edit these values to change the initial
# set of users.
ldapadd \
-x \
-D "cn=admin,dc=example,dc=org" \
-w admin \
-H ldap://localhost:10389/ \
-f $PWD/examples/config-ldap.ldif

# Wait for slapd to exit.
wait $SLAPD_PID

0 comments on commit e40c01e

Please sign in to comment.