On my server I have an LDAP directory where all the users are stored. To use this for user authentication for GIT using Gitolite you will need 3 things…
First – Getting usergroup information from LDAP
The first source you should bounce in when trying to do this is . There you can read that you will need a script and setting 2 properties in .gitolite.rc
:
$GL_GET_MEMBERSHIPS_PGM = "/usr/local/bin/expand-ldap-user-to-groups"
$GL_BIG_CONFIG = 1;
The script is, as you can see, in out case located at: /usr/local/bin/expand-ldap-user-to-groups
. It accepts one parameter and that is the user name. It searches the LDAP directory for the user’s primary group and all secondary groups. The result will be returned as a space separated list of group names. The script:
#!/bin/bash
USER=$1
GID=""
groups=""
BIND_DN="cn=admin,dc=poterion,dc=com"
BIND_PW="*****"
USERS_DN="ou=users,dc=poterion,dc=com"
GROUPS_DN="ou=groups,dc=poterion,dc=com"
LOGIN_KEY="uid"
GID_KEY="gidNumber"
GROUP_KEY="cn"
MEMBER_KEY="memberUid"
IFS="
"
currentLogin=""
currentGID=""
for line in `ldapsearch -h localhost -s one -D "${BIND_DN}" -w ${BIND_PW} -b ${USERS_DN} ${LOGIN_KEY} ${GID_KEY}`; do
if [ "${line:0:1}" = "#" ]; then
if [ ! -z $currentLogin ]; then
if [ "${currentLogin}" = "${USER}" ]; then
GID=$currentGID
fi
currentLogin=""
currentGID=""
fi
fi
if [ "${line:0:${#LOGIN_KEY}}: " = "${LOGIN_KEY}: " ]; then
currentLogin=`echo ${line} | cut -d":" -f2`
currentLogin=${currentLogin:1}
elif [ "${line:0:${#GID_KEY}}: " = "${GID_KEY}: " ]; then
currentGID=`echo ${line} | cut -d":" -f2`
currentGID=${currentGID:1}
fi
done
currentGroup=""
currentMembers=""
currentGID=""
for line in `ldapsearch -h localhost -D "${BIND_DN}" -w ${BIND_PW} -b ${GROUPS_DN} ${GROUP_KEY} ${MEMBER_KEY} ${GID_KEY}`; do
if [ "${line:0:1}" = "#" ]; then
if [ ! -z $currentGroup ]; then
IFS=" "
for user in $currentMembers; do
if [ "${user}" = "${USER}" ]; then
groups="${groups} ${currentGroup}"
currentGID=""
fi
done
if [ "${currentGID}" = "${GID}" ]; then
groups="${groups} ${currentGroup}"
fi
currentGroup=""
currentMembers=""
currentGID=""
fi
fi
if [ "${line:0:${#GROUP_KEY}}: " = "${GROUP_KEY}: " ]; then
currentGroup=`echo ${line} | cut -d":" -f2`
currentGroup=${currentGroup:1}
elif [ "${line:0:${#MEMBER_KEY}}: " = "${MEMBER_KEY}: " ]; then
user=`echo ${line} | cut -d":" -f2`
user=${user:1}
currentMembers="${currentMembers} ${user}"
elif [ "${line:0:${#GID_KEY}}: " = "${GID_KEY}: " ]; then
currentGID=`echo ${line} | cut -d":" -f2`
currentGID=${currentGID:1}
fi
IFS="
"
done
if [ ! -z "${groups}" ]; then
echo ${groups:1}
fi
Second – Password authentication with gitolite
You need to authenticate using a public key with Gitolite. This is neccessary since gitolite uses only one system user. Another option is to create each user on the system and hook the authentication as described in Enabling git access via password authentication with gitolite. The only difference in my script was adding an extra check for “virt-shell” group. This allows me to have a user who is able to use GIT via SSH but is not able to login to the shell controlled just by his membership in “virt-shell”. The resulting script is stored in /usr/bin/bash
which should be also a shell in passwd
for every user in the system.
#!/bin/bash
shift # get rid of -c
# if no commands, just open a shell
if [[ $# -eq 0 ]]; then
if groups 2> /dev/null | grep -Eq ' host-diderma ' && groups 2> /dev/null | grep -Eq ' virt-shell ' ; then
/bin/bash -l
else
echo "Error: Not member of host-diderma or virt-shell groups." >&2
fi;
# if the first arg is a git- command, that means it is something like git-push, etc... so forward it
elif [[ $1 == git-* ]]; then
ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no git@localhost $*
# if the first arg is SET_ENV_ONLY, we sourced this file in order to set up the gitolite function
elif [[ $1 == "SET_ENV_ONLY" ]]; then
gitolite () {
ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no git@localhost $*
}
# if there is at least one non-git command, source this file in a new shell and create the 'gitolite' function
else
/bin/bashplain -c "source $0 shiftme SET_ENV_ONLY; $*"
fi
Thirds
Last thing todo is to be able to add new user to Gitolite just by addind them to the LDAP directory. This can be accomplished using pam_script. I added a /var/lib/pam/scripts/onsessionopen/create-gitolite-user.sh
:
#!/bin/bash
USERID=$1
GROUPID=$(getent group `getent passwd verena.geist | cut -d":" -f4` | cut -d":" -f1)
HOMEDIR=`getent passwd $USERID | cut -d":" -f6`
REPOS="/srv/git/repositories/"
REPO="gitolite-admin"
MACHINE="poterion-com"
if [ ! -f ${HOMEDIR}/.ssh/id_rsa.pub ]; then
rm -rf ${HOMEDIR}/.ssh/id_rsa
ssh-keygen -t rsa -N "" -f ${HOMEDIR}/.ssh/id_rsa
chown ${USERID} ${HOMEDIR}/.ssh/id_rsa
chgrp ${GROUPID} ${HOMEDIR}/.ssh/id_rsa
chown ${USERID} ${HOMEDIR}/.ssh/id_rsa.pub
chgrp ${GROUPID} ${HOMEDIR}/.ssh/id_rsa.pub
fi
CURDIR=`pwd`
cd /tmp
git clone ${REPOS}${REPO}.git ${REPO}
cd ${REPO}
KEY=keydir/${USERID}@${MACHINE}.pub
if [[ ! -f ${KEY} || -n `diff ${KEY} ${HOMEDIR}/.ssh/id_rsa.pub` ]]; then
cp ${HOMEDIR}/.ssh/id_rsa.pub ${KEY};read
git add -A;read
git commit --author='PAM Script ' -m "Add/Update user ${USERID}.";read
git push
fi
cd ..
rm -rf ${REPO}
cd $CURDIR
As soon as the user’s session is opened a ssh-key will be generated for him and added to Gitolite.