Stories from the life of a Windows domain:
Do you know the password of the Linux host-A? Im not quite sure, maybe it is "init" - "password" - "barack".
Isn't it stupid that you are guessing the passwords every time you want to connect to a linux server within a Windows domain?
Wouldn't it be pretty cool if domain users can authenticate to your Linux server with their domain credentials?
No more password guessing, password excel sheets or crypted databases!
I'll show you how to do that with keytab and a little script written by my own.
You can join the domain and configure everything without using a keytab, but manually entering the password is irritating.
First of all, we need to create the keytab file. We need the key version number of the domain account you want to use for
keytab credentials. Everytime you change the domain password of an user, the key version number is incremented. To find out your
current number you can use ADSIEdit or ldapsearch:
$ ldapsearch -x -h DOMAINSERVER.LOCAL.LAN -D 'DOMAINUSER@local.lan' -W -b 'dc=local,dc=lan' '(sAMAccountName=DOMAINUSER)' msDS-KeyVersionNumber
# msDS-KeyVersionNumber: 2
Key version number is 2. Now we can create the keytab by using ktutil:
$ ktutil
ktutil: addent -password -p DOMAINUSER@LOCAL.LAN -k 2 -e RC4-HMAC
Password for DOMAINUSER@LOCAL.LAN: <enter the password>
ktutil: wkt /etc/krb5.keytab.DOMAINUSER
ktutil: q
After we created the keytab, we can check the file with klist:
$ klist -k -t /etc/krb5.keytab.DOMAINUSER
Keytab name: FILE:/etc/krb5.keytab.DOMAINUSER
KVNO Timestamp Principal
---- ------------------- ------------------------------------------------------
1 02.10.2015 12:16:34 DOMAINUSER@LOCAL.LAN
The keytab file is ready to use. We need to store this keytab file in a central location, where it can be downloaded really easily.
We use our mecurial repository for storing the domain join keytab file.
You can now download this little script and change the line 212:
212: wget <LINK-TO-YOUR-KEYTAB-FILE> --> insert the url, where your keytab is stored.
Show Script
#!/bin/bash
### BEGIN INIT INFO
# Provides: linux-ad-join-and-auth.sh
# Short-Description: Automatically joins a Windows AD-Domain and authenticating windows domain users on linux servers
# Author: Kai Wagner <kai@openattic.org>
# Date: 02.10.2015
# Tested: Working with Ubuntu 14.04 and Debian Jessie 8.0
### END INIT INFO
function usage
{
echo "usage: please insert -h | --help for more informations"
}
function help
{
echo "This little script automatically joins a windows ad-domain and configure authentication against linux servers"
echo ""
echo "-D | --domain # Enter your Domainname ex. LOCAL.LAN"
echo "-H | --hostname # Enter your Hostname - not FQDN!"
echo "-W | --workgroup # Enter your WORKGROUP ex. LOCAL"
echo "-G | --groups # Enter your AD-Groups which are allowed to connect to the server -
ex. -G \"Domain Admins\" -G \"Domain Users\" - quotation marks needed
You can add multiple groups at once by seperated -G"
echo ""
}
##### Main
counter=0
if [ "$1" = "-h" ] || [ "$1" = "--help" ] || [ "$1" = "" ];
then
help
exit 1
else
while [ "$1" != "" ]; do
case $1 in
-D | --domain ) shift
DOMAIN=$1
;;
-H | --hostname ) shift
HOSTNAME=$1
;;
-W | --workgroup ) shift
WORKGROUP=$1
;;
-G | --groups ) shift
DOMAINGROUPS[counter]="$1"
counter=$[$counter+1]
;;
esac
shift
done
fi
if [ "$HOSTNAME" = "" ] || [ "$DOMAIN" = "" ] || [ "$WORKGROUP" = "" ] || [ "$DOMAINGROUPS" = "" ]
then
echo "Something missing!"
echo "Please specify Hostname, Domain, Workgroup and Groupnames"
echo ""
exit 1
fi
HOSTNAME_UPPER=`echo $HOSTNAME | tr '[:lower:]' '[:upper:]'`
DOMAIN_LOWER=`echo $DOMAIN | tr '[:upper:]' '[:lower:]'`
DOMAIN_UPPER=`echo $DOMAIN | tr '[:lower:]' '[:upper:]'`
echo $HOSTNAME > /etc/hostname
echo "127.0.0.1 localhost
127.0.1.1 $HOSTNAME.$DOMAIN $HOSTNAME
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters" > /etc/hosts
echo "krb5-config krb5-config/add_servers boolean true
krb5-config krb5-config/kerberos_servers string
krb5-config krb5-config/read_conf boolean true
krb5-config krb5-config/default_realm string OADEV.MASTER.DNS
krb5-config krb5-config/admin_server string
libpam-runtime libpam-runtime/profiles multiselect krb5, unix, winbind, systemd, capability
krb5-config krb5-config/add_servers_realm string OADEV.MASTER.DNS" | debconf-set-selections
apt-get install -y samba winbind libnss-winbind krb5-user sudo libpam-krb5 libpam-winbind debconf-utils
rm -f /etc/krb5.conf
echo "[libdefaults]
default_realm = $DOMAIN_UPPER
default_keytab_name = /etc/krb5.keytab
default_tkt_enctypes = rc4-hmac des-cbc-crc des-cbc-md5
default_tgs_enctypes = rc4-hmac des-cbc-crc des-cbc-md5
[domain_realm]
.$DOMAIN_LOWER = $DOMAIN_UPPER
$DOMAIN_LOWER = $DOMAIN_UPPER" > /etc/krb5.conf
rm -f /etc/samba/smb.conf
echo "[global]
netbios name = $HOSTNAME
workgroup = $WORKGROUP
realm = $DOMAIN
security = ADS
encrypt passwords = yes
# Load the acl_xattr module for Windows ACL support
vfs objects = shadow_copy2 acl_xattr
# Use an external keytab that can be used for other services (e.g. apache)
kerberos method = dedicated keytab
dedicated keytab file = /etc/krb5.keytab
idmap config *:backend = tdb
idmap config *:range = 1000000-1999999
# Make sure we have reproducible user IDs
idmap config $DOMAIN_UPPER:backend = rid
idmap config $DOMAIN_UPPER:range = 10000-999999
winbind cache time = 30
winbind refresh tickets = yes
winbind nss info = rfc2307
winbind trusted domains only = no
winbind use default domain = yes
# should "getent passwd" and "getent group" list *all* AD users/groups?
winbind enum users = yes
winbind enum groups = yes
# Default shell that users get (/bin/true = no login)
template shell = /bin/bash
template homedir = /home/%D/%U" > /etc/samba/smb.conf
rm -f /etc/krb5.keytab
cd /etc/
wget <LINK-TO-YOUR-KEYTAB-FILE>
hostname $HOSTNAME
kinit logonadm -k -t /etc/krb5.keytab.logonadm
net ads -k join
net ads -k keytab add HTTP
net ads -k keytab add HTTPS
net ads -k keytab add NFS
net ads -k keytab add SSH
kdestroy
kinit -k $HOSTNAME_UPPER$
echo "# /etc/nsswitch.conf
#
# Example configuration of GNU Name Service Switch functionality.
# If you have the "glibc-doc-reference" and "info" packages installed, try:
# info libc "Name Service Switch" for information about this file.
passwd: compat winbind
group: compat winbind
shadow: compat
gshadow: files
hosts: files dns
networks: files
protocols: db files
services: db files
ethers: db files
rpc: db files
netgroup: nis" > /etc/nsswitch.conf
pam-auth-update --package --force
echo "#
# /etc/pam.d/common-auth - authentication settings common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of the authentication modules that define
# the central authentication scheme for use on the system
# (e.g., /etc/shadow, LDAP, Kerberos, etc.). The default is to use the
# traditional Unix authentication mechanisms.
#
# As of pam 1.0.1-6, this file is managed by pam-auth-update by default.
# To take advantage of this, it is recommended that you configure any
# local modules either before or after the default block, and use
# pam-auth-update to manage selection of other modules. See
# pam-auth-update(8) for details.
# here are the per-package modules (the "Primary" block)
auth [success=3 default=ignore] pam_krb5.so minimum_uid=1000
auth [success=2 default=ignore] pam_unix.so nullok_secure try_first_pass
auth [success=1 default=ignore] pam_winbind.so krb5_auth krb5_ccache_type=FILE cached_login try_first_pass
# heres the fallback if no module succeeds
auth requisite pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
auth required pam_permit.so
# and here are more per-package modules (the "Additional" block)
# end of pam-auth-update config" > /etc/pam.d/common-auth
for item in `seq 0 "$((${#DOMAINGROUPS[*]} - 1))"`
do
stringsession="session sufficient pam_succeed_if.so debug user ingroup [${DOMAINGROUPS[$item]}]\n$stringsession"
done
echo -e "#
# /etc/pam.d/common-session - session-related modules common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of modules that define tasks to be performed
# at the start and end of sessions of *any* kind (both interactive and
# non-interactive).
#
# As of pam 1.0.1-6, this file is managed by pam-auth-update by default.
# To take advantage of this, it is recommended that you configure any
# local modules either before or after the default block, and use
# pam-auth-update to manage selection of other modules. See
# pam-auth-update(8) for details.
# here are the per-package modules (the "Primary" block)
session [default=1] pam_permit.so
# here's the fallback if no module succeeds
session requisite pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
session required pam_permit.so
# and here are more per-package modules (the "Additional" block)
session optional pam_krb5.so minimum_uid=1000
session required pam_unix.so
session optional pam_winbind.so
# end of pam-auth-update config
# always allow root
session [success=1 default=ignore] pam_succeed_if.so debug uid = 0
# other users only if members of the given groups (resolved through winbind)
$stringsession
session required pam_deny.so" > /etc/pam.d/common-session
echo "#
# /etc/pam.d/common-account - authorization settings common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of the authorization modules that define
# the central access policy for use on the system. The default is to
# only deny service to users whose accounts are expired in /etc/shadow.
#
# As of pam 1.0.1-6, this file is managed by pam-auth-update by default.
# To take advantage of this, it is recommended that you configure any
# local modules either before or after the default block, and use
# pam-auth-update to manage selection of other modules. See
# pam-auth-update(8) for details.
#
# here are the per-package modules (the "Primary" block)
account [success=2 new_authtok_reqd=done default=ignore] pam_unix.so
account [success=1 new_authtok_reqd=done default=ignore] pam_winbind.so
# here's the fallback if no module succeeds
account requisite pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
account required pam_permit.so
# and here are more per-package modules (the "Additional" block)
account required pam_krb5.so minimum_uid=1000
# end of pam-auth-update config
session required pam_mkhomedir.so skel=/etc/skel/ umask=0022" > /etc/pam.d/common-account
for item in `seq 0 "$((${#DOMAINGROUPS[*]} - 1))"`
do
string="\"%${DOMAINGROUPS[$item]}\" ALL=(ALL:ALL) NOPASSWD: ALL \n$string"
done
echo -e "$string" > /etc/sudoers.d/domainuser
mkdir /home/$WORKGROUP
service smbd restart
service nmbd restart
service winbind restart
echo "#######################"
echo "Done - Have a nice day!"
echo "#######################"
When it's done, you can start joining your domain, by using the ./script.sh.
The needed parameters are:
echo "-D | --domain # Enter your Domainname ex. LOCAL.LAN"
echo "-H | --hostname # Enter your Hostname - not FQDN!"
echo "-W | --workgroup # Enter your WORKGROUP ex. LOCAL"
echo "-G | --groups # Enter your AD-Groups which are allowed to connect to the server -
ex. -G \"Domain Admins\" -G \"Domain Users\" - quotation marks needed
You can add multiple groups at once by seperated -G"
Example:
./script.sh -D LOCAL.LAN -H DOMAINSERVER.LOCAL.LAN -W LOCAL -G "Domain Admins" -G "Linuxadmins"
You can now authenticate to your linux servers by using your windows ad credentials.
Just add your users to the needed or wanted groups and your done.
Next and missing step is a NFS-shared Home-Directory which is automatically mounted, when you connect to
a linux server. To be continued...
Special thanks and greetings to Svedrin.
Comments
Comments powered by Disqus