diff --git a/comanage-registry-slapd/Dockerfile b/comanage-registry-slapd/Dockerfile new file mode 100644 index 0000000..d57bf81 --- /dev/null +++ b/comanage-registry-slapd/Dockerfile @@ -0,0 +1,48 @@ +# slapd Dockerfile template for use with COmanage Registry +# +# Portions licensed to the University Corporation for Advanced Internet +# Development, Inc. ("UCAID") under one or more contributor license agreements. +# See the NOTICE file distributed with this work for additional information +# regarding copyright ownership. +# +# UCAID licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +FROM debian:jessie + +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \ + ldap-utils \ + slapd \ + && cp -a /var/lib/ldap /var/lib/ldap.dist \ + && cp -a /etc/ldap/slapd.d /etc/ldap/slapd.d.dist \ + && apt-get clean + +ARG OLC_SUFFIX +ARG OLC_ROOT_DN +ARG OLC_ROOT_PW + +ENV OLC_SUFFIX ${OLC_SUFFIX:-dc=my,dc=org} +ENV OLC_ROOT_DN ${OLC_ROOT_DN:-cn=admin,dc=my,dc=org} +ENV OLC_ROOT_PW ${OLC_ROOT_PW:-password} + +COPY eduperson.ldif /etc/ldap/schema/ +COPY openssh-lpk.ldif /etc/ldap/schema/ + +VOLUME [ "/var/lib/ldap", "/etc/ldap/slapd.d" ] + +COPY docker-slapd-entrypoint /usr/local/bin/ + +ENTRYPOINT ["docker-slapd-entrypoint"] + +EXPOSE 389 + +CMD ["slapd", "-d", "32768", "-h", "ldapi:/// ldap://127.0.0.1", "-u", "openldap", "-g", "openldap"] diff --git a/comanage-registry-slapd/README.md b/comanage-registry-slapd/README.md new file mode 100644 index 0000000..3682301 --- /dev/null +++ b/comanage-registry-slapd/README.md @@ -0,0 +1,72 @@ + + +# OpenLDAP slapd for COmanage Registry + +A simple example demonstrating how to create an image and container +based on OpenLDAP slapd to use with COmanage Registry containers. + +## Build + +``` +docker build -t comanage-registry-slapd . +``` + +## Run + +Create a user-defined network bridge with + +``` +docker network create --driver=bridge \ + --subnet=192.168.0.0/16 \ + --gateway=192.168.0.100 \ + comanage-registry-internal-network +``` + +and then mount a directory such as `/tmp/slapd-data` +to `/var/lib/ldap` inside the container to persist +data and `/tmp/slapd-config` to `/etc/ldap/slapd.d` +inside the container to persist the configuration, eg. + +``` +docker run -d --name comanage-registry-slapd \ + -v /tmp/slapd-data:/var/lib/ldap \ + -v /tmp/slapd-config:/etc/ldap/slapd.d \ + --network comanage-registry-internal-network \ + -p 389:389 \ + sphericalcowgroup/comanage-registry-slapd + +``` + +To support TLS mount or copy in an X.509 certificate, private key, +and CA signing certificate or chain file like this: + +``` +docker run -d --name comanage-registry-slapd \ + -v /tmp/slapd-data:/var/lib/ldap \ + -v /tmp/slapd-config:/etc/ldap/slapd.d \ + -v my.crt:/etc/ldap/slapd.crt \ + -v my.key:/etc/ldap/slapd.key \ + -v chain.pem:/etc/ldap/slapd.ca.crt \ + --network comanage-registry-internal-network \ + -p 389:389 -p 636:636 \ + sphericalcowgroup/comanage-registry-slapd +``` diff --git a/comanage-registry-slapd/docker-slapd-entrypoint b/comanage-registry-slapd/docker-slapd-entrypoint new file mode 100755 index 0000000..6842275 --- /dev/null +++ b/comanage-registry-slapd/docker-slapd-entrypoint @@ -0,0 +1,191 @@ +#!/bin/bash + +# slapd for COmanage Registry Dockerfile entrypoint +# +# Portions licensed to the University Corporation for Advanced Internet +# Development, Inc. ("UCAID") under one or more contributor license agreements. +# See the NOTICE file distributed with this work for additional information +# regarding copyright ownership. +# +# UCAID licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +# Only bootstrap the directory if it does not already exist. +if [[ ! -f /var/lib/ldap/data.mdb && ! -f /etc/ldap/slapd.d/cn=config.ldif ]]; then + # Parse the domain, rdn, and the value of rdn from the OLC_SUFFIX + DOMAIN=`echo ${OLC_SUFFIX} | sed -e 's/dc=//g' -e 's/,/./g'` + RDN=`echo ${OLC_SUFFIX} | sed -E -e 's/^([^=]+)=[^=,]+.*/\1/'` + RDN_VALUE=`echo ${OLC_SUFFIX} | sed -E -e 's/^[^=]+=([^=,]+).*/\1/'` + + # Parse the rdn and its value from the OLC_ROOT_DN + ADMIN_RDN=`echo ${OLC_ROOT_DN} | sed -E -e 's/^([^=]+)=[^=,]+.*/\1/'` + ADMIN_RDN_VALUE=`echo ${OLC_ROOT_DN} | sed -E -e 's/^[^=]+=([^=,]+).*/\1/'` + + # Create a temporary password and its hash that will be used to + # bootstrap the OLC_SUFFIX. It is later replaced by the OLC_ROOT_PW hash. + OLC_ROOT_PW_TMP=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1` + OLC_ROOT_PW_TMP_HASH=`/usr/sbin/slappasswd -s ${OLC_ROOT_PW_TMP}` + + # Copy over the distribution files created by Debian installation of slapd + # so that we can start slapd. + mkdir -p /var/lib/ldap + cp -a /var/lib/ldap.dist/* /var/lib/ldap/ + chown -R openldap:openldap /var/lib/ldap + + mkdir -p /etc/ldap/slapd.d + cp -a /etc/ldap/slapd.d.dist/* /etc/ldap/slapd.d/ + chown -R openldap:openldap /etc/ldap/slapd.d + + # Start slapd listening only on socket. + slapd -h ldapi:/// -u openldap -g openldap > /dev/null 2>&1 + + # Reconfigure slapd to look in /var/lib/ldap.dist for the default + # directory created by the Debian slapd installation. + cat < /tmp/modify.ldif +dn: olcDatabase={1}mdb,cn=config +changetype: modify +replace: olcDbDirectory +olcDbDirectory: /var/lib/ldap.dist +EOF + + ldapmodify -Y EXTERNAL -H ldapi:/// -f /tmp/modify.ldif > /dev/null 2>&1 + + rm -f /tmp/modify.ldif > /dev/null 2>&1 + + # Kill slapd and remove the directory created by the Debian installation + # that was copied over and used to allow slapd to start initially. + killall slapd + + rm -f /var/lib/ldap/* + + # Start slapd again listening only on socket. + slapd -h ldapi:/// -u openldap -g openldap > /dev/null 2>&1 + + # Configure the directory with the injected suffix but the temporary password. + cat < /tmp/modify.ldif +dn: olcDatabase={2}mdb,cn=config +objectClass: olcDatabaseConfig +objectClass: olcMdbConfig +olcDatabase: {2}mdb +olcDbDirectory: /var/lib/ldap +olcSuffix: ${OLC_SUFFIX} +olcLastMod: TRUE +olcRootDN: ${OLC_ROOT_DN} +olcRootPW: ${OLC_ROOT_PW_TMP_HASH} +olcAccess: {0}to dn.base="${OLC_ROOT_DN}" by sockname.regex=/var/run/slapd/ldapi auth by users none by * none +olcAccess: {1}to attrs=userPassword,shadowLastChange by self auth by anonymous auth by * none +olcAccess: {2}to * by * none +olcDbCheckpoint: 512 30 +olcDbIndex: objectClass eq,pres +olcDbIndex: ou,cn,mail,surname,givenname eq,pres,sub +olcDbMaxSize: 1073741824 +EOF + + ldapmodify -Y EXTERNAL -H ldapi:/// -a -f /tmp/modify.ldif > /dev/null 2>&1 + + rm -f /tmp/modify.ldif > /dev/null 2>&1 + + # Configure slapd to use a better password hash. + cat < /tmp/modify.ldif +dn: cn=config +changetype: modify +add: olcPasswordCryptSaltFormat +olcPasswordCryptSaltFormat: \$6\$rounds=5000$%.86s +- +add: olcPasswordHash +olcPasswordHash: {CRYPT} +EOF + + ldapmodify -Y EXTERNAL -H ldapi:/// -f /tmp/modify.ldif > /dev/null 2>&1 + + rm -f /tmp/modify.ldif > /dev/null 2>&1 + + # Create the actual contents of the directory and the admin DN + # with the injected password hash. + cat < /tmp/modify.ldif +dn: ${OLC_SUFFIX} +objectClass: dcObject +objectClass: organization +o: ${DOMAIN} +${RDN}: ${RDN_VALUE} + +dn: ${OLC_ROOT_DN} +objectClass: simpleSecurityObject +objectClass: organizationalRole +${ADMIN_RDN}: ${ADMIN_RDN_VALUE} +description: LDAP administrator +userPassword: ${OLC_ROOT_PW} +EOF + + ldapmodify -x -D ${OLC_ROOT_DN} -w ${OLC_ROOT_PW_TMP} -H ldapi:/// -a -f /tmp/modify.ldif > /dev/null 2>&1 + + rm -f /tmp/modify.ldif > /dev/null 2>&1 + + # Remove the temporary root password from the directory configuration. + cat < /tmp/modify.ldif +dn: olcDatabase={2}mdb,cn=config +changetype: modify +delete: olcRootPW +EOF + + ldapmodify -Y EXTERNAL -H ldapi:/// -f /tmp/modify.ldif > /dev/null 2>&1 + + rm -f /tmp/modify.ldif > /dev/null 2>&1 + + # Configure TLS if cert and key available. + if [[ -f /etc/ldap/slapd.crt && -f /etc/ldap/slapd.key ]]; then + cat < /tmp/modify.ldif +dn: cn=config +changetype: modify +add: olcTLSCertificateFile +olcTLSCertificateFile: /etc/ldap/slapd.crt +- +add: olcTLSCertificateKeyFile +olcTLSCertificateKeyFile: /etc/ldap/slapd.key +- +add: olcTLSCipherSuite +olcTLSCipherSuite: SECURE256 +- +add: olcTLSProtocolMin +olcTLSProtocolMin: 3.2 +EOF + if [[ -f /etc/ldap/slapd.ca.crt ]]; then + cat <> /tmp/modify.ldif +- +add: olcTLSCACertificateFile +olcTLSCACertificateFile: /etc/ldap/slapd.ca.crt +EOF + fi + + ldapmodify -Y EXTERNAL -H ldapi:/// -f /tmp/modify.ldif > /dev/null 2>&1 + + rm -f /tmp/modify.ldif > /dev/null 2>&1 + + + fi # Done configuring TLS if cert and key available. + + # Add eduPerson, eduMember, and openssh-lpk schemas. + ldapmodify -Y EXTERNAL -H ldapi:/// -a -f /etc/ldap/schema/eduperson.ldif 2>&1 + ldapmodify -Y EXTERNAL -H ldapi:/// -a -f /etc/ldap/schema/openssh-lpk.ldif 2>&1 + + # Stop slapd. + killall slapd + + # Fix permissions. + chown -R openldap:openldap /var/lib/ldap + chown -R openldap:openldap /etc/ldap/slapd.d + +fi + +exec "$@" diff --git a/comanage-registry-slapd/eduperson.ldif b/comanage-registry-slapd/eduperson.ldif new file mode 100644 index 0000000..0ea6926 --- /dev/null +++ b/comanage-registry-slapd/eduperson.ldif @@ -0,0 +1,64 @@ +dn: cn=eduperson,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: eduperson +olcAttributeTypes: {0}( 1.3.6.1.4.1.5923.1.1.1.1 NAME 'eduPersonAffiliation' D + ESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SUBSTR ca + seIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: {1}( 1.3.6.1.4.1.5923.1.1.1.2 NAME 'eduPersonNickname' DESC + 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SUBSTR caseI + gnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: {2}( 1.3.6.1.4.1.5923.1.1.1.3 NAME 'eduPersonOrgDN' DESC 'e + duPerson per Internet2 and EDUCAUSE' EQUALITY distinguishedNameMatch SYNTAX 1 + .3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE ) +olcAttributeTypes: {3}( 1.3.6.1.4.1.5923.1.1.1.4 NAME 'eduPersonOrgUnitDN' DES + C 'eduPerson per Internet2 and EDUCAUSE' EQUALITY distinguishedNameMatch SYNT + AX 1.3.6.1.4.1.1466.115.121.1.12 ) +olcAttributeTypes: {4}( 1.3.6.1.4.1.5923.1.1.1.5 NAME 'eduPersonPrimaryAffilia + tion' DESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SU + BSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VA + LUE ) +olcAttributeTypes: {5}( 1.3.6.1.4.1.5923.1.1.1.6 NAME 'eduPersonPrincipalName' + DESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SUBSTR + caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE ) +olcAttributeTypes: {6}( 1.3.6.1.4.1.5923.1.1.1.7 NAME 'eduPersonEntitlement' D + ESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseExactMatch SYNTAX 1.3 + .6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: {7}( 1.3.6.1.4.1.5923.1.1.1.8 NAME 'eduPersonPrimaryOrgUnit + DN' DESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY distinguishedNameMat + ch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE ) +olcAttributeTypes: {8}( 1.3.6.1.4.1.5923.1.1.1.9 NAME 'eduPersonScopedAffiliat + ion' DESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SYN + TAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: {9}( 1.3.6.1.4.1.5923.1.1.1.10 NAME 'eduPersonTargetedID' D + ESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SYNTAX 1. + 3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: {10}( 1.3.6.1.4.1.5923.1.1.1.11 NAME 'eduPersonAssurance' + DESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: {11}( 1.3.6.1.4.1.5923.1.1.1.12 NAME 'eduPersonPrincipalNam + ePrior' DESC 'eduPersonPrincipalNamePrior per Internet2' EQUALITY caseIgnoreM + atch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: {12}( 1.3.6.1.4.1.5923.1.1.1.13 NAME 'eduPersonUniqueId' DE + SC 'eduPersonUniqueId per Internet2' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1. + 4.1.1466.115.121.1.15 ) +olcAttributeTypes: {13}( 1.3.6.1.4.1.5923.1.1.1.16 NAME 'eduPersonOrcid' DE + SC 'ORCID researcher identifiers belonging to the principal' EQUALITY caseIgn + oreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcObjectClasses: {0}( 1.3.6.1.4.1.5923.1.1.2 NAME 'eduPerson' DESC 'eduPerson + per Internet2 and EDUCAUSE' AUXILIARY MAY ( eduPersonAffiliation $ eduPerson + Nickname $ eduPersonOrgDN $ eduPersonOrgUnitDN $ eduPersonPrimaryAffiliation + $ eduPersonPrincipalName $ eduPersonEntitlement $ eduPersonPrimaryOrgUnitDN + $ eduPersonScopedAffiliation $ eduPersonTargetedID $ eduPersonAssurance $ edu + PersonPrincipalNamePrior $ eduPersonUniqueId $ eduPersonOrcid ) ) + +dn: cn=edumember,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: edumember +olcAttributeTypes: {0}( 1.3.6.1.4.1.5923.1.5.1.1 NAME 'isMemberOf' DESC 'ident + ifiers for groups to which containing entity belongs' EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: {1}( 1.3.6.1.4.1.5923.1.5.1.2 NAME 'hasMember' DESC 'identi + fiers for entities that are members of the group' EQUALITY caseExactMatch SYN + TAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcObjectClasses: {0}( 1.3.6.1.4.1.5923.1.5.2.1 NAME 'eduMember' AUXILIARY MAY + ( isMemberOf $ hasMember ) ) diff --git a/comanage-registry-slapd/openssh-lpk.ldif b/comanage-registry-slapd/openssh-lpk.ldif new file mode 100644 index 0000000..cf717cc --- /dev/null +++ b/comanage-registry-slapd/openssh-lpk.ldif @@ -0,0 +1,5 @@ +dn: cn=openssh-lpk,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: openssh-lpk +olcAttributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' DESC 'MANDATORY: OpenSSH Public key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) +olcObjectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY DESC 'MANDATORY: OpenSSH LPK objectclass' MAY ( sshPublicKey $ uid ) )