Merge pull request #1022 from ericchiang/ldap-example
*: add "getting started" example for LDAP
This commit is contained in:
commit
e40c01ec39
6 changed files with 231 additions and 2 deletions
|
@ -50,9 +50,16 @@ $ sudo ./storage/sql/standup.sh destroy postgres
|
||||||
|
|
||||||
## LDAP
|
## 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
|
$ 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).
|
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/
|
[okta-sign-up]: https://www.okta.com/developer/signup/
|
||||||
|
[openldap]: https://www.openldap.org/
|
||||||
|
[ldap-getting-started]: ldap-connector.md#getting-started
|
||||||
|
|
|
@ -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.
|
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.
|
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
|
[go-setup]: https://golang.org/doc/install
|
||||||
[example-config]: ../examples/config-dev.yaml
|
[example-config]: ../examples/config-dev.yaml
|
||||||
[oidc-discovery]: https://openid.net/specs/openid-connect-discovery-1_0-17.html#ProviderMetadata
|
[oidc-discovery]: https://openid.net/specs/openid-connect-discovery-1_0-17.html#ProviderMetadata
|
||||||
[using-dex]: using-dex.md
|
[using-dex]: using-dex.md
|
||||||
|
[ldap-getting-started]: ldap-connector.md#getting-started
|
||||||
|
|
|
@ -9,6 +9,30 @@ The connector executes two primary queries:
|
||||||
1. Finding the user based on the end user's credentials.
|
1. Finding the user based on the end user's credentials.
|
||||||
2. Searching for groups using the user entry.
|
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
|
## 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.
|
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.
|
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
42
examples/config-ldap.ldif
Normal 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
51
examples/config-ldap.yaml
Normal 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
98
scripts/slapd.sh
Executable 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
|
Reference in a new issue