Skip to content

Instantly share code, notes, and snippets.

@fapestniegd
Created July 18, 2010 15:54
Show Gist options
  • Save fapestniegd/480498 to your computer and use it in GitHub Desktop.
Save fapestniegd/480498 to your computer and use it in GitHub Desktop.
#!/bin/bash
################################################################################
# using this host's credentials, look up the (yes, plaintext) userpassword for
# cn=LDAP Anonymous,ou=Special,dc=websages,dc=com, to which all members or
# ou=Hosts have read (ACL in /etc/ldap/slapd/domains/${f.q.d.n}_slapd.conf)
# so that we can put it in the global ldap.conf, such that we can disable
# "true" anonymous binds, but getent will work for everyone, because the
# /etc/ldap.secret won't have to exist and be mode 0600
################################################################################
export PATH="/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin"
logexit(){
EXIT=$1
WHY=$2
[ -z "${WHY}" ] && WHY="no reason specified"
echo "$0 exited ${EXIT} last time because ${WHY}." >> /var/log/logexit.log
exit ${EXIT}
}
grep "^binddn cn=LDAP Anonymous" /etc/ldap/ldap.conf >/dev/null 2>&1
if [ $? -eq 0 ]; then
if [ -x /usr/local/sbin/testldap ]; then
/usr/local/sbin/testldap && exit 0
fi
fi
if [ ! -x /usr/local/sbin/secret ]; then
logexit 1 "/usr/local/sbin/secret not executable"
fi
SECRET=$(/usr/local/sbin/secret)
if [ -z "$(dnsdomainname)" ] ;then
logexit 1 "cannot determine dns domain name"
fi
if [ -z "$(hostname -s)" ]; then
logexit 1 "cannot determine short host name"
fi
URI=$(
for h in `dig +short -tsrv _ldap._tcp.$(dnsdomainname)|awk '{print $NF}'|sed -e 's/\.$//'`;do
echo "$(traceroute ${h}|grep -v '* * *'|tail -1 |awk '{print $1}') ${h}"
done | sort -n | awk '{if($2!=""){print " ldaps://"$2":636,"}}' | tr '\n' ' '|sed -e 's/, *$//';
)
if [ -z "${URI}" ] ;then
logexit 1 "could not get URIs"
fi
BASEDN="dc=$(dnsdomainname|sed -e 's/\./,dc=/g')"
HOST=$(hostname -s)
SECRET=$(/usr/local/sbin/secret)
export URI BASEDN HOST SECRET
################################################################################
# get the anonymous password from ldap, and transform from mime if necessary #
ANONPASS=$(
ldapsearch -xLH "$URI" \
-b "${BASEDN}" \
-D "cn=${HOST},ou=Hosts,${BASEDN}" \
-w "${SECRET}" "(cn=LDAP Anonymous)" | \
tr "\n" ''| sed -e 's/ //g' | tr '' "\n" | grep -i userpassword
)
echo ${ANONPASS} | grep -qi "userPassword:: " && \
ANONPASS=$(
echo ${ANONPASS}|awk '{print $2}'| \
perl -MMIME::Base64 -le '
while(chomp($line=<STDIN>)){
$key=decode_base64($line);
chomp($key);
print $key;
}
'
) || \
ANONPASS=$( echo ${ANONPASS} |awk '{print $2}' )
################################################################################
if [ -z ${ANONPASS} ];then
logexit 1 "cannot retrieve the anonymous password"
fi
if [ -z ${ANONPASS} ];then
logexit 1 "cannot retrieve the anonymous password"
fi
cat<<EOF > /etc/ldap/ldap.conf.new
uri ${URI}
base ${BASEDN}
ldap_version 3
scope sub
TLS_CACERT /etc/ldap/ssl/domain_trustchain.pem
# sudo-ldap uses this one but not the one above... ugh
TLS_CACERTFILE /etc/ldap/ssl/domain_trustchain.pem
TLS_REQCERT allow
binddn cn=LDAP Anonymous,ou=Special,${BASEDN}
bindpw ${ANONPASS}
pam_filter objectclass=posixAccount
pam_login_attribute uid
pam_crypt local
pam_password md5
sudoers_base ou=sudoers,${BASEDN}
#sudoers_debug 5
ssl yes
EOF
if [ -f /etc/ldap/ldap.conf.new ];then
grep ${ANONPASS} /etc/ldap/ldap.conf.new > /dev/null 2>&1
if [ $? -ne 0 ]; then
logexit 1 "anonymous password is not in new file"
fi
fi
OLD=$(md5sum /etc/ldap/ldap.conf|awk '{print $1}')
NEW=$(md5sum /etc/ldap/ldap.conf.new|awk '{print $1}')
if [ "${NEW}" != "${OLD}" ]; then
/bin/cp /etc/ldap/ldap.conf.new /etc/ldap/ldap.conf
chmod 444 /etc/ldap/ldap.conf
fi
logexit 0 "everything looks good"
#!/bin/bash
################################################################################
# This is a test for both the host credentials and the anonymous credentials
################################################################################
export PATH="/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin"
LDAP_URIS=($(dig +short -tsrv _ldap._tcp.$(dnsdomainname)|awk '{print "ldaps://"$4":"$3}'|sed -e 's/\.:/:/'))
anon-passwd(){
RESULT=1; IDX=0;
while [ ${RESULT} -ne 0 -a ${IDX} -lt ${#LDAP_URIS[@]} ];do
ANON_PASS=$(
ldapsearch -xH ${LDAP_URIS[${IDX}]} \
-b "ou=Special,dc=websages,dc=com" \
-D "cn=$(hostname -s),ou=Hosts,dc=websages,dc=com" \
-w $(secret) -s sub "(cn=LDAP Anonymous)" | \
tr "\n" ''| sed -e 's/ //g' | tr '' "\n" | \
sed -e 's/#.*//g' | grep "^userPassword" | awk '{print $2}' | \
perl -MMIME::Base64 -le '
while(chomp($line=<STDIN>)){
$key=decode_base64($line);
chomp($key);
print $key;
}
'
export RESULT=$?
)
IDX=`expr ${IDX} + 1`
done
echo ${ANON_PASS}
}
ldap-bind(){
RESULT=1; IDX=0;
while [ ${RESULT} -ne 0 -a ${IDX} -lt ${#LDAP_URIS[@]} ];do
ldapsearch -xH ${LDAP_URIS[${IDX}]} \
-b "dc=$(dnsdomainname|sed -e 's/\./,dc=/g')" \
-D "cn=LDAP Anonymous,ou=Special,dc=$(dnsdomainname|sed -e 's/\./,dc=/g')" \
-w "$(anon-passwd)" "(cn=$(hostname -s))"
RESULT=$?
IDX=`expr ${IDX} + 1`
done
return ${RESULT}
}
ldap-bind > /dev/null 2>&1
exit $?
#/bin/bash
PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
LOG="/var/log/wcyd.log"
########################################################################
# make sure we've got the latest package list on a apt/yum system...
########################################################################
apt-get update >> $LOG 2>&1 || yum update >> $LOG 2>&1
########################################################################
# This is the bare-minimum a host needs to get initialized into the farm
########################################################################
# It's so configuring a host will consist of just running:
#
# wget -qO /tmp/wcyd "$(dig +short -ttxt wcyd.$(dnsdomainname))"
# chmod 755 /tmp/wcyd; /tmp/wcyd $(hostname -f) ${LDAP_HOST_PASSWORD}
#
################################################################################
# functions
################################################################################
usage(){
echo "Usage $0 <fully.qualified.domain.nam> [<ldap_secret>]"
exit 1;
}
####################################
# Common fixups
####################################
fix_etc_hosts(){
FQDN=$1
echo "rewriting /etc/hosts"
if [ -f /etc/.new_etc_hosts ];then rm /etc/.new_etc_hosts;fi
HNAME=$(echo ${FQDN} |sed -e 's/\..*//g')
LOCAL=$(grep "127.0.0.1" /etc/hosts| head -1)
if [ ! -z "${LOCAL}" ];then
echo "${LOCAL}"|grep -q "127.0.0.1 *localhost.localdomain *localhost" || \
LOCAL=$(echo ${LOCAL}|sed -e 's/127.0.0.1.*/127.0.0.1 localhost.localdomain localhost/')
else
LOCAL="127.0.0.1 localhost.localdomain localhost"
fi
PUBLIC=$(grep "${IPADDR}" /etc/hosts)
if [ ! -z "${PUBLIC}" ];then
echo "${PUBLIC}"|grep -q "${IPADDR} *${FQDN} *${HNAME}"||\
PUBLIC=$(echo "${PUBLIC}"| sed -e "s/${IPADDR}.*/${IPADDR} ${FQDN} ${HNAME}/")
else
PUBLIC="${IPADDR} ${FQDN} ${HNAME}"
fi
echo "${LOCAL}" > /etc/.new_etc_hosts
echo "${PUBLIC}" >> /etc/.new_etc_hosts
sed -e "s/127.0.0.1.*//" -e "s/${IPADDR}.*//" /etc/hosts |grep .>> /etc/.new_etc_hosts
if [ ! -f /etc/hosts.dists ];then mv /etc/hosts /etc/hosts.dist;fi
mv /etc/.new_etc_hosts /etc/hosts
}
####################################
# Debian style fixups
####################################
fix_etc_hostname(){
echo "rewriting /etc/hostname"
FQDN=$(hostname -f);
if [ ! -z "${FQDN}" ]; then
echo "${FQDN}" > /etc/hostname
else
echo "unable to determine host name in fix_etc_hostname.";
fi
}
fix_etc_mailname(){
echo "rewriting /etc/mailname"
DOMAIN=$(dnsdomainname)
if [ ! -z "${DOMAIN}" ]; then
HNAME=$(hostname -s);
FQDN=$(hostname -f);
DOMAIN=$(echo $FQDN|sed -e "s/${HNAME}\.//")
fi
if [ ! -z "${DOMAIN}" ]; then
echo "Setting mail name to ${DOMAIN}";
echo "${DOMAIN}" > /etc/mailname
else
echo "unable to determine domain name in fix_etc_mailname.";
exit -1;
fi
}
####################################
# RedHat style fixups
####################################
####################################
# git our sources
####################################
# This will now fail if the host's key is not set up in gitosis/keydir
puppet_init(){
if [ ! -d /var/cache/git ]; then mkdir -p /var/cache/git;fi
if [ ! -d /root/.ssh ]; then (umask 077; mkdir -p /root/.ssh);fi
echo "Downloading Repositories"
ssh-keyscan github.com >> /root/.ssh/known_hosts >> ${LOG} 2>&1
if [ -d /var/cache/git/puppet-strings ];then
(cd /var/cache/git/puppet-strings; git pull)>> ${LOG} 2>&1
else
dig +short -ttxt puppet-strings.$(dnsdomainname) | sed -e 's/"//g'| while read repo; do
if [ ! -d "/var/cache/git/puppet-strings" ];then
(cd /var/cache/git; git clone ${repo})
fi;
done
(cd /var/cache/git; git clone )>> ${LOG} 2>&1
fi
[ -d /var/log/puppet ] ||/bin/mkdir -p /var/log/puppet
if [ -f /var/cache/git/puppet-strings/hosts/$(hostname -f).pp ]; then
puppet --debug --modulepath=/var/cache/git/puppet-strings/modules/ \
/var/cache/git/puppet-strings/hosts/$(hostname -f).pp \
> /var/log/puppet/firstrun.log 2>&1
else
puppet --debug --modulepath=/var/cache/git/puppet-strings/modules/ \
/var/cache/git/puppet-strings/hosts/default.pp \
> /var/log/puppet/firstrun.log 2>&1
fi
}
secret-init(){
echo "Initializing secret"
SECRET=$1;
UMASK=$(umask)
umask 0077
if [ -z $SECRET ];then
SUPPLIED="Auto-Generated"
SECRET=$(dd if=/dev/random bs=512 count=1 2>/dev/null|md5sum|\
perl -MMIME::Base64 -ne 'print encode_base64($_)')
else
SUPPLIED="Provided"
fi
/bin/cat<<EOSEC>/usr/local/sbin/secret
#!/bin/bash
# Password: ${SUPPLIED}
echo -n "${SECRET}"
EOSEC
# just in case umask went awry...
chown root:root /usr/local/sbin/secret
chmod 700 /usr/local/sbin/secret
umask ${UMASK}
if [ ! -f /root/.ssh/id_dsa.pub ];then
if [ ! -d /root/.ssh ];then
mkdir -p /root/.ssh
chown root:root /root/.ssh
chmod 700 /root/.ssh
fi
ssh-keygen -t dsa -N '' -f /root/.ssh/id_dsa>/dev/null 2>&1
fi
}
####################################
# LDAP Routines
# /*FIXME*/ write parallel gist ones
####################################
ldap-bind(){
LDAP_URIS=($(dig +short -tsrv _ldap._tcp.$(dnsdomainname)|awk '{print "ldaps://"$4":"$3}'|sed -e 's/\.:/:/'))
RESULT=1; IDX=0;
while [ ${RESULT} -ne 0 -a ${IDX} -le ${#LDAP_URIS[@]} ];do
ldapsearch -xH ${LDAP_URIS[${IDX}]} \
-b "dc=$(dnsdomainname|sed -e 's/\./,dc=/g')" \
-D "cn=$(hostname -s),ou=Hosts,dc=$(dnsdomainname|sed -e 's/\./,dc=/g')" \
-w "$(/usr/local/sbin/secret)" "(cn=$(hostname -s))"
RESULT=$?
IDX=`expr ${IDX} + 1`
done
return ${RESULT}
}
ldif_dump(){
NAME=$1
VALUE=$2
MIMELINE=$(perl -MMIME::Base64 -le 'print "$ARGV[0]::".encode_base64($ARGV[1]);' "${NAME}" "${VALUE}"|tr '\n' ' '|sed -e 's/ //g' -e 's/::/:: /';)
LENGTH=$(echo -n "${MIMELINE}" | wc -c)
CHUNK=$(echo "${MIMELINE}"|cut -b 1-78)
echo ${CHUNK}
MIMELINE=$(echo ${MIMELINE}|sed -e "s/^${CHUNK}//")
while [ ${LENGTH} -gt 0 ];do
CHUNK=$(echo "${MIMELINE}"|cut -b 1-77)
echo " ${CHUNK}"
MIMELINE=$(echo "${MIMELINE}"|sed -e "s/^${CHUNK}//")
LENGTH=$(echo -n "${MIMELINE}" | wc -c)
done
}
ldapadd-selfrecord(){
LDIF=$(mktemp /tmp/ldif.XXXX)
cat<<EOF>${LDIF}
dn: cn=$(hostname -s),ou=Hosts,dc=$(dnsdomainname|sed -e 's/\./,dc=/g')
configBase: debian_lenny
objectClass: configHost
objectClass: device
objectClass: ipHost
objectClass: top
objectClass: simpleSecurityObject
objectClass: ldapPublicKey
cn: $(hostname -s)
configSet: ldap_client
EOF
# insert all the IP addresses
for IP in `ifconfig | grep "inet addr:"|sed -e 's/.*inet addr://g' -e 's/ .*//g'|grep -v 127.0.0.1`;do
echo "ipHostNumber: ${IP}" >> ${LDIF}
done
# insert the id_dsa.pub
cat /root/.ssh/id_dsa.pub|while read LINE; do
ldif_dump "sshPublicKey" "${LINE}" >> ${LDIF}
done
# insert the SSHA password
SALT=$(dd if=/dev/random bs=512 count=1 2>/dev/null|md5sum| perl -MMIME::Base64 -ne 'print encode_base64($_)'|cut -b 1-4)
PASSWD=$(perl -MDigest::SHA1 -MMIME::Base64 -le '
$ctx = Digest::SHA1->new;
$ctx->add($ARGV[0]);
$ctx->add($ARGV[1]);
$hashedPasswd = "{SSHA}" . encode_base64($ctx->digest . $ARGV[1] ,"");
print $hashedPasswd . "\n";
' $(secret) ${SALT})
ldif_dump "userPassword" "${PASSWD}" >> ${LDIF}
if [ -z ${LDAP_USER} ];then
echo -n "Enter LDAP Administrator User Name: (just the uid) "
read LDAP_USER
fi
if [ -z ${LDAP_PASSWORD} ];then
echo -n "Enter LDAP Administrator Password: "
stty -echo
read LDAP_PASSWORD
stty echo
fi
############################################################################
# delete the record if it exits and install the new one
############################################################################
LDAP_URIS=($(dig +short -tsrv _ldap._tcp.$(dnsdomainname)|awk '{print "ldaps://"$4":"$3}'|sed -e 's/\.:/:/'))
RESULT=1; IDX=0;
while [ ${RESULT} -ne 0 -a ${IDX} -lt ${#LDAP_URIS[@]} ];do
echo "${LDAP_URIS[${IDX}]}"
ldapdelete -xH ${LDAP_URIS[${IDX}]} \
-D "uid=${LDAP_USER},ou=People,dc=$(dnsdomainname|sed -e 's/\./,dc=/g')" \
-w "${LDAP_PASSWORD}" "cn=$(hostname -s),ou=Hosts,dc=$(dnsdomainname|sed -e 's/\./,dc=/g')" && \
ldapadd -xH ${LDAP_URIS[${IDX}]} \
-D "uid=${LDAP_USER},ou=People,dc=$(dnsdomainname|sed -e 's/\./,dc=/g')" \
-w "${LDAP_PASSWORD}" \
-f ${LDIF}
RESULT=$?
IDX=`expr ${IDX} + 1`
done
cp ${LDIF} /root/$(hostname -s).ldif
chmod 600 /root/$(hostname -s).ldif
rm ${LDIF}
}
ldapmodify-sshpublickey(){
LDIF=$(mktemp /tmp/ldif.XXXX)
cat<<EOF>${LDIF}
dn: cn=$(hostname -s),ou=Hosts,dc=$(dnsdomainname|sed -e 's/\./,dc=/g')
changetype: modify
replace: sshPublicKey
EOF
# insert the id_dsa.pub
cat /root/.ssh/id_dsa.pub|while read LINE; do
ldif_dump "sshPublicKey" "${LINE}" >> ${LDIF}
done
LDAP_URIS=($(dig +short -tsrv _ldap._tcp.$(dnsdomainname)|sort -nr|awk '{print "ldaps://"$4":"$3}'|sed -e 's/\.:/:/'))
RESULT=1; IDX=0;
while [ ${RESULT} -ne 0 -a ${IDX} -lt ${#LDAP_URIS[@]} ];do
echo "${LDAP_URIS[${IDX}]}"
ldapmodify -xH ${LDAP_URIS[${IDX}]} \
-D "cn=$(hostname -s),ou=Hosts,dc=$(dnsdomainname|sed -e 's/\./,dc=/g')" \
-w "$(secret)" -f ${LDIF}
RESULT=$?
IDX=`expr ${IDX} + 1`
done
rm ${LDIF}
}
################################################################################
# main.c, yo #
################################################################################
####################################
# Some usage validation #
####################################
[ ${UID} -eq 0 ]||echo "Nononononoo. Be you root."
if [ $# -lt 1 ]; then
echo "not enough arguments"
usage
fi
DESIRED_FQDN=$1;
SUPPLIED_SECRET=$2;
echo "${DESIRED_FQDN}"|grep "\."
if [ $? -ne 0 ]; then usage; fi
hostname "${DESIRED_FQDN}"
####################################
# Get minimal facts about system #
####################################
HNAME=$(hostname -s)
FQDN=$(hostname -f)
# Assume the primary interface has the default route on it.
IFACE=$(route -n|awk -v e='0.0.0.0' '{if(($1==e)&&($2!=e)){print $NF;}}'|head -1)
IPADDR=$(ifconfig ${IFACE}|grep 'inet addr:'|cut -d: -f2|awk '{ print $1}')
if [ ${IPADDR} == "127.0.0.1" ];then
IPADDR=$(ifconfig | grep 'inet addr:'|cut -d: -f2|awk '{if($1!="127.0.0.1"){print $1}}'| head -1)
echo "this looks like openvz, so i'm re-guessing the public ip is ${IPADDR}"
fi
[ -z ${IFACE} ]&& ( echo "I cannot determine the public interface"; exit -1)
[ -z ${IPADDR} ]&& ( echo "I cannot determine my IP address"; exit -1)
echo "Using ${IPADDR} on ${IFACE} to contact the policy host."
####################################
# Try to determine the distribution
####################################
(apt-get install -y lsb-release || yum install -y redhat-lsb )>> ${LOG} 2>&1
DISTRO=$(lsb_release -i | sed -e 's/Distributor ID:[ \t]*//g')
####################################
# Set up configuration management
####################################
case "${DISTRO}" in
Debian)
echo "I appear to be running debian."
apt-get update >> ${LOG} 2>&1 && apt-get dist-upgrade -y >> ${LOG} 2>&1
[ -z $(which dig) ] && apt-get install -y dns-browse >> ${LOG} 2>&1
[ -z $(which git) ] && apt-get install -y git-core >> ${LOG} 2>&1
[ -z $(which ldapdelete) ] && apt-get install -y ldap-utils >> ${LOG} 2>&1
[ -z $(which puppet) ] && apt-get install -y puppet >> ${LOG} 2>&1
fix_etc_hosts "${DESIRED_FQDN}"
fix_etc_hostname
fix_etc_mailname
;;
CentOS|RedHatEnterpriseServer)
echo "I appear to be running redhat."
yum clean all -y
yum update -y
yum upgrade -y
[ -z $(which dig) ] && yum install -y bind-utils >> ${LOG} 2>&1
[ -z $(which puppet) ] && yum install -y puppet >> ${LOG} 2>&1
fix_etc_hosts
#fix_etc_sysconfig_network
;;
*)
echo "I don't appear to be running a disribution I support"
exit -2;
;;
esac
####################################
# Save the secret, bind to ldap #
####################################
if [ ! -z ${SUPPLIED_SECRET} ];then
# if we were supplied a secret,
# then that's our LDAP password
secret-init ${SUPPLIED_SECRET}
ldap.conf-init # create our ldap.conf
testldap > /dev/null || exit 1 # make sure it works or abort
# update our public key (for gitosis-admin/keydir)
ldapmodify-sshpublickey
else
# if we were NOT supplied a secret,
# then we create a random one
secret-init # generate a new random one
ldap.conf-init # create our ldap.conf
# update our new secret and our public key (for gitosis)
# since we were not provided a secret, LDAP Administrator's
# Credentials will be prompted for to write the record.
ldapadd-selfrecord
testldap > /dev/null || exit 1 # make sure it works or abort
fi
# Refresh the nameservice
/usr/sbin/nscd -i passwd; /usr/sbin/nscd -i group; /etc/init.d/nscd restart
# we need to trigger a run of regenerate_gitosis.conf here... but how?
# then we hand off the bootstrap to puppet
puppet_init
/usr/local/sbin/pupprun > /var/log/puppet/post-wcyd.log
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment