Initial commit
This commit is contained in:
commit
70ffd9b09c
8 changed files with 374 additions and 0 deletions
3
.dockerignore
Normal file
3
.dockerignore
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
docker-compose.yml
|
||||||
|
.git/
|
||||||
|
data/
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
data/
|
27
Dockerfile
Normal file
27
Dockerfile
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
FROM debian:stretch
|
||||||
|
EXPOSE 389
|
||||||
|
|
||||||
|
ENV DEBIAN_FRONTEND noninteractive \
|
||||||
|
CONFDIR /etc/ldap/slapd.d \
|
||||||
|
DATADIR /var/lib/ldap
|
||||||
|
|
||||||
|
# add our users and groups first to ensure their IDs get assigned consitently
|
||||||
|
RUN groupadd -r -g 500 openldap && useradd -r -u 500 -g openldap openldap
|
||||||
|
|
||||||
|
|
||||||
|
RUN \
|
||||||
|
apt-get update && \
|
||||||
|
apt-get install --yes --no-install-recommends \
|
||||||
|
slapd \
|
||||||
|
ldap-utils \
|
||||||
|
ca-certificates && \
|
||||||
|
# remove the default config, since the entrypoint
|
||||||
|
# will populate it by hand.
|
||||||
|
rm -rf /etc/ldap/slapd.d && \
|
||||||
|
apt-get clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||||
|
|
||||||
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
COPY fixtures/ /usr/share/slapd/fixtures/
|
||||||
|
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
30
README.md
Normal file
30
README.md
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
## slapd
|
||||||
|
Slapd offers a LDAP server, which we mostly use for authentication of various
|
||||||
|
services.
|
||||||
|
Therefore, a lot of services have a direct (or indirect) dependency on this
|
||||||
|
image.
|
||||||
|
|
||||||
|
### Building slapd
|
||||||
|
|
||||||
|
```
|
||||||
|
docker build -t zombi/slapd .
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running slapd
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run -d --name ldap -v /data/ldap:/data -p 389:389 zombi/slapd
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backing up data
|
||||||
|
Data in this container is considered essential, since it influences almost
|
||||||
|
all other services we run.
|
||||||
|
|
||||||
|
We recently discovered that **simply copying all the data from `data` DOES
|
||||||
|
NOT WORK**, therefore we included scripts for backing up the slapd database
|
||||||
|
into a compact .ldif format.
|
||||||
|
|
||||||
|
running `tools/create-ldap-backup.sh` will create two files:
|
||||||
|
* `conf.ldif` is a backup of the configuration.
|
||||||
|
* `data.ldif` contains all the saved datasets.
|
||||||
|
|
15
docker-compose.yml
Normal file
15
docker-compose.yml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
version: '2'
|
||||||
|
|
||||||
|
services:
|
||||||
|
ldap:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "3810:389"
|
||||||
|
environment:
|
||||||
|
- "ROOTPW=pass"
|
||||||
|
- "ORGANIZATION=zombi"
|
||||||
|
- "DATADIR=/data"
|
||||||
|
- "CONFDIR=/conf"
|
||||||
|
volumes:
|
||||||
|
- ./data/ldap/config:/conf
|
||||||
|
- ./data/ldap/data:/data
|
93
entrypoint.sh
Executable file
93
entrypoint.sh
Executable file
|
@ -0,0 +1,93 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
# set default values for undefined vars
|
||||||
|
CONFDIR=${CONFDIR:-'/etc/ldap/slapd.d'}
|
||||||
|
DATADIR=${DATADIR:-'/var/lib/ldap'}
|
||||||
|
|
||||||
|
if [[ -z "$ORGANIZATION" && -z "$SUFFIX" ]] ; then
|
||||||
|
fail 'neither ORGANIZATION nor SUFFIX supplied as environment var'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$ORGANIZATION" ]] ; then
|
||||||
|
# if an organization was set, we can generate the RootDN from that
|
||||||
|
SUFFIX=${SUFFIX:-"o=${ORGANIZATION}"}
|
||||||
|
fi
|
||||||
|
|
||||||
|
function fail {
|
||||||
|
# write to stderr
|
||||||
|
echo "ERROR: $@" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function configure {
|
||||||
|
sed \
|
||||||
|
-e "s|@SUFFIX@|${SUFFIX}|g" \
|
||||||
|
-e "s|@PASSWORD@|${ROOTPW}|g" \
|
||||||
|
-e "s|@DATADIR@|${DATADIR}|g" \
|
||||||
|
/usr/share/slapd/fixtures/config.ldif \
|
||||||
|
| slapadd -F "$CONFDIR" -b "cn=config"
|
||||||
|
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
function init_fixtures {
|
||||||
|
mkdir -p /docker-entrypoint-initdb.d
|
||||||
|
# if no files exist in this directory then copy example structure
|
||||||
|
if ! ls /docker-entrypoint-initdb.d/* 1> /dev/null 2>&1 ; then
|
||||||
|
cp /usr/share/slapd/fixtures/example_structure.ldif /docker-entrypoint-initdb.d/structure.ldif
|
||||||
|
fi
|
||||||
|
|
||||||
|
for f in /docker-entrypoint-initdb.d/*; do
|
||||||
|
|
||||||
|
case "$f" in
|
||||||
|
*.sh)
|
||||||
|
echo "$0: running $f"; . "$f"
|
||||||
|
;;
|
||||||
|
*.ldif)
|
||||||
|
sed \
|
||||||
|
-e "s|@SUFFIX@|${SUFFIX}|g" \
|
||||||
|
-e "s|@PASSWORD@|${ROOTPW}|g" \
|
||||||
|
-e "s|@DATADIR@|${DATADIR}|g" \
|
||||||
|
-e "s|@ORGANIZATION@|${ORGANIZATION}|g" \
|
||||||
|
"$f" \
|
||||||
|
| slapadd -F "$CONFDIR" -b "$SUFFIX"
|
||||||
|
;;
|
||||||
|
*) echo "$0: ignoring $f" ;;
|
||||||
|
esac
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# Reduce maximum number of open file descriptors to 1024
|
||||||
|
# otherwise slapd consumes two orders of magnitude more of RAM
|
||||||
|
# see https://github.com/docker/docker/issues/8231
|
||||||
|
ulimit -n 1024 || fail "could not set ulimits"
|
||||||
|
|
||||||
|
# create dirs if they not already exists
|
||||||
|
[ -d $CONFDIR ] || mkdir -p $CONFDIR
|
||||||
|
[ -d $DATADIR ] || mkdir -p $DATADIR
|
||||||
|
|
||||||
|
if [[ ! -d "$CONFDIR/cn=config" ]] ; then
|
||||||
|
echo "configuration not found, creating one for $SUFFIX .."
|
||||||
|
[[ -z "$ROOTPW" ]] && fail "ROOTPW not set."
|
||||||
|
[[ -z "$SUFFIX" ]] && fail "SUFFIX not set."
|
||||||
|
|
||||||
|
# if rootpw is not already in hashed format, hash it first
|
||||||
|
[[ "${ROOTPW:0:1}" == '{' ]] \
|
||||||
|
||ROOTPW=`slappasswd -s "$ROOTPW"`
|
||||||
|
|
||||||
|
configure || fail "could not create slapd config"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "$DATADIR/data.mdb" ]] ; then
|
||||||
|
init_fixtures
|
||||||
|
fi
|
||||||
|
|
||||||
|
# fix file permissions
|
||||||
|
chown -R openldap:openldap $CONFDIR $DATADIR \
|
||||||
|
|| fail "could not change permissions"
|
||||||
|
|
||||||
|
echo "Starting slapd."
|
||||||
|
exec /usr/sbin/slapd -F $CONFDIR -u openldap -g openldap -h 'ldapi:// ldap://' -d stats
|
156
fixtures/config.ldif
Normal file
156
fixtures/config.ldif
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
# this file was adapted from the default /usr/share/slapd/slapd.init.ldif
|
||||||
|
# Global config:
|
||||||
|
dn: cn=config
|
||||||
|
objectClass: olcGlobal
|
||||||
|
cn: config
|
||||||
|
olcPidFile: /var/run/slapd/slapd.pid
|
||||||
|
# List of arguments that were passed to the server
|
||||||
|
olcArgsFile: /var/run/slapd/slapd.args
|
||||||
|
# Read slapd-config(5) for possible values
|
||||||
|
olcLogLevel: none
|
||||||
|
# The tool-threads parameter sets the actual amount of cpu's that is used
|
||||||
|
# for indexing.
|
||||||
|
olcToolThreads: 1
|
||||||
|
|
||||||
|
# Frontend settings
|
||||||
|
dn: olcDatabase={-1}frontend,cn=config
|
||||||
|
objectClass: olcDatabaseConfig
|
||||||
|
objectClass: olcFrontendConfig
|
||||||
|
olcDatabase: {-1}frontend
|
||||||
|
# The maximum number of entries that is returned for a search operation
|
||||||
|
olcSizeLimit: 500
|
||||||
|
# Allow unlimited access to local connection from the local root user
|
||||||
|
olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break
|
||||||
|
# Allow unauthenticated read access for schema and base DN autodiscovery
|
||||||
|
olcAccess: {1}to dn.exact="" by * read
|
||||||
|
olcAccess: {2}to dn.base="cn=Subschema" by * read
|
||||||
|
|
||||||
|
# Config db settings
|
||||||
|
dn: olcDatabase=config,cn=config
|
||||||
|
objectClass: olcDatabaseConfig
|
||||||
|
olcDatabase: config
|
||||||
|
# Allow unlimited access to local connection from the local root user
|
||||||
|
olcAccess: to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break
|
||||||
|
olcRootDN: cn=admin,cn=config
|
||||||
|
olcRootPW: @PASSWORD@
|
||||||
|
|
||||||
|
# Load schemas
|
||||||
|
dn: cn=schema,cn=config
|
||||||
|
objectClass: olcSchemaConfig
|
||||||
|
cn: schema
|
||||||
|
|
||||||
|
# base schemas
|
||||||
|
include: file:///etc/ldap/schema/core.ldif
|
||||||
|
include: file:///etc/ldap/schema/cosine.ldif
|
||||||
|
include: file:///etc/ldap/schema/nis.ldif
|
||||||
|
include: file:///etc/ldap/schema/inetorgperson.ldif
|
||||||
|
|
||||||
|
# additional schemas
|
||||||
|
# include: file:///etc/ldap/schema/ppolicy.ldif
|
||||||
|
#
|
||||||
|
# Load module
|
||||||
|
dn: cn=module{0},cn=config
|
||||||
|
objectClass: olcModuleList
|
||||||
|
cn: module{0}
|
||||||
|
# Where the dynamically loaded modules are stored
|
||||||
|
olcModulePath: /usr/lib/ldap
|
||||||
|
olcModuleLoad: back_mdb
|
||||||
|
|
||||||
|
# Load memberof module
|
||||||
|
dn: cn=module{1},cn=config
|
||||||
|
objectClass: olcModuleList
|
||||||
|
objectClass: top
|
||||||
|
cn: module{1}
|
||||||
|
olcModulePath: /usr/lib/ldap
|
||||||
|
olcModuleLoad: memberof.la
|
||||||
|
|
||||||
|
# Load refint module
|
||||||
|
dn: cn=module{2},cn=config
|
||||||
|
objectClass: olcModuleList
|
||||||
|
objectClass: top
|
||||||
|
cn: module{2}
|
||||||
|
olcModulePath: /usr/lib/ldap
|
||||||
|
olcModuleLoad: refint.la
|
||||||
|
|
||||||
|
# Set defaults for the backend
|
||||||
|
dn: olcBackend=mdb,cn=config
|
||||||
|
objectClass: olcBackendConfig
|
||||||
|
olcBackend: mdb
|
||||||
|
|
||||||
|
# The database definition.
|
||||||
|
dn: olcDatabase=mdb,cn=config
|
||||||
|
objectClass: olcDatabaseConfig
|
||||||
|
objectClass: olcMdbConfig
|
||||||
|
olcDatabase: mdb
|
||||||
|
# Checkpoint the database periodically in case of system
|
||||||
|
# failure and to speed slapd shutdown.
|
||||||
|
olcDbCheckpoint: 512 30
|
||||||
|
olcDbMaxSize: 1073741824
|
||||||
|
# Save the time that the entry gets modified, for database #1
|
||||||
|
olcLastMod: TRUE
|
||||||
|
# The base of your directory in database #1
|
||||||
|
olcSuffix: @SUFFIX@
|
||||||
|
# Where the database file are physically stored for database #1
|
||||||
|
olcDbDirectory: @DATADIR@
|
||||||
|
# olcRootDN directive for specifying a superuser on the database. This
|
||||||
|
# is needed for syncrepl.
|
||||||
|
olcRootDN: cn=admin,@SUFFIX@
|
||||||
|
olcRootPW: @PASSWORD@
|
||||||
|
# Indexing options for database #1
|
||||||
|
olcDbIndex: objectClass eq
|
||||||
|
olcDbIndex: cn,uid eq
|
||||||
|
olcDbIndex: uidNumber,gidNumber eq
|
||||||
|
olcDbIndex: member,memberUid eq
|
||||||
|
# additional attributes
|
||||||
|
olcDbIndex: mail,associatedDomain eq
|
||||||
|
olcDbIndex: memberOf eq
|
||||||
|
# The userPassword by default can be changed by the entry owning it if
|
||||||
|
# they are authenticated. Others should not be able to see it, except
|
||||||
|
# the admin entry above.
|
||||||
|
olcAccess: to attrs=userPassword
|
||||||
|
by self write
|
||||||
|
by anonymous auth
|
||||||
|
by * none
|
||||||
|
# Allow update of authenticated user's shadowLastChange attribute.
|
||||||
|
# Updating it on password change is implemented at least by libpam-ldap,
|
||||||
|
# libpam-ldapd, and the slapo-smbk5pwd overlay.
|
||||||
|
olcAccess: to attrs=shadowLastChange
|
||||||
|
by self write
|
||||||
|
by * read
|
||||||
|
# ou=People users can see ou=People node
|
||||||
|
olcAccess: to dn.exact="ou=People,@SUFFIX@"
|
||||||
|
by dn.subtree="ou=People,@SUFFIX@" read
|
||||||
|
by * break
|
||||||
|
# User can only access their own profile
|
||||||
|
# Services can read all User nodes
|
||||||
|
olcAccess: to dn.subtree="ou=People,@SUFFIX@"
|
||||||
|
by self read
|
||||||
|
by dn.subtree="ou=Services,ou=People,@SUFFIX@" read
|
||||||
|
by * none
|
||||||
|
# allow to read domain attributes for service accounts
|
||||||
|
olcAccess: to dn.subtree="ou=Domains,@SUFFIX@"
|
||||||
|
by dn.subtree="ou=Services,ou=People,@SUFFIX@" read
|
||||||
|
# The admin dn (olcRootDN) bypasses ACLs and so has total access,
|
||||||
|
# everyone logged in can read everything.
|
||||||
|
olcAccess: to *
|
||||||
|
by anonymous none
|
||||||
|
by * read
|
||||||
|
|
||||||
|
# memberof overlay manages the memberOf attribute based on referential
|
||||||
|
# groups
|
||||||
|
dn: olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config
|
||||||
|
objectClass: olcConfig
|
||||||
|
objectClass: olcMemberOf
|
||||||
|
objectClass: olcOverlayConfig
|
||||||
|
objectClass: top
|
||||||
|
olcOverlay: memberof
|
||||||
|
|
||||||
|
# refint overlay preserves referential integrety, by watching for renames of
|
||||||
|
# referenced fields
|
||||||
|
dn: olcOverlay={1}refint,olcDatabase={1}mdb,cn=config
|
||||||
|
objectClass: olcConfig
|
||||||
|
objectClass: olcOverlayConfig
|
||||||
|
objectClass: olcRefintConfig
|
||||||
|
objectClass: top
|
||||||
|
olcOverlay: {1}refint
|
||||||
|
olcRefintAttribute: memberof member manager owner
|
49
fixtures/example_structure.ldif
Normal file
49
fixtures/example_structure.ldif
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
# Create RootDN first:
|
||||||
|
dn: @SUFFIX@
|
||||||
|
objectClass: organization
|
||||||
|
objectClass: top
|
||||||
|
o: @ORGANIZATION@
|
||||||
|
|
||||||
|
dn: ou=People,@SUFFIX@
|
||||||
|
ou: people
|
||||||
|
objectClass: organizationalUnit
|
||||||
|
objectClass: top
|
||||||
|
description: People associated with @ORGANIZATION@
|
||||||
|
|
||||||
|
dn: ou=Services,ou=People,@SUFFIX@
|
||||||
|
ou: services
|
||||||
|
objectClass: organizationalUnit
|
||||||
|
objectClass: top
|
||||||
|
description: Accounts for services of @ORGANIZATION@
|
||||||
|
|
||||||
|
dn: ou=Groups,@SUFFIX@
|
||||||
|
ou: groups
|
||||||
|
objectClass: organizationalUnit
|
||||||
|
objectClass: top
|
||||||
|
description: User groups within @ORGANIZATION@
|
||||||
|
|
||||||
|
dn: ou=System,ou=Groups,@SUFFIX@
|
||||||
|
ou: system
|
||||||
|
objectClass: organizationalUnit
|
||||||
|
objectClass: top
|
||||||
|
description: Posix groups within @ORGANIZATION@
|
||||||
|
|
||||||
|
dn: cn=user,ou=System,ou=Groups,@SUFFIX@
|
||||||
|
cn: user
|
||||||
|
objectClass: posixGroup
|
||||||
|
objectClass: top
|
||||||
|
gidNumber: 30000
|
||||||
|
description: Default system user group
|
||||||
|
|
||||||
|
dn: ou=Domains,@SUFFIX@
|
||||||
|
ou: domains
|
||||||
|
objectClass: organizationalUnit
|
||||||
|
objectClass: top
|
||||||
|
description: Domains controlled by @ORGANIZATION@
|
||||||
|
|
||||||
|
dn: ou=Policies,@SUFFIX@
|
||||||
|
ou: policies
|
||||||
|
objectClass: organizationalUnit
|
||||||
|
objectClass: top
|
||||||
|
description: Password policies for @ORGANIZATION@
|
||||||
|
|
Loading…
Reference in a new issue