multi-supplier replication with certificate-based authentication

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Fedora User Discussion]     [Older Fedora Users]     [Fedora Announce]     [Fedora Package Announce]     [EPEL Announce]     [Fedora News]     [Fedora Cloud]     [Fedora Advisory Board]     [Fedora Education]     [Fedora Security]     [Fedora Scitech]     [Fedora Robotics]     [Fedora Maintainers]     [Fedora Infrastructure]     [Fedora Websites]     [Anaconda Devel]     [Fedora Devel Java]     [Fedora Legacy]     [Fedora Desktop]     [Fedora Fonts]     [ATA RAID]     [Fedora Marketing]     [Fedora Management Tools]     [Fedora Mentors]     [Fedora Package Review]     [Fedora R Devel]     [Fedora PHP Devel]     [Kickstart]     [Fedora Music]     [Fedora Packaging]     [Centos]     [Fedora SELinux]     [Fedora Legal]     [Fedora Kernel]     [Fedora QA]     [Fedora Triage]     [Fedora OCaml]     [Coolkey]     [Virtualization Tools]     [ET Management Tools]     [Yum Users]     [Tux]     [Yosemite News]     [Yosemite Photos]     [Linux Apps]     [Maemo Users]     [Gnome Users]     [KDE Users]     [Fedora Tools]     [Fedora Art]     [Fedora Docs]     [Maemo Users]     [Asterisk PBX]     [Fedora Sparc]     [Fedora Universal Network Connector]     [Fedora ARM]

  Powered by Linux