Differences between revisions 64 and 65
Revision 64 as of 2012-03-05 17:12:34
Size: 16530
Editor: ?PaulvanderVlis
Comment:
Revision 65 as of 2012-03-05 17:22:06
Size: 16415
Editor: ?PaulvanderVlis
Comment:
Deletions are marked like this. Additions are marked like this.
Line 399: Line 399:
Line 400: Line 401:
Line 405: Line 407:
echo -e "\nHOST: $HOST \nDOMAIN: $DOMAIN"
echo -e "SERVER: ${SERVER} \nREALM: $REALM \nLDAPROOT: $LDAPROOT"
Line 495: Line 495:

This will become a setup for NFS4 with Kerberos and secure LDAP on Debian Squeeze (it's not ready at the moment). Kerberos will use LDAP as backend database. Most information in this setup comes from Heiko Noordhof. I know, there are allready pages in this wiki about NFS4, Kerberos and LDAP. This howto tries to give an easy start. This setup is not very secure, but in many cases secure enough.

The idea is, that you copy/paste parts of the howto to your console.

Look out when you copy many lines, some commands (like "apt-get" and "read") will remove later lines from memory.

Server setup:

# become root:
su -

# When you did install LDAP or Kerberos or NFS before, it is a good idea to remove it to
# have a clean start. Backup it first if you want to keep it!
apt-get purge krb5-kdc-ldap gnutls-bin krb5-admin-server nfs-kernel-server \
  ldap-utils slapd krb5-kdc ssh rpl

rm -rv /var/lib/ldap/
rm -rv /etc/ldap/
rm -rv /etc/krb5kdc/
rm -rv /root/kerberos-setup/
rm -r /etc/krb5.keytab
rm -v /etc/krb5.conf
rm -v /etc/ssl/certs/CAself-cert.pem
rm -v /etc/ssl/certs/*_slapd_cert.pem
rm -v /etc/ssl/*.info
rm -v /etc/ssl/private/*_slapd_key.pem
rm -v /etc/ssl/private/CAself-key.pem

# Your fqdn-hostname should be OK, it should be something like:  server1.example.com
# When it's wrong, change your /etc/hosts, there should be a line like:
# 127.0.1.1       server1.example.com   server1
# with this command you can check your fqdn hostname:
hostname --fqdn

# Main setup variables defaults
SERVER=$(hostname --fqdn)   # something like: server1.example.com
DOMAIN=${SERVER#*.}         # something like: example.com
REALM=$(echo "${DOMAIN}" | tr '[:lower:]' '[:upper:]')   # something like: EXAMPLE.COM
LDAPROOT=""; IFS="."; for DC in $DOMAIN ; do LDAPROOT="${LDAPROOT},dc=$DC"; done
LDAPROOT="${LDAPROOT#,}"    # somthing like "dc=example,dc=com"
echo -e "\nSERVER:   $SERVER \nDOMAIN:   $DOMAIN \nREALM:    $REALM \nLDAPROOT: $LDAPROOT \n\
Change this defaults when needed with something like: DOMAIN='example2.com' \n"

# Install packages without questions. You can also answer the questions but this is
# pointless, because the configuration will be overwritten later.
# Some errors are normal because of the noninteractive install
DEBIAN_FRONTEND=noninteractive apt-get install ldap-utils slapd nfs-kernel-server \
  krb5-admin-server krb5-kdc krb5-kdc-ldap krb5-doc libnss-ldap nscd libpam-ldap \
  gnutls-bin ssl-cert ntp pwgen

# Directory for temporary setup files
SETUPDIR=/root/kerberos-setup/
mkdir "$SETUPDIR"
chmod 700 "$SETUPDIR"
cd "$SETUPDIR"

# Setup ldap.conf for clients
cat <<EOF >/etc/ldap/ldap.conf
BASE    ${LDAPROOT}
URI     ldapi://
EOF

# Setup SSL/TLS certificate (self-signed) for TLS on LDAP
CA_KEY=/etc/ssl/private/CAself-key.pem
CA_INFO=/etc/ssl/CAself.info
CA_CERT=/etc/ssl/certs/CAself-cert.pem
certtool --generate-privkey >"${CA_KEY}"
cat <<EOF >"${CA_INFO}"
cn = ${DOMAIN}
ca
cert_signing_key
EOF
certtool \
    --generate-self-signed \
    --load-privkey "${CA_KEY}" \
    --template "${CA_INFO}" \
    --outfile "${CA_CERT}"
chgrp ssl-cert "${CA_KEY}"
chmod 0640 "${CA_KEY}"

# Generate private-key for TLS on the LDAP-service
LDAP_TLS_KEY="/etc/ssl/private/${SERVER}_slapd_key.pem"
LDAP_TLS_INFO="/etc/ssl/${SERVER}.info"
LDAP_TLS_CERT="/etc/ssl/certs/${SERVER}_slapd_cert.pem"
certtool --generate-privkey >"${LDAP_TLS_KEY}"
cat <<EOF >"${LDAP_TLS_INFO}"
organization = ${DOMAIN}
cn = ${SERVER}
tls_www_server
encryption_key
signing_key
EOF
certtool \
    --generate-certificate \
    --load-privkey "${LDAP_TLS_KEY}" \
    --load-ca-certificate "${CA_CERT}" \
    --load-ca-privkey "${CA_KEY}" \
    --template "${LDAP_TLS_INFO}" \
    --outfile "${LDAP_TLS_CERT}"
chgrp ssl-cert "${LDAP_TLS_KEY}"
chmod 0640 "${LDAP_TLS_KEY}"

# Set access to ssl keys for LDAP-daemon (slapd)
adduser openldap ssl-cert

# Generate hash from admin password
LDAP_ADMIN_PW=$(pwgen -s 10 1)
echo -n "$LDAP_ADMIN_PW" >ldap-admin-pw.txt
chmod 600 ldap-admin-pw.txt
LDAP_ADMIN_HASH=$(slappasswd -h '{SHA}' -T ldap-admin-pw.txt)
touch passwords.txt; chmod 600 passwords.txt
echo "LDAP admin password: $LDAP_ADMIN_PW" >> passwords.txt

# Create ldifs and load them into LDAP
cat <<EOF >slapd-loglevel.ldif
dn: cn=config
changeType: modify
replace: olcLogLevel
olcLogLevel: stats
EOF
ldapmodify -v -Y EXTERNAL -H ldapi:/// -f slapd-loglevel.ldif

cat <<EOF >slapd-tls.ldif
dn: cn=config
changeType: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: ${CA_CERT}
-
add: olcTLSCertificateFile
olcTLSCertificateFile: ${LDAP_TLS_CERT}
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: ${LDAP_TLS_KEY}
EOF
ldapmodify -v -Y EXTERNAL -H ldapi:/// -f slapd-tls.ldif

cat <<EOF >slapd-database.ldif
dn: olcDatabase={1}hdb,cn=config
changeType: modify
replace: olcDbConfig
olcDbConfig: {0}set_cachesize 0 2097152 0
olcDbConfig: {1}set_lk_max_objects 1500
olcDbConfig: {2}set_lk_max_locks 1500
olcDbConfig: {3}set_lk_max_lockers 1500
olcDbConfig: {4}set_flags DB_LOG_AUTOREMOVE
-
replace: olcRootPW
olcRootPW: ${LDAP_ADMIN_HASH}
EOF
ldapmodify -v -Y EXTERNAL -H ldapi:/// -f slapd-database.ldif

# Do not listen on the clear-text port (389) only SSL/LDAPS (636)
sed -i 's|^SLAPD_SERVICES.*|SLAPD_SERVICES="ldaps:/// ldapi:///"|' /etc/default/slapd

# Restart LDAP-server
/etc/init.d/slapd restart

# Setup LDAP structure
# Generate random password for kerberos-admin account in LDAP, and a hash.
LDAP_KRBADMIN_PW=$(pwgen -s 12 1)
echo -n "$LDAP_KRBADMIN_PW" >ldap-krbadmin-pw.txt
chmod 600 ldap-krbadmin-pw.txt
LDAP_KRBADMIN_HASH=$(slappasswd -h '{SHA}' -T ldap-krbadmin-pw.txt)

cat <<EOF >structure.ldif
dn: cn=krb-admin,${LDAPROOT}
cn: krb-admin
objectClass: organizationalRole
objectClass: simpleSecurityObject
userPassword: ${LDAP_KRBADMIN_HASH}

dn: ou=groups,${LDAPROOT}
objectClass: organizationalUnit
ou: groups

dn: ou=users,${LDAPROOT}
objectClass: organizationalUnit
ou: users
EOF
ldapadd -x -D cn=admin,"${LDAPROOT}" -y ldap-admin-pw.txt -f structure.ldif

# Setup kerberos services, with backend database in LDAP
gunzip -c /usr/share/doc/krb5-kdc-ldap/kerberos.schema.gz >krb.schema
echo 'include krb.schema' >slapd.tmp.conf
slaptest -f slapd.tmp.conf -F ./
mv  'cn=config/cn=schema/cn={0}krb.ldif' krb.schema.ldif
sed -i 's/^dn: cn={0}krb/dn: cn=kerberos,cn=schema,cn=config/' krb.schema.ldif
sed -i 's/^cn: {0}krb/cn: kerberos/' krb.schema.ldif
sed -i '/^structuralObjectClass/,$d' krb.schema.ldif
ldapadd -QY EXTERNAL -H ldapi:///  -f krb.schema.ldif

# Add index
cat <<EOF >krbindex.ldif
dn: olcDatabase={1}hdb,cn=config
add: olcDbIndex
olcDbIndex: krbPrincipalName eq,pres,sub
EOF
ldapmodify -v -Y EXTERNAL -H ldapi:/// -f krbindex.ldif

# Add some ACL's
cat <<EOF >krbacl.ldif
dn: olcDatabase={1}hdb,cn=config
replace: olcAccess
olcAccess: to attrs=userPassword,shadowLastChange,krbPrincipalKey by dn="cn=krb-admin,${LDAPROOT}" write by anonymous auth by self write by * none
-
add: olcAccess
olcAccess: to dn.base="" by * read
-
add: olcAccess
olcAccess: to * by dn="cn=krb-admin,${LDAPROOT}" write by * read
EOF
ldapmodify -v -Y EXTERNAL -H ldapi:/// -f krbacl.ldif

# Setup MIT-kerberos
cp /etc/krb5.conf /etc/krb5.conf.bak-$(date +%Y%m%d_%H%M)
cat <<EOF >/etc/krb5.conf
[libdefaults]
        default_realm = ${REALM}
        allow_weak_crypto = true
        default_tgs_enctypes = des-cbc-crc
        default_tkt_enctypes = des-cbc-crc
        permitted_enctypes = des-cbc-crc

        krb4_config = /etc/krb.conf
        krb4_realms = /etc/krb.realms
        kdc_timesync = 1
        ccache_type = 4
        forwardable = true
        proxiable = true

[realms]
        ${REALM} = {
                kdc = ${SERVER}
                admin_server = ${SERVER}
                default_domain = ${DOMAIN}
                database_module = openldap_ldapconf
        }

[domain_realm]
        .${DOMAIN} = ${REALM}

[login]
        krb4_convert = true
        krb4_get_tickets = false

[logging]
     kdc = SYSLOG:INFO:DAEMON
     admin_server = SYSLOG:INFO:DAEMON
     default = SYSLOG:INFO:DAEMON

[dbdefaults]
        ldap_kerberos_container_dn = ${LDAPROOT}

[dbmodules]
        openldap_ldapconf = {
                db_library = kldap
                ldap_kdc_dn = "cn=krb-admin,${LDAPROOT}"
                ldap_kadmind_dn = "cn=krb-admin,${LDAPROOT}"
                ldap_service_password_file = /etc/krb5kdc/service.keyfile
                ldap_servers = ldapi:///
                ldap_conns_per_server = 5
EOF

# ACL to grant all permissions to principals like "<name>/admin@<REALM>"
echo '*/admin *' >>/etc/krb5kdc/kadm5.acl

# Ask for password for kerberos LDAP backend
KLDAPPWD=`pwgen -s 10 1`
read -p "Password for Kerberos LDAP backend, specify a password (return='$KLDAPPWD') : " KLDAPPW

if test "$KLDAPPW" = ""; then KLDAPPW="$KLDAPPWD"; fi
echo "$KLDAPPW" > $SETUPDIR/kerberos-ldap-password.txt
echo "Kerberos LDAP password: $KLDAPPW" >> passwords.txt

# Create basic entries in the kerberos LDAP backend
echo -e "You will now be asked to enter the password (twice). \n
Please copy and paste the password, it is: $KLDAPPW\n"

kdb5_ldap_util -w "$LDAP_KRBADMIN_PW" \
    -D  "cn=krb-admin,$LDAPROOT" \
    create \
    -subtrees "$LDAPROOT" \
    -r "$REALM" \
    -s \
    -H ldapi:///

# Stash the LDAP-password for the account the kerberos daemons use to
# read and write to LDAP
echo -e "You will now be asked to enter another password (twice). \n
Please copy/paste the following password in there:  $LDAP_KRBADMIN_PW\n"

kdb5_ldap_util -w "$LDAP_KRBADMIN_PW" \
    -D  "cn=krb-admin,$LDAPROOT" \
    stashsrvpw \
    -f /etc/krb5kdc/service.keyfile \
    "cn=krb-admin,$LDAPROOT"

# Restart the Kerberos daemons
/etc/init.d/krb5-kdc restart  
/etc/init.d/krb5-admin-server restart

# kerberos admin user:
read -p "Kerberos admin username, normally your name (without '/admin'): " KADMIN

echo "kerberos admin username: $KADMIN/admin" >> passwords.txt
KADMINPWD=`pwgen -s 10 1`
read -p "Password for Kerberos admin user, specify a password (return='$KADMINPWD') : " KADMINPW

if test "$KADMINPW" = ""; then KADMINPW="$KADMINPWD"; fi
echo "kerberos admin paswword: $KADMINPW" >> passwords.txt
kadmin.local -q "addprinc -pw $KADMINPW $KADMIN/admin"

# The NFS-server must know the same user names and UID's as the clients.
# Therefore our server name service switch needs to be a client of the server itself.
cp /etc/libnss-ldap.conf /etc/libnss-ldap.conf -$(date +%Y%m%d_%H%M)
cat <<EOF >/etc/libnss-ldap.conf
uri ldapi://
ldap_version 3
base ${LDAPROOT}
scope sub
EOF

# Activate LDAP in name service switch
sed -i 's/compat/files ldap/' /etc/nsswitch.conf
/etc/init.d/nscd restart

# Setup NFS4-service
# ==> Security level "krb5i" is middle level. More secure (everything encrypted)
# would be: "krb5p". This must match mount option on the client.
mkdir -p /srv/nfs4/home
echo "/srv/nfs4 *.${DOMAIN}(rw,sync,sec=krb5i,fsid=0,crossmnt,no_subtree_check) " >> /etc/exports
echo "/srv/nfs4/home *.${DOMAIN}(rw,sync,sec=krb5i,no_subtree_check) " >> /etc/exports

# Create kerberos principal for NFS-server
kadmin.local -q "addprinc -randkey nfs/${SERVER}"

# Store the key for the nfs-service principal in (default) keytab file
kadmin.local -q "ktadd nfs/${SERVER}"

# Configure NFS-service daemons for kerberized NFS4:
sed -i 's/^ *NEED_SVCGSSD=.*$/NEED_SVCGSSD=yes/' /etc/default/nfs-kernel-server
sed -i 's/^ *NEED_IDMAPD=.*$/NEED_IDMAPD=yes/' /etc/default/nfs-common

# Restart the NFS4 (related) services
/etc/init.d/nfs-kernel-server stop
/etc/init.d/nfs-common restart
/etc/init.d/nfs-kernel-server start

# Download and install some usefull scripts in /usr/local/sbin/
# maybe take a look first in http://vandervlis.nl/krb5/
mkdir scripts; cd scripts
wget -qr -nd --no-parent http://vandervlis.nl/krb5/
rm index.html*
rpl "dc=example,dc=com" "$LDAPROOT" variables
rpl "secret" "$LDAP_ADMIN_PW" variables
chmod +x *
chmod 600 variables uid guid
cp -a * /usr/local/sbin/
cd $SETUPDIR

# Test creating users
au jan25  # creates a user "jan25" in Kerberos and LDAP
getent passwd jan25   # check if the user excists
ru jan25  # removes the test user

# Add a real user and an machine account
au   # add user
ama  # add machine account

# Give information about the setup on the screen:
echo -e "\nSave this information on a good place:\n
==> LDAP root:                ${LDAPROOT}
==> LDAP super-user account:  cn=admin,${LDAPROOT}
==> LDAP super-user password: ${LDAP_ADMIN_PW}
==> Kerberos realm:           ${REALM}
==> Kerberos LDAP password:   $KLDAPPW
==> Kerberos admin username:  $KADMIN/admin
==> Kerberos admin paswword:  $KADMINPW \n"

The setupdir contains all passwords among other things. Please make sure to remove this directory later.

Client setup (not well tested):

# become root:
su -

# Your fqdn-hostname should be OK, it should be something like:  server1.example.com
# When it's wrong, change your /etc/hosts, there should be a line like:
# 127.0.1.1       pc1.example.com   pc1
# with this command you can check your fqdn hostname:
hostname --fqdn

# First set variables, and ask for some
read -p "Server with Kerberos and LDAP, something like 'server.example.com' : " SERVER

read -p "Admin username on the server, something like 'john' : " ADMIN

HOST=$(hostname --fqdn)
DOMAIN=${HOST#*.}
REALM=$(echo "${DOMAIN}" | tr '[:lower:]' '[:upper:]')
LDAPROOT=""; IFS="."; for DC in $DOMAIN ; do LDAPROOT="${LDAPROOT},dc=$DC"; done
LDAPROOT="${LDAPROOT#,}"

# Install some packages
apt-get install ntp libnss-ldap nscd krb5-user krb5-doc libpam-krb5 nfs-common ca-certificates

# Increase minimal UID in for kerberos accounts accepted by PAM
sed -i '/[^#].*pam_krb5/s/minimum_uid=1000/minimum_uid=2000/' \
    common-auth common-session common-password common-account

# Configure LDAP
cat <<EOF >/etc/ldap/ldap.conf
BASE ${LDAPROOT}
URI ldaps://${SERVER}
TLS_CACERT /etc/ssl/certs/CAself-cert.pem
TLS_REQCERT demand
EOF

# Copy /etc/ssl/certs/CAself-cert.pem from the server to the client
# in the same directory, e.g. if you have an account on the server.
# (there no real need to do this in a secure way)
scp $ADMIN@"${SERVER}:/etc/ssl/certs/CAself-cert.pem /etc/ssl/certs

# configure name service switch
cat <<EOF >/etc/libnss-ldap.conf
base ${LDAPROOT}
uri ldaps://${SERVER}
ldap_version 3
scope sub
EOF

# Configure kerberos
cat <<EOF >/etc/krb5.conf
[libdefaults]
        default_realm = ${REALM}
        allow_weak_crypto = true
        krb4_config = /etc/krb.conf
        krb4_realms = /etc/krb.realms
        kdc_timesync = 1
        ccache_type = 4
        forwardable = true
        proxiable = true

[realms]
        $REALM = {
                kdc = ${SERVER}
                admin_server = ${SERVER}
        }

[domain_realm]
        .$DOMAIN = ${REALM}

[login]
        krb4_convert = true
        krb4_get_tickets = false

[logging]
     kdc = SYSLOG:INFO:DAEMON
     admin_server = SYSLOG:INFO:DAEMON
     default = SYSLOG:INFO:DAEMON[logging]
EOF

# Download the machine-key to /etc/krb5.keytab
kadmin -p $ADMIN/admin -q "ktadd nfs/client.domain"

# configure the NFS init script for the daemons
sed -i 's/^ *NEED_GSSD=.*$/NEED_GSSD=yes/' /etc/default/nfs-common
sed -i 's/^ *NEED_IDMAPD=.*$/NEED_IDMAPD=yes/' /etc/default/nfs-common
echo 'RPCGSSDOPTS="-vv"' >>/etc/default/nfs-common
/etc/init.d/nfs-common restart

echo "$SERVER:/home /home nfs4 -o rw,sec=krb5i,auto 0 0" >>/etc/fstab
mount -a

What to do when you don't want that the person who install's the client has an admin account on the server? Or when you don't want ssh access on the server?

# On the server you can do this to get the key of a machine
kadmin.local -q "ktadd -k nfs-pc1.example.com.keytab"
# You have to find a secure way to bring the file to the client-machine.

# On the client you can do this to to copy the key to the right place:
mv nfs-pc1.example.com.keytab /etc/krb5.keytab
chmod 0600 /etc/krb5.keytab

# You can publish your certificate on a website. You can download it, and copy it to the right location
wget www.example.com/CAself-cert.pem
mv CAself-cert.pem /etc/ssl/certs/