Merge pull request #1022 from ericchiang/ldap-example

*: add "getting started" example for LDAP
This commit is contained in:
rithu leena john 2017-08-22 10:46:55 -07:00 committed by GitHub
commit e40c01ec39
6 changed files with 231 additions and 2 deletions

View file

@ -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
@ -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

View file

@ -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

View file

@ -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.
@ -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
examples/config-ldap.ldif Normal file
View file

@ -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
examples/config-ldap.yaml Normal file
View file

@ -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
scripts/slapd.sh Executable file
View file

@ -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