-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #131 from SURFscz/add-dry-run
Add dry-run
- Loading branch information
Showing
17 changed files
with
478 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
backup.ldif* | ||
result.ldif* | ||
sync.json* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
--- | ||
|
||
services: | ||
ldap: | ||
image: ghcr.io/surfscz/sram-ldap:main | ||
ports: | ||
- 1389:1389 | ||
environment: | ||
LDAP_ROOT: "${BASEDN}" | ||
LDAP_ADMIN_USERNAME: "admin" | ||
LDAP_ADMIN_PASSWORD: "changethispassword" | ||
LDAP_CONFIG_ADMIN_USERNAME: "admin" | ||
LDAP_CONFIG_ADMIN_PASSWORD: "changethispassword" | ||
LDAP_CONFIG_ADMIN_ENABLED: "yes" | ||
LDAP_CUSTOM_SCHEMA_DIR: "/opt/ldap/schema" | ||
LDAP_SKIP_DEFAULT_TREE: "yes" | ||
LDAP_ENABLE_TLS: "no" | ||
LDAP_ENABLE_SYNCPROV: "yes" | ||
volumes: | ||
- ./schema:/opt/ldap/schema | ||
- ./ldif:/opt/ldap/ldif | ||
- ./backup.ldif:/backup.ldif:ro |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
#!/bin/bash | ||
|
||
set -e | ||
shopt -s extglob # for the string postfix matching below | ||
|
||
cleanup() { | ||
[ -n "$COMPOSE" ] && ${COMPOSE} rm --force --stop >/dev/null 2>&1 || true | ||
[ -n "$SOCAT_PID" ] && kill "$SOCAT_PID" || true | ||
[ -n "$TMPFILE" ] && rm -f "${TMPFILE}" || true | ||
} | ||
trap cleanup EXIT | ||
|
||
# check if data file are present | ||
if [ ! -f "backup.ldif" ] || [ ! -f "sync.json" ]; then | ||
echo "Data files backup.ldif and/or sync.json not found" | ||
echo "Copy ldap backup (slapcat -n1 output) to backup.ldif" | ||
echo "Copy SBS plsc sync output to sync.json" | ||
exit 1 | ||
fi | ||
|
||
GREEN="\033[0;32m" | ||
NORMAL="\033[0m" | ||
|
||
# check if we're using a remote docker host | ||
# in that case, we need to forward the local port 1389 to the real docker host | ||
# because all scripts depend on the ldap being available locally | ||
docker_host=$(docker context inspect -f '{{ .Endpoints.docker.Host }}') | ||
docker_proto=${docker_host:0:6} | ||
if [ "$docker_proto" == "tcp://" ]; then | ||
# remove protocol | ||
HOST=${docker_host:6} | ||
# remove port number | ||
HOST=${HOST%:+([[:digit:]])?(/)} | ||
|
||
echo "Using remote docker host $HOST ($docker_host)" | ||
socat "TCP4-LISTEN:1389,fork,reuseaddr" "TCP4:${HOST}:1389" 2>/dev/null & | ||
SOCAT_PID=$! | ||
fi | ||
|
||
|
||
# find basedn | ||
BASEDN=$( awk '/^dn: / { print $2; exit }' backup.ldif ) | ||
export BASEDN | ||
echo "Found basedn '$BASEDN'" | ||
|
||
COMPOSE_FILE="docker-compose.yml" | ||
COMPOSE="docker compose --file ${COMPOSE_FILE}" | ||
|
||
echo -n "Starting containers..." | ||
${COMPOSE} rm --force --stop >/dev/null 2>&1 || true | ||
${COMPOSE} up --detach >/dev/null 2>&1 | ||
echo | ||
|
||
echo -n "Waiting for ldap to start" | ||
while sleep 0.2 | ||
do | ||
echo -n "." | ||
if docker compose logs | grep -q '\*\* Starting slapd \*\*' | ||
then | ||
echo " Up!" | ||
break | ||
fi | ||
done | ||
|
||
echo "Configuring LDAP" | ||
${COMPOSE} exec ldap ldapmodify -H ldap://localhost:1389/ -D cn=admin,cn=config -w changethispassword -f /opt/ldap/ldif/config_1.ldif > /dev/null 2>&1 | ||
${COMPOSE} exec ldap ldapadd -H ldap://localhost:1389/ -D cn=admin,cn=config -w changethispassword -f /opt/ldap/ldif/config_2.ldif > /dev/null 2>&1 | ||
|
||
echo "Loading data" | ||
${COMPOSE} exec ldap slapadd -F /opt/bitnami/openldap/etc/slapd.d/ -n 2 -l /backup.ldif > /dev/null 2>&1 | ||
|
||
# generate plsc config | ||
echo "Generating plsc config" | ||
TMPFILE=$(mktemp -t plsc_XXXXXX.yml) | ||
cat <<EOF | sed 's/^ //' > "${TMPFILE}" | ||
--- | ||
ldap: | ||
src: | ||
uri: "ldap://localhost:1389/" | ||
basedn: "${BASEDN}" | ||
binddn: "cn=admin,${BASEDN}" | ||
passwd: "changethispassword" | ||
sizelimit: 5 | ||
dst: | ||
uri: "ldap://localhost:1389/" | ||
basedn: "${BASEDN}" | ||
binddn: "cn=admin,${BASEDN}" | ||
passwd: "changethispassword" | ||
sizelimit: 5 | ||
sbs: | ||
src: | ||
host: "test" | ||
sync: "dry_run/sync.json" | ||
pwd: '{CRYPT}!' | ||
uid: 1000 | ||
gid: 1000 | ||
EOF | ||
|
||
# install venv | ||
if ! test -d '../venv' | ||
then | ||
echo -n "Installing venv..." | ||
python3 -mvenv ../venv | ||
../venv/bin/pip install -q --upgrade pip wheel setuptools | ||
../venv/bin/pip install -q -r ../requirements.txt | ||
echo | ||
fi | ||
|
||
|
||
#export LOGLEVEL=DEBUG | ||
echo "Running plsc" | ||
( | ||
cd .. | ||
export PATH="$(pwd)/venv/bin:${PATH}" | ||
./run.sh "${TMPFILE}" | ||
) | ||
|
||
echo Dumping result | ||
docker-compose -f docker-compose.yml exec -ti ldap slapcat -F /opt/bitnami/openldap/etc/slapd.d/ -o ldif-wrap=no -n2 > result.ldif 2>/dev/null | ||
|
||
echo Comparing result | ||
../venv/bin/python ./ldifparser.py < backup.ldif > backup.ldif.parsed | ||
../venv/bin/python ./ldifparser.py < result.ldif > result.ldif.parsed | ||
diff --unified --text --color=always backup.ldif.parsed result.ldif.parsed && echo -e "${GREEN}No changes detected!${NORMAAL}" | ||
|
||
exit 0 |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
dn: cn=config | ||
changetype: Modify | ||
add: olcAttributeOptions | ||
olcAttributeOptions: time- | ||
|
||
dn: cn=module{1},cn=config | ||
changetype: Modify | ||
add: olcModuleLoad | ||
olcModuleLoad: {1}dynlist.so | ||
|
||
dn: olcDatabase={2}mdb,cn=config | ||
changetype: Modify | ||
replace: olcDbIndex | ||
olcDbIndex: objectClass eq,pres | ||
olcDbIndex: ou,cn,mail,surname,givenname eq,pres,sub | ||
olcDbIndex: entryUUID eq | ||
olcDbIndex: o eq | ||
olcDbIndex: dc eq | ||
olcDbIndex: entryCSN eq | ||
|
||
replace: olcDbMaxSize | ||
olcDbMaxSize: 1073741824 | ||
|
||
replace: olcAccess | ||
olcAccess: {0}to dn.regex="(([^,]+),dc=services,dc=vnet)$" by dn.exact="cn=adm | ||
in,dc=services,dc=vnet" write by dn.exact=gidNumber=0+uidNumber=0,cn=peercred | ||
,cn=external,cn=auth write by dn.exact,expand="cn=admin,$1" read by * break | ||
olcAccess: {1}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external | ||
,cn=auth manage by dn.regex="cn=[^,]+,dc=services,dc=vnet" read by dn.exact= | ||
gidNumber=1000+uidNumber=1000,cn=peercred,cn=external,cn=auth manage by * br | ||
eak | ||
olcAccess: {2}to attrs=userPassword by self write by anonymous auth by * break |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
dn: olcOverlay={1}dynlist,olcDatabase={2}mdb,cn=config | ||
objectClass: olcOverlayConfig | ||
objectClass: olcDynListConfig | ||
olcOverlay: {1}dynlist | ||
olcDynListAttrSet: {0}voPerson labeledURI member+memberOf@groupOfMembers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#!/usr/bin/env python3 | ||
import sys | ||
import ldif | ||
from collections import OrderedDict | ||
|
||
|
||
def kcmp(item): | ||
(key, v) = item | ||
parts = key.split(',')[::-1] | ||
new_key = ','.join(parts) | ||
return (new_key, v) | ||
|
||
|
||
def freeze(o): | ||
if isinstance(o, dict): | ||
return OrderedDict({k: freeze(v) for k, v in sorted(o.items(), key=kcmp)}.items()) | ||
if isinstance(o, list): | ||
return sorted([freeze(v) for v in o]) | ||
return o.decode('utf-8') | ||
|
||
|
||
def my_print(o, depth): | ||
if isinstance(o, OrderedDict): | ||
for k, v in o.items(): | ||
my_print(k, depth) | ||
my_print(v, depth + 2) | ||
elif isinstance(o, list): | ||
for v in o: | ||
my_print(v, depth) | ||
else: | ||
print(f"{' ' * depth}{o}") | ||
|
||
|
||
ldifparser = ldif.LDIFRecordList(sys.stdin) | ||
ldifparser.parse() | ||
|
||
data = {k: v for k, v in ldifparser.all_records} | ||
f = freeze(data) | ||
|
||
# print(json.dumps(f, indent=2)) | ||
my_print(f, 0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
dn: cn=eduMember,cn=schema,cn=config | ||
objectClass: olcSchemaConfig | ||
cn: eduMember | ||
# Internet X.500 Schema for Ldappc | ||
# Includes the eduMember ObjectClass schema | ||
# | ||
# | ||
# An auxiliary object class, "eduMember," is a convenient container | ||
# for an extensible set of attributes concerning group memberships. | ||
# At this time, the only attributes specified as belonging to the | ||
# object class are "isMemberOf" and "hasMember." | ||
# | ||
olcAttributeTypes: ( 1.3.6.1.4.1.5923.1.5.1.1 | ||
NAME 'isMemberOf' | ||
DESC 'identifiers for groups to which containing entity belongs' | ||
EQUALITY caseExactMatch | ||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) | ||
olcAttributeTypes: ( 1.3.6.1.4.1.5923.1.5.1.2 | ||
NAME 'hasMember' | ||
DESC 'identifiers for entities that are members of the group' | ||
EQUALITY caseExactMatch | ||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) | ||
olcObjectClasses: ( 1.3.6.1.4.1.5923.1.5.2.1 | ||
NAME 'eduMember' | ||
AUXILIARY | ||
MAY ( isMemberOf $ hasMember ) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
dn: cn=eduperson,cn=schema,cn=config | ||
objectClass: olcSchemaConfig | ||
cn: eduperson | ||
olcAttributeTypes: ( 1.3.6.1.4.1.5923.1.1.1.1 | ||
NAME 'eduPersonAffiliation' | ||
DESC 'eduPerson per Internet2 and EDUCAUSE' | ||
EQUALITY caseIgnoreMatch | ||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) | ||
olcAttributeTypes: ( 1.3.6.1.4.1.5923.1.1.1.7 | ||
NAME 'eduPersonEntitlement' | ||
DESC 'eduPerson per Internet2 and EDUCAUSE' | ||
EQUALITY caseExactMatch | ||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) | ||
olcAttributeTypes: ( 1.3.6.1.4.1.5923.1.1.1.2 | ||
NAME 'eduPersonNickName' | ||
DESC 'eduPerson per Internet2 and EDUCAUSE' | ||
EQUALITY caseIgnoreMatch | ||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) | ||
olcAttributeTypes: ( 1.3.6.1.4.1.5923.1.1.1.3 | ||
NAME 'eduPersonOrgDN' | ||
DESC 'eduPerson per Internet2 and EDUCAUSE' | ||
EQUALITY distinguishedNameMatch | ||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE ) | ||
olcAttributeTypes: ( 1.3.6.1.4.1.5923.1.1.1.4 | ||
NAME 'eduPersonOrgUnitDN' | ||
DESC 'eduPerson per Internet2 and EDUCAUSE' | ||
EQUALITY distinguishedNameMatch | ||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) | ||
olcAttributeTypes: ( 1.3.6.1.4.1.5923.1.1.1.5 | ||
NAME 'eduPersonPrimaryAffiliation' | ||
DESC 'eduPerson per Internet2 and EDUCAUSE' | ||
EQUALITY caseIgnoreMatch | ||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE ) | ||
olcAttributeTypes: ( 1.3.6.1.4.1.5923.1.1.1.8 | ||
NAME 'eduPersonPrimaryOrgUnitDN' | ||
DESC 'eduPerson per Internet2 and EDUCAUSE' | ||
EQUALITY distinguishedNameMatch | ||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE ) | ||
olcAttributeTypes: ( 1.3.6.1.4.1.5923.1.1.1.6 | ||
NAME 'eduPersonPrincipalName' | ||
DESC 'eduPerson per Internet2 and EDUCAUSE' | ||
EQUALITY caseIgnoreMatch | ||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE ) | ||
olcAttributeTypes: ( 1.3.6.1.4.1.5923.1.1.1.12 | ||
NAME 'eduPersonPrincipalNamePrior' | ||
DESC 'eduPersonPrincipalNamePrior per Internet2' | ||
EQUALITY caseIgnoreMatch | ||
SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) | ||
olcAttributeTypes: ( 1.3.6.1.4.1.5923.1.1.1.9 | ||
NAME 'eduPersonScopedAffiliation' | ||
DESC 'eduPerson per Internet2 and EDUCAUSE' | ||
EQUALITY caseIgnoreMatch | ||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) | ||
olcAttributeTypes: ( 1.3.6.1.4.1.5923.1.1.1.10 | ||
NAME 'eduPersonTargetedID' | ||
DESC 'eduPerson per Internet2 and EDUCAUSE' | ||
EQUALITY caseExactMatch | ||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) | ||
olcAttributeTypes: ( 1.3.6.1.4.1.5923.1.1.1.11 | ||
NAME 'eduPersonAssurance' | ||
DESC 'eduPerson per Internet2 and EDUCAUSE' | ||
EQUALITY caseExactMatch | ||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) | ||
olcAttributeTypes: ( 1.3.6.1.4.1.5923.1.1.1.13 | ||
NAME 'eduPersonUniqueId' | ||
DESC 'eduPersonUniqueId per Internet2' | ||
EQUALITY caseIgnoreMatch | ||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE ) | ||
olcAttributeTypes: ( 1.3.6.1.4.1.5923.1.1.1.16 | ||
NAME 'eduPersonOrcid' | ||
DESC 'ORCID researcher identifiers belonging to the principal' | ||
EQUALITY caseIgnoreMatch | ||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) | ||
olcObjectClasses: ( 1.3.6.1.4.1.5923.1.1.2 | ||
NAME 'eduPerson' | ||
AUXILIARY | ||
MAY ( | ||
eduPersonAffiliation $ eduPersonNickname $ eduPersonOrgDN $ | ||
eduPersonOrgUnitDN $ eduPersonPrimaryAffiliation $ | ||
eduPersonPrincipalName $ eduPersonEntitlement $ eduPersonPrimaryOrgUnitDN $ | ||
eduPersonScopedAffiliation $ eduPersonTargetedID $ eduPersonAssurance $ | ||
eduPersonPrincipalNamePrior $ eduPersonUniqueId $ eduPersonOrcid ) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Internet X.500 Schema for Ldappc | ||
# Includes the groupOfMembers ObjectClass schema | ||
# | ||
# Taken from RFC2307bis draft 2 | ||
# https://tools.ietf.org/html/draft-howard-rfc2307bis-02 | ||
# | ||
# An structural object class, "groupOfMembers" is a convenient container | ||
# for an extensible set of attributes concerning group memberships. | ||
# | ||
dn: cn=groupOfMembers,cn=schema,cn=config | ||
objectClass: olcSchemaConfig | ||
cn: groupOfMembers | ||
olcObjectClasses: ( 1.3.6.1.1.1.2.18 SUP top STRUCTURAL | ||
NAME 'groupOfMembers' | ||
DESC 'A group with members (DNs)' | ||
MUST cn | ||
MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ | ||
description $ member ) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
dn: cn=openssh-lpk-openldap,cn=schema,cn=config | ||
objectClass: olcSchemaConfig | ||
cn: openssh-lpk-openldap | ||
# | ||
# LDAP Public Key Patch schema for use with openssh-ldappubkey | ||
# useful with PKA-LDAP also | ||
# | ||
# Author: Eric AUGE <[email protected]> | ||
# | ||
# Based on the proposal of : Mark Ruijter | ||
# | ||
# octetString SYNTAX | ||
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 ) | ||
# printableString SYNTAX yes|no | ||
olcObjectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY | ||
DESC 'MANDATORY: OpenSSH LPK olcObjectClasses:' | ||
MUST ( sshPublicKey $ uid ) | ||
) |
Oops, something went wrong.