Hi, I'm trying to setup multi-supplier replication with certificate-based authentication. The only documentation I have found on the subject is: https://access.redhat.com/documentation/en-us/red_hat_directory_server/11/html/administration_guide/configuring_replication_partners_to_use_certificate-based_authentication however it doesn't seems to be complete. I have been doing my test with openSUSE 15.3 and RHEL/CentOS 8 with SELinux disabled. Attached there are a couple of scripts (dmtest-init and dmtest-agmt) that will help you reproduce my setup so you can tell me what I'm missing or doing wrong. For testing you need two (virtual) machines and their ip addresses. A minimum text/server installation will do. Run on the first machine: ./dmtest-init <IP1> <IP2> The script will configure /etc/hosts so that the machine with IP1 can be reached as host1.example.com and the other as host2.example.com. 389-ds will be installed if not present. A new ds instance will be created, started (password is: password) and configured. /etc/openldap/ldap.conf is configured appropriately. group1 and user1 are created. Now run on the second machine the same command: ./dmtest-init <IP1> <IP2> the script will setup the second machine in the same way but with the following differences: The CA database is imported with rsync from host1. A new Server-Cert is created using the CA certificate from host1. group1 and user1 are not created. They should appear on host2 after host1 will replicate his database. A temporary replication manager account is created. At this point the following commands should work on both machines: ldapsearch -H ldaps://host1.example.com -D "cn=Directory Manager" -w password ldapsearch -H ldaps://host2.example.com -D "cn=Directory Manager" -w password Binding with a user certificate should also work: openssl req -subj "/DC=com/DC=example/OU=people/UID=user1" -newkey rsa:2048 -nodes -keyout cert.key -new -out cert.csr certutil -C -d /etc/dirsrv/ssca -f /etc/dirsrv/ssca/pwdfile.txt -a -i cert.csr -o cert.crt -c Self-Signed-CA LDAPTLS_CERT=$PWD/cert.crt LDAPTLS_KEY=$PWD/cert.key ldapsearch -H ldaps://host1.example.com -D "uid=user1,ou=people,dc=example,dc=com" The next step is the replication setup. Run on host1: ./dstest-agmt this script will: - create the group repl_server for nsds5ReplicaBindDNGroup - create accounts for both hosts - add the client certificates to the corresponding accounts - add both accounts to the group repl_server - create the replica entry - create the replication agreement (with bootstrapt parameters) These are essentially the steps described in the RedHat Directory Server 11 documentation: 15.6 Now a look at /var/log/dirsrv/slapd-ldaptest/errors shows that the replication bind with the bootstrap parameters works (group1 and user1 are now present on host2) but the replication bind with EXTERNAL auth fails. - ERR - slapi_ldap_bind - Error: could not bind id [(anon)] authentication mechanism [EXTERNAL]: error 49 (Invalid credentials) - ERR - NSMMReplicationPlugin - bind_and_check_pwp - agmt="cn=agreement" (host2:636) - Replication bind with EXTERNAL auth failed: LDAP error 49 (Invalid credentials) () - INFO - NSMMReplicationPlugin - bind_and_check_pwp - agmt="cn=agreement" (host2:636): Replication bind with SIMPLE auth resumed Clearly there is something wrong with the client certificate setup, but I could not figure out what. Any help is appreciated. Giacomo Comes
#!/bin/bash #### install 389-ds if ! type -p dbscan >/dev/null ; then if [[ -f /etc/redhat-release ]]; then ! yum module list 389-ds | grep -q '389-ds.*\[e]' && \ yum module enable -y 389-ds yum install -y 389-ds-base elif [[ -f /etc/SUSE-brand ]]; then zypper in -y 389-ds else echo "unknown distribution" exit 1 fi fi #### reset if [[ $1 = -reset ]]; then rm -f /etc/openldap/ldap-cacert.crt sed -i '/^BASE/d;/^URI/d;/^TLS_CACERT/d' /etc/openldap/ldap.conf DS=$(dsctl -l) [[ "$DS" ]] && dsctl $DS remove --do-it echo "directory server reset completed" exit fi #### preset values H1=host1.example.com H2=host2.example.com DSINSTANCE=ldaptest DBBASE='dc=example,dc=com' DSPASSWORD=password #### check the ip addresses and /etc/hosts [[ $1 ]] || exec echo 'missing ip for host1' [[ $2 ]] || exec echo 'missing ip for host2' [[ $1 = $2 ]] && exec echo 'the two ip must be different' ping -c 1 $1 >/dev/null || exec echo 'cannot ping host with ip: $1' ping -c 1 $2 >/dev/null || exec echo 'cannot ping host with ip: $2' ! grep -q "^${1//./\\.}[[:blank:]]" /etc/hosts && echo -e "$1\t$H1 ${H1%%.*}" >>/etc/hosts ! grep -q "^${1//./\\.}[[:blank:]]$H1 ${H1%%.*}" /etc/hosts && \ sed -i "/^${1//./\\.}[[:blank:]]/s@.*@$1\t$H1 ${H1%%.*}@" /etc/hosts ! grep -q "^${2//./\\.}[[:blank:]]" /etc/hosts && echo -e "$2\t$H2 ${H2%%.*}" >>/etc/hosts ! grep -q "^${2//./\\.}[[:blank:]]$H2 ${H2%%.*}" /etc/hosts && \ sed -i "/^${2//./\\.}[[:blank:]]/s@.*@$2\t$H2 ${H2%%.*}@" /etc/hosts DEV=$(ip route list scope global | awk -v v=dev '$1=="default"{for(a=2;a<NF;a++)if($a==v){print $(a+1);exit}}') ADDR=$(ip addr show dev $DEV scope global | awk '$1=="inet"{print $2;exit}' | cut -f1 -d/) #### set SID LOCALSUPPLIER REMOTESUPPLIER if [[ $ADDR = $1 ]]; then SID=1 ; LOCALSUPPLIER=$H1 ; REMOTESUPPLIER=$H2 elif [[ $ADDR = $2 ]]; then SID=2 ; LOCALSUPPLIER=$H2 ; REMOTESUPPLIER=$H1 else echo 'my ip is not $1 or $2, it is $ADDR' exit 1 fi #### create and start the instance: $DSINSTANCE if ! dsctl -l | grep -qFx slapd-$DSINSTANCE ; then TMP=$(mktemp -p /dev/shm) dscreate create-template >$TMP sed -i "/;full_machine_name/s@.*@full_machine_name = $LOCALSUPPLIER@" $TMP sed -i "/;instance_name/s@.*@instance_name = $DSINSTANCE@" $TMP sed -i "/;sample_entries/s@.*@sample_entries = yes@" $TMP sed -i "/;suffix/s@.*@suffix = $DBBASE@" $TMP #set a default password for testing sed -i "/;root_password/s@.*@root_password = $DSPASSWORD@" $TMP dscreate from-file $TMP rm $TMP if systemctl is-active -q firewalld ; then ! firewall-cmd -q --query-service ldap && firewall-cmd --add-service=ldap && firewall-cmd --runtime-to-permanent ! firewall-cmd -q --query-service ldaps && firewall-cmd --add-service=ldaps && firewall-cmd --runtime-to-permanent fi dsconf $DSINSTANCE config replace nsslapd-require-secure-binds=on dsconf $DSINSTANCE config replace nsslapd-force-sasl-external=on dsctl $DSINSTANCE restart fi #### copy the CA certificate in /etc/openldap/ldap-cacert.crt #### only on host2: syncronize Self-Signed-CA with host1, regenerate Server-Cert if [[ ! -f /etc/openldap/ldap-cacert.crt ]]; then if ((SID==2)); then echo " INFO: importing Self-Signed-CA from $REMOTESUPPLIER" rsync -avWHP --delete $REMOTESUPPLIER:/etc/dirsrv/ssca /etc/dirsrv cp /etc/dirsrv/ssca/ca.crt /etc/dirsrv/slapd-$DSINSTANCE/ca.crt certutil -F -n Server-Cert -d /etc/dirsrv/slapd-$DSINSTANCE -f /etc/dirsrv/slapd-$DSINSTANCE/pwdfile.txt certutil -D -d /etc/dirsrv/slapd-$DSINSTANCE -n Self-Signed-CA dsctl $DSINSTANCE tls generate-server-cert-csr -s "CN=$LOCALSUPPLIER" -8 $LOCALSUPPLIER certutil -C -d /etc/dirsrv/ssca -f /etc/dirsrv/ssca/pwdfile.txt -v 24 -a -i /etc/dirsrv/slapd-$DSINSTANCE/Server-Cert.csr -o /etc/dirsrv/slapd-$DSINSTANCE/Server-Cert.crt -c Self-Signed-CA openssl rehash /etc/dirsrv/slapd-$DSINSTANCE certutil -A -n Self-Signed-CA -t CT,, -a -i /etc/dirsrv/slapd-$DSINSTANCE/ca.crt -d /etc/dirsrv/slapd-$DSINSTANCE -f /etc/dirsrv/slapd-$DSINSTANCE/pwdfile.txt certutil -A -n Server-Cert -t ,, -a -i /etc/dirsrv/slapd-$DSINSTANCE/Server-Cert.crt -d /etc/dirsrv/slapd-$DSINSTANCE -f /etc/dirsrv/slapd-$DSINSTANCE/pwdfile.txt dsctl $DSINSTANCE restart fi cp /etc/dirsrv/ssca/ca.crt /etc/openldap/ldap-cacert.crt fi #### configure /etc/openldap/ldap.conf ! grep -qi '^base' /etc/openldap/ldap.conf && \ echo "BASE $DBBASE" >>/etc/openldap/ldap.conf ! grep -qi '^uri' /etc/openldap/ldap.conf && \ echo "URI ldap://$LOCALSUPPLIER" >>/etc/openldap/ldap.conf ! grep -qi '^TLS_CACERT' /etc/openldap/ldap.conf && \ echo "TLS_CACERT /etc/openldap/ldap-cacert.crt" >>/etc/openldap/ldap.conf #### on host1: create group1 and user1 #### on host2: create a temporary replication manager account if ((SID==1)); then LIST=$(dsidm -b $DBBASE $DSINSTANCE posixgroup list) ! echo "$LIST" | grep -qFx group1 && \ dsidm -b $DBBASE $DSINSTANCE posixgroup create --cn group1 --gidNumber 1000 LIST=$(dsidm -b $DBBASE $DSINSTANCE user list) ! echo "$LIST" | grep -qFx user1 && \ dsidm -b $DBBASE $DSINSTANCE user create \ --uid user1 \ --uidNumber 1000 \ --cn "User1" \ --displayName "User1 Test" \ --gidNumber 1000 \ --homeDirectory /home/user1 elif ((SID==2)); then LIST=$(dsidm -b $DBBASE $DSINSTANCE user list) if ! echo "$LIST" | grep -qFx $REMOTESUPPLIER ; then ! ldapsearch -Y EXTERNAL -Q -H ldapi://%2fvar%2frun%2fslapd-$DSINSTANCE.socket -b cn=config -LLL dn | grep -qF "cn=replication manager,cn=config" && \ dsconf $DSINSTANCE replication create-manager --passwd tmp1234 ! dsconf $DSINSTANCE replication list | grep -qFx $DBBASE && \ dsconf $DSINSTANCE replication enable --suffix="$DBBASE" --role="supplier" --replica-id="$SID" --bind-dn="cn=replication manager,cn=config" dsctl $DSINSTANCE restart fi fi
#!/bin/bash #### set SID LOCALSUPPLIER REMOTESUPPLIER DEV=$(ip route list scope global | awk -v v=dev '$1=="default"{for(a=2;a<NF;a++)if($a==v){print $(a+1);exit}}') ADDR=$(ip addr show dev $DEV scope global | awk '$1=="inet"{print $2;exit}' | cut -f1 -d/) case $(awk -v i=$ADDR '$1==i{print $3;exit}' </etc/hosts) in host1) SID=1 LOCALSUPPLIER=$(awk -v i=$ADDR '$1==i{print $2;exit}' </etc/hosts) REMOTESUPPLIER=$(awk -v i=host2 '$3==i{print $2;exit}' </etc/hosts) ;; host2) SID=2 LOCALSUPPLIER=$(awk -v i=$ADDR '$1==i{print $2;exit}' </etc/hosts) REMOTESUPPLIER=$(awk -v i=host1 '$3==i{print $2;exit}' </etc/hosts) ;; *) echo error this machine in not host1 or host2 exit 1 ;; esac #### set DSINSTANCE DBBASE DSINSTANCE=$(dsctl -l | sed 's@^slapd-@@') DBBASE=$(awk '$1=="BASE"{print $2;exit}' </etc/openldap/ldap.conf) #### on host1 if ((SID==1)); then #### create the group repl_server for nsds5ReplicaBindDNGroup ! dsidm -b $DBBASE $DSINSTANCE group list | grep -qFx repl_server && \ dsidm -b $DBBASE $DSINSTANCE group create --cn repl_server #### create accounts for both hosts #### add the client certificates to the corresponding accounts #### add both accounts to the group repl_server for a in $LOCALSUPPLIER $REMOTESUPPLIER ; do LIST=$(dsidm -b $DBBASE $DSINSTANCE user list) ! echo "$LIST" | grep -qFx $a && \ dsidm -b $DBBASE $DSINSTANCE user create --uid $a --uidNumber $((1000+SID)) --cn $a \ --displayName $a --gidNumber 2000 --homeDirectory /home/$a && \ TMP=$(mktemp -d --tmpdir=/dev/shm) && \ openssl req -subj "/DC=${DBBASE##*=}/DC=$(echo $DBBASE | cut -f1 -d, | cut -f2 -d=)/OU=people/UID=$a" -newkey rsa:2048 -nodes -keyout $TMP/cert.key -new -out $TMP/cert.csr && \ certutil -C -d /etc/dirsrv/ssca -f /etc/dirsrv/ssca/pwdfile.txt -v 24 -a -i $TMP/cert.csr -o $TMP/cert.crt -c Self-Signed-CA && \ openssl x509 -in $TMP/cert.crt -out $TMP/cert.der -outform DER && \ echo -e "dn: uid=$a,ou=people,$DBBASE\nchangetype: modify\nadd: userCertificate\nuserCertificate:< file://$TMP/cert.der" | ldapmodify -Y EXTERNAL -Q -H ldapi://%2fvar%2frun%2fslapd-$DSINSTANCE.socket && \ rm -r $TMP && \ echo -e "dn: cn=repl_server,ou=groups,$DBBASE\nchangetype: modify\nadd: member\nmember: uid=$a,ou=people,$DBBASE" | ldapmodify -Y EXTERNAL -Q -H ldapi://%2fvar%2frun%2fslapd-$DSINSTANCE.socket done #### create the replica entry ! dsconf $DSINSTANCE replication list | grep -qFx $DBBASE && \ dsconf $DSINSTANCE replication enable --suffix="$DBBASE" --role="supplier" --replica-id="$SID" --bind-group-dn="cn=repl_server,ou=groups,$DBBASE" && \ dsconf $DSINSTANCE replication set --suffix="$DBBASE" --repl-bind-group-interval=0 #### create the replication agreement ! dsconf $DSINSTANCE repl-agmt list --suffix=$DBBASE | grep -qFx 'cn: agreement' && \ dsconf $DSINSTANCE repl-agmt create --suffix="$DBBASE" --host="$REMOTESUPPLIER" --port=636 --conn-protocol=LDAPS --bind-method=SSLCLIENTAUTH --init --bootstrap-bind-dn="cn=replication manager,cn=config" --bootstrap-bind-passwd="tmp1234" --bootstrap-bind-method=SIMPLE --bootstrap-conn-protocol=LDAPS agreement fi
_______________________________________________ 389-users mailing list -- 389-users@xxxxxxxxxxxxxxxxxxxxxxx To unsubscribe send an email to 389-users-leave@xxxxxxxxxxxxxxxxxxxxxxx Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/389-users@xxxxxxxxxxxxxxxxxxxxxxx Do not reply to spam on the list, report it: https://pagure.io/fedora-infrastructure