[new-type] __openldap_server: first public version.
This already takes care of setting up the base DN and managing it as well as allowing for settings for the listener URLS. The type was also made a singleton as it doesn't make much sense to setup multiple LDAP servers on the same machine.
This commit is contained in:
parent
42914d26c5
commit
22c5cd550b
9 changed files with 176 additions and 50 deletions
44
cdist/conf/type/__openldap_server/gencode-remote
Normal file
44
cdist/conf/type/__openldap_server/gencode-remote
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
manager_dn=$(cat "${__object}/parameter/manager-dn")
|
||||||
|
manager_password=$(cat "${__object}/parameter/manager-password")
|
||||||
|
description=$(cat "${__object}/parameter/description")
|
||||||
|
suffix=$(cat "${__object}/parameter/suffix")
|
||||||
|
suffix_dc=$(echo -n ${suffix} | awk -F',' '{print $1}' | awk -F'=' '{print $2}')
|
||||||
|
|
||||||
|
SLAPD_IPC=$(cat "${__object}/parameter/slapd-url" | tr '\n' ' ' | awk '{ print $1}')
|
||||||
|
|
||||||
|
cat <<DONE # | tee /dev/stderr
|
||||||
|
# Restart service
|
||||||
|
service slapd restart
|
||||||
|
# It can sometimes take a tiny bit to bind
|
||||||
|
sleep 1
|
||||||
|
# Create or update base object
|
||||||
|
if ldapsearch -xZ -D "${manager_dn}" -w "${manager_password}" -H '${SLAPD_IPC}' -b '${suffix}' -s base 2>&1 > /dev/null; then
|
||||||
|
# Already exists, use ldapmodify
|
||||||
|
ldapmodify -xZ -D "${manager_dn}" -w "${manager_password}" -H '${SLAPD_IPC}' <<EOF
|
||||||
|
dn: ${suffix}
|
||||||
|
changetype: modify
|
||||||
|
replace: objectClass
|
||||||
|
objectClass: top
|
||||||
|
objectClass: dcObject
|
||||||
|
objectClass: organization
|
||||||
|
-
|
||||||
|
replace: o
|
||||||
|
o: ${description}
|
||||||
|
-
|
||||||
|
replace: dc
|
||||||
|
dc: ${suffix_dc}
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
# Does not exist, use ldapadd
|
||||||
|
ldapadd -xZ -D "${manager_dn}" -w "${manager_password}" -H '${SLAPD_IPC}' <<EOF
|
||||||
|
dn: ${suffix}
|
||||||
|
objectClass: top
|
||||||
|
objectClass: dcObject
|
||||||
|
objectClass: organization
|
||||||
|
o: ${description}
|
||||||
|
dc: ${suffix_dc}
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
DONE
|
|
@ -10,6 +10,9 @@ DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
This type can be used to bootstrap an LDAP environment using openldap as slapd.
|
This type can be used to bootstrap an LDAP environment using openldap as slapd.
|
||||||
|
|
||||||
|
It bootstraps the LDAP server with sane defaults and creates and manages the
|
||||||
|
base DN defined by `suffix`.
|
||||||
|
|
||||||
|
|
||||||
REQUIRED PARAMETERS
|
REQUIRED PARAMETERS
|
||||||
-------------------
|
-------------------
|
||||||
|
@ -17,14 +20,19 @@ manager-dn
|
||||||
The rootdn to set up in the directory.
|
The rootdn to set up in the directory.
|
||||||
E.g. `cn=manager,dc=ungleich,dc=ch`. See `slapd.conf(5)`.
|
E.g. `cn=manager,dc=ungleich,dc=ch`. See `slapd.conf(5)`.
|
||||||
|
|
||||||
|
manager-password
|
||||||
|
The password for `manager-dn` in the directory.
|
||||||
|
This will be used to connect to the LDAP server on the first `slapd-url`
|
||||||
|
with the given `manager-dn`.
|
||||||
|
|
||||||
manager-password-hash
|
manager-password-hash
|
||||||
The password for `manager-dn` in the directory.
|
The password for `manager-dn` in the directory.
|
||||||
This should be valid for `slapd.conf` like `{SSHA}qV+mCs3u8Q2sCmUXT4Ybw7MebHTASMyr`.
|
This should be valid for `slapd.conf` like `{SSHA}qV+mCs3u8Q2sCmUXT4Ybw7MebHTASMyr`.
|
||||||
Generate e.g. with: `slappasswd -s weneedgoodsecurity`.
|
Generate e.g. with: `slappasswd -s weneedgoodsecurity`.
|
||||||
See `slappasswd(8C)`, `slapd.conf(5)`.
|
See `slappasswd(8C)`, `slapd.conf(5)`.
|
||||||
TODO: implement this: http://blog.adamsbros.org/2015/06/09/openldap-ssha-salted-hashes-by-hand/
|
TODO: implement this: http://blog.adamsbros.org/2015/06/09/openldap-ssha-salted-hashes-by-hand/
|
||||||
to allow for a manager-password parameter and ensure idempotency (care with salts).
|
to derive from the manager-password parameter and ensure idempotency (care with salts).
|
||||||
Such manager-password parameter should be mutually exclusive with this one.
|
At that point, manager-password-hash should be deprecated and ignored.
|
||||||
|
|
||||||
serverid
|
serverid
|
||||||
The server for the directory.
|
The server for the directory.
|
||||||
|
@ -35,6 +43,17 @@ suffix
|
||||||
E.g. `dc=ungleich,dc=ch`. See `slapd.conf(5)`.
|
E.g. `dc=ungleich,dc=ch`. See `slapd.conf(5)`.
|
||||||
|
|
||||||
|
|
||||||
|
REQUIRED MULTIPLE PARAMETERS
|
||||||
|
----------------------------
|
||||||
|
slapd-url
|
||||||
|
A URL for slapd to listen on.
|
||||||
|
Pass once for each URL you want to support,
|
||||||
|
e.g.: `--slapd-url ldaps://my.fqdn/ --slapd-url ldap://my.fqdn/`.
|
||||||
|
The first instance that is passed will be used as the main URL to
|
||||||
|
connect to this LDAP server
|
||||||
|
See the `-h` flag in `slapd(8C)`.
|
||||||
|
|
||||||
|
|
||||||
OPTIONAL PARAMETERS
|
OPTIONAL PARAMETERS
|
||||||
-------------------
|
-------------------
|
||||||
syncrepl-credentials
|
syncrepl-credentials
|
||||||
|
@ -53,6 +72,11 @@ admin-email
|
||||||
Required if using `__letsencrypt_cert`.
|
Required if using `__letsencrypt_cert`.
|
||||||
Where to send Let's Encrypt emails like "certificate needs renewal".
|
Where to send Let's Encrypt emails like "certificate needs renewal".
|
||||||
|
|
||||||
|
tls-cipher-suite
|
||||||
|
Setting for TLSCipherSuite.
|
||||||
|
Defaults to `NORMAL` in a Debian-like OS and `HIGH:MEDIUM:+SSLv2` on FreeBSD.
|
||||||
|
See `slapd.conf(5)`.
|
||||||
|
|
||||||
tls-cert
|
tls-cert
|
||||||
If defined, `__letsencrypt_cert` is not used and this must be the path in
|
If defined, `__letsencrypt_cert` is not used and this must be the path in
|
||||||
the remote hosts to the PEM-encoded TLS certificate.
|
the remote hosts to the PEM-encoded TLS certificate.
|
||||||
|
@ -87,6 +111,11 @@ schema
|
||||||
The type user must ensure that the schema file is deployed.
|
The type user must ensure that the schema file is deployed.
|
||||||
This defaults to a sensible subset, for details see the type definition.
|
This defaults to a sensible subset, for details see the type definition.
|
||||||
|
|
||||||
|
description
|
||||||
|
The description of the base DN passed in the `suffix` parameter.
|
||||||
|
Defaults to `Managed by cdist, do not edit manually.`
|
||||||
|
|
||||||
|
|
||||||
BOOLEAN PARAMETERS
|
BOOLEAN PARAMETERS
|
||||||
------------------
|
------------------
|
||||||
staging
|
staging
|
||||||
|
@ -97,48 +126,71 @@ replicate
|
||||||
Whether to setup replication or not.
|
Whether to setup replication or not.
|
||||||
If present `syncrepl-credentials` and `syncrepl-host` are also required.
|
If present `syncrepl-credentials` and `syncrepl-host` are also required.
|
||||||
|
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
|
||||||
.. code-block:: sh
|
.. code-block:: sh
|
||||||
|
|
||||||
# Modify the ruleset on $__target_host:
|
# Example of a simple server with manual certificate management.
|
||||||
__pf_ruleset --state present --source /my/pf/ruleset.conf
|
pki_prefix="/usr/local/etc/pki/realms/ldap.camilion.cloud" \
|
||||||
require="__pf_ruleset" \
|
__openldap_server \
|
||||||
__pf_apply
|
--manager-dn 'cn=manager,dc=camilion,dc=cloud' \
|
||||||
|
--manager-password "foo" \
|
||||||
|
--manager-password-hash '{SSHA}foo' \
|
||||||
|
--serverid 0 \
|
||||||
|
--suffix 'dc=camilion,dc=cloud' \
|
||||||
|
--slapd-url 'ldaps://ldap.camilion.cloud' \
|
||||||
|
--tls-cert '${pki_prefix}/default.crt' \
|
||||||
|
--tls-privkey '${pki_prefix}/default.key' \
|
||||||
|
--tls-ca '${pki_prefix}/CA.crt'
|
||||||
|
|
||||||
# Remove the ruleset on $__target_host (implies disabling pf(4):
|
# The created basedn looks as follows:
|
||||||
__pf_ruleset --state absent
|
|
||||||
require="__pf_ruleset" \
|
|
||||||
__pf_apply
|
|
||||||
|
|
||||||
root@ldap-for-guacamole:~# cat ldapbase.ldif
|
|
||||||
dn: dc=guaca-test,dc=ungleich,dc=ch
|
|
||||||
objectClass: top
|
|
||||||
objectClass: dcObject
|
|
||||||
objectClass: organization
|
|
||||||
o: Some description
|
|
||||||
dc: guaca-test
|
|
||||||
|
|
||||||
|
|
||||||
# Sample usage:
|
|
||||||
#
|
#
|
||||||
# id=1
|
# dn: dc=camilion,dc=cloud
|
||||||
# for host in ldap-test1.ungleich.ch ldap-test2.ungleich.ch; do
|
# objectClass: top
|
||||||
# echo "__ungleich_ldap ${host} \
|
# objectClass: dcObject
|
||||||
# --manager-dn 'cn=manager,dc=ungleich,dc=ch' \
|
# objectClass: organization
|
||||||
# --manager-password '{SSHA}fooo' \
|
# o: Managed by cdist, do not edit manually.
|
||||||
# --serverid '${id}' \
|
# dc: camilion
|
||||||
# --staging \
|
#
|
||||||
# --suffix 'dc=ungleich,dc=ch' \
|
# Do not change it manually, the type will overwrite your changes.
|
||||||
# --searchbase 'dc=ungleich,dc=ch' \
|
|
||||||
# --syncrepl-credentials 'fooo' \
|
|
||||||
# --syncrepl-host 'ldap-test1.ungleich.ch' \
|
#
|
||||||
# --syncrepl-host 'ldap-test2.ungleich.ch' \
|
# Changing to a replicated setup is a simple change to something like:
|
||||||
# --descriptiont 'Ungleich LDAP server'" \
|
#
|
||||||
# | cdist config -i - -v ${host}
|
# Example for multiple servers with replication and automatic
|
||||||
# id=$((id + 1))
|
# Let's Encrypt certificate management through certbot.
|
||||||
# done
|
id=1
|
||||||
|
for host in ldap-test1.ungleich.ch ldap-test2.ungleich.ch; do
|
||||||
|
echo "__ungleich_ldap \
|
||||||
|
--manager-dn 'cn=manager,dc=ungleich,dc=ch' \
|
||||||
|
--manager-psasword 'foo' \
|
||||||
|
--manager-password-hash '{SSHA}fooo' \
|
||||||
|
--serverid '${id}' \
|
||||||
|
--suffix 'dc=ungleich,dc=ch' \
|
||||||
|
--slapd-url ldap://${host} \
|
||||||
|
--searchbase 'dc=ungleich,dc=ch' \
|
||||||
|
--syncrepl-credentials 'fooo' \
|
||||||
|
--syncrepl-host 'ldap-test1.ungleich.ch' \
|
||||||
|
--syncrepl-host 'ldap-test2.ungleich.ch' \
|
||||||
|
--description 'Ungleich LDAP server'" \
|
||||||
|
--staging \
|
||||||
|
| cdist config -i - -v ${host}
|
||||||
|
id=$((id + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
# The created basedn looks as follows:
|
||||||
|
#
|
||||||
|
# dn: dc=ungleich,dc=ch
|
||||||
|
# objectClass: top
|
||||||
|
# objectClass: dcObject
|
||||||
|
# objectClass: organization
|
||||||
|
# o: Ungleich LDAP server
|
||||||
|
# dc: ungleich
|
||||||
|
#
|
||||||
|
# Do not change it manually, the type will overwrite your changes.
|
||||||
|
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
|
|
|
@ -5,13 +5,17 @@ manager_dn=$(cat "${__object}/parameter/manager-dn")
|
||||||
manager_password_hash=$(cat "${__object}/parameter/manager-password-hash")
|
manager_password_hash=$(cat "${__object}/parameter/manager-password-hash")
|
||||||
serverid=$(cat "${__object}/parameter/serverid")
|
serverid=$(cat "${__object}/parameter/serverid")
|
||||||
suffix=$(cat "${__object}/parameter/suffix")
|
suffix=$(cat "${__object}/parameter/suffix")
|
||||||
slapd_modules=$(cat "${__object}/parameter/module" || true)
|
slapd_modules=$(cat "${__object}/parameter/module" 2>/dev/null || true)
|
||||||
schemas=$(cat "${__object}/parameter/schema")
|
schemas=$(cat "${__object}/parameter/schema")
|
||||||
|
slapd_urls=$(cat "${__object}/parameter/slapd-url" | tr '\n' ' ')
|
||||||
|
tls_cipher_suite=$(cat "${__object}/parameter/tls-cipher-suite" 2>/dev/null || true)
|
||||||
|
|
||||||
|
|
||||||
os="$(cat "${__global}/explorer/os")"
|
os="$(cat "${__global}/explorer/os")"
|
||||||
|
|
||||||
# Setup OS-dependent vars
|
# Setup OS-dependent vars
|
||||||
|
CONF_OWNER="root"
|
||||||
|
CONF_GROUP="root"
|
||||||
case "${os}" in
|
case "${os}" in
|
||||||
freebsd)
|
freebsd)
|
||||||
PKGS="openldap-server"
|
PKGS="openldap-server"
|
||||||
|
@ -24,6 +28,12 @@ case "${os}" in
|
||||||
# It looks like ppolicy and syncprov must be compiled
|
# It looks like ppolicy and syncprov must be compiled
|
||||||
slapd_modules="back_mdb back_monitor"
|
slapd_modules="back_mdb back_monitor"
|
||||||
fi
|
fi
|
||||||
|
CONF_OWNER="ldap"
|
||||||
|
CONF_GROUP="ldap"
|
||||||
|
if [ -z "${tls_cipher_suite}" ]; then
|
||||||
|
# TODO: research default for FreeBSD. 'NORMAL' appears to not work
|
||||||
|
tls_cipher_suite="HIGH:MEDIUM:+SSLv2"
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
debian|ubuntu|devuan)
|
debian|ubuntu|devuan)
|
||||||
PKGS="slapd ldap-utils"
|
PKGS="slapd ldap-utils"
|
||||||
|
@ -35,6 +45,9 @@ case "${os}" in
|
||||||
if [ -z "${slapd_modules}" ]; then
|
if [ -z "${slapd_modules}" ]; then
|
||||||
slapd_modules="back_mdb ppolicy syncprov back_monitor"
|
slapd_modules="back_mdb ppolicy syncprov back_monitor"
|
||||||
fi
|
fi
|
||||||
|
if [ -z "${tls_cipher_suite}" ]; then
|
||||||
|
tls_cipher_suite="NORMAL"
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Don't know the openldap defaults for: $os" >&2
|
echo "Don't know the openldap defaults for: $os" >&2
|
||||||
|
@ -42,6 +55,8 @@ case "${os}" in
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
PKG_MAIN=$(echo ${PKGS} | awk '{print $1;}')
|
||||||
|
|
||||||
|
|
||||||
# Determine if __letsencrypt_cert is to be used and setup vars accordingly
|
# Determine if __letsencrypt_cert is to be used and setup vars accordingly
|
||||||
if [ -f "${__object}/parameter/tls-cert" ]; then
|
if [ -f "${__object}/parameter/tls-cert" ]; then
|
||||||
|
@ -106,17 +121,26 @@ for pkg in ${PKGS}; do
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
# TODO: Implement __start_on_boot for BSD
|
require="__package/${PKG_MAIN}" __start_on_boot slapd
|
||||||
require="__package/slapd" __start_on_boot slapd
|
|
||||||
|
|
||||||
|
# Setup -h flag for the listeners. See man slapd (-h flag).
|
||||||
case "${os}" in
|
case "${os}" in
|
||||||
|
freebsd)
|
||||||
|
require="__package/${PKG_MAIN}" __key_value \
|
||||||
|
--file "/etc/rc.conf" \
|
||||||
|
--key "slapd_flags" \
|
||||||
|
--value "\"-h '${slapd_urls}'\"" \
|
||||||
|
--delimiter "=" \
|
||||||
|
--comment "# LDAP Listener URLs" \
|
||||||
|
"${__target_host}__slapd_flags"
|
||||||
|
;;
|
||||||
debian|ubuntu|devuan)
|
debian|ubuntu|devuan)
|
||||||
require="__package/slapd" __line rm_slapd_conf \
|
require="__package/${PKG_MAIN}" __line rm_slapd_conf \
|
||||||
--file ${ETC}/default/slapd \
|
--file ${ETC}/default/slapd \
|
||||||
--regex 'SLAPD_CONF=.*' \
|
--regex 'SLAPD_CONF=.*' \
|
||||||
--state absent
|
--state absent
|
||||||
|
|
||||||
require="__package/slapd" __line rm_slapd_services \
|
require="__package/${PKG_MAIN}" __line rm_slapd_services \
|
||||||
--file ${ETC}/default/slapd \
|
--file ${ETC}/default/slapd \
|
||||||
--regex 'SLAPD_SERVICES=.*' \
|
--regex 'SLAPD_SERVICES=.*' \
|
||||||
--state absent
|
--state absent
|
||||||
|
@ -128,7 +152,7 @@ case "${os}" in
|
||||||
|
|
||||||
require="__line/rm_slapd_services" __line add_slapd_services \
|
require="__line/rm_slapd_services" __line add_slapd_services \
|
||||||
--file ${ETC}/default/slapd \
|
--file ${ETC}/default/slapd \
|
||||||
--line "SLAPD_SERVICES=\"ldap://localhost/ ldap://${name}/\"" \
|
--line "SLAPD_SERVICES=\"${slapd_urls}\"" \
|
||||||
--state present
|
--state present
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
@ -149,15 +173,15 @@ if [ -z "${_skip_letsencrypt_cert}" ]; then
|
||||||
--automatic-renewal ${staging}
|
--automatic-renewal ${staging}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
require="__package/slapd" __directory ${SLAPD_DIR}/slapd.d --state absent
|
require="__package/${PKG_MAIN}" __directory ${SLAPD_DIR}/slapd.d --state absent
|
||||||
|
|
||||||
if [ -z "${_skip_letsencrypt_cert}" ]; then
|
if [ -z "${_skip_letsencrypt_cert}" ]; then
|
||||||
require="__package/slapd __letsencrypt_cert/${name}" \
|
require="__package/${PKG_MAIN} __letsencrypt_cert/${name}" \
|
||||||
__file ${SLAPD_DIR}/slapd.conf --owner root --group root --mode 644 \
|
__file ${SLAPD_DIR}/slapd.conf --owner ${CONF_OWNER} --group ${CONF_GROUP} --mode 644 \
|
||||||
--source "${ldapconf}"
|
--source "${ldapconf}"
|
||||||
else
|
else
|
||||||
require="__package/slapd" \
|
require="__package/${PKG_MAIN}" \
|
||||||
__file ${SLAPD_DIR}/slapd.conf --owner root --group root --mode 644 \
|
__file ${SLAPD_DIR}/slapd.conf --owner ${CONF_OWNER} --group ${CONF_GROUP} --mode 644 \
|
||||||
--source "${ldapconf}"
|
--source "${ldapconf}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -166,7 +190,7 @@ cat << EOF > "${ldapconf}"
|
||||||
pidfile ${SLAPD_RUN_DIR}/slapd.pid
|
pidfile ${SLAPD_RUN_DIR}/slapd.pid
|
||||||
argsfile ${SLAPD_RUN_DIR}/slapd.args
|
argsfile ${SLAPD_RUN_DIR}/slapd.args
|
||||||
|
|
||||||
TLSCipherSuite NORMAL
|
TLSCipherSuite ${tls_cipher_suite}
|
||||||
TLSCertificateFile ${tls_cert}
|
TLSCertificateFile ${tls_cert}
|
||||||
TLSCertificateKeyFile ${tls_privkey}
|
TLSCertificateKeyFile ${tls_privkey}
|
||||||
TLSCACertificateFile ${tls_ca}
|
TLSCACertificateFile ${tls_ca}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Managed by cdist, do not edit manually.
|
|
@ -1,6 +1,8 @@
|
||||||
|
description
|
||||||
syncrepl-credentials
|
syncrepl-credentials
|
||||||
syncrepl-searchbase
|
syncrepl-searchbase
|
||||||
admin-email
|
admin-email
|
||||||
|
tls-cipher-suite
|
||||||
tls-cert
|
tls-cert
|
||||||
tls-privkey
|
tls-privkey
|
||||||
tls-ca
|
tls-ca
|
|
@ -1,2 +1,3 @@
|
||||||
syncrepl-host
|
syncrepl-host
|
||||||
module
|
module
|
||||||
|
schema
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
manager-dn
|
manager-dn
|
||||||
|
manager-password
|
||||||
manager-password-hash
|
manager-password-hash
|
||||||
serverid
|
serverid
|
||||||
suffix
|
suffix
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
slapd-url
|
0
cdist/conf/type/__openldap_server/singleton
Normal file
0
cdist/conf/type/__openldap_server/singleton
Normal file
Loading…
Reference in a new issue