From Bob Brandt's Projects Site

SLED: Custom setup for Novell Account Management

Novell Account Management (NAM) is very simply a method of using eDirectory as the authentication source for all your corporate sources. (i.e. NT, Active Directory, Unix, Linux AS/400 systems would all look to eDirectory for username/password queries.) This is ideal as each individual would have only one username and password to maintain.

Specifically with Linux, Novell uses the terminology Linux User Management (LUM), however this encompasses more than just usernames and password. Because Linux systems use UIDs and GIDs to identify users and groups, eDirectory users and groups must be made Posix enabled (i.e. given a unique number and group assignment). Also, Novell uses a model similar to the Microsoft Domain method, where it creates an object for the workstation/server in eDirectory to control you has access to this device. Groups are associated with the workstation object and if a user is a member of one of those groups, he is allowed to access the workstation. On the workstation side of things, a PAM (Pluggable Authentication Module) is created that reads its workstation object details from eDirectory and determines whether a user is allowed access or not. There is a YaST module that is suppose to create the eDirectory Object and setup the PAM on the workstation, but it has some bugs. So to fix this, I created this script (/sbin/namsetup) which I install via RPM during the initial installation the workstation.

Enabled eDirectory Users (LUM) LUM allows eDirectory users to log into the SLED workstation as if they were installed on the local workstation. A workstation object is created is created in eDirectory controling access to the workstation.

There is a YaST module that is suppose to do this with a nice GUI, but for some reason it doesn't work. So I created a custom script that will perform all the heavy lifting for you.

To start the process, type in the command as root

username-sled10:~ # namsetup

Enter in the requested information and select the context of the user.

After the script runs successfully, a new object will be created in the eDirectory tree in the context you specified above.

Before eDirectory users can login, they need to be associated with this workstation. How this is done is beyond the purpose of this document, but once a user is associated with a workstation, they will be able to login using their eDirectory username and password.

To test that it is working, use the command id username (i.e. id networkusername)

/sbin/namsetup
#!/bin/bash
##############################################################################
##############################################################################
#                                                                            #
# namsetup                                                                   #
#                                                                            #
# Author: Bob Brandt projects@brandt.ie                                      #
#                                                                            #
# This program was created to help administrators setup LUM on workstations. #
#  Although I have been unable to get LUM to work by using the YaST2 LUM     #
#  compoment, I found a Novell TID (3994289) which describes how to setup    #
#  LUM on SLED10 workstation.  In this TID it explains how to modify text    #
#  files directly, a task I definitely don't want my junior Administrators   #
#  performing.                                                               #
#                                                                            #
# Comments can be used but must be preceeded by a hash symbol (#)            #
# All Comments are to be preceded by a hash symbol (#) (Maximum of 78 chars) #
#                                                                            #
##############################################################################
##############################################################################

# Set the defaults
defaultLinuxConfigContext=${defaultLinuxConfigContext:-""}
defaultSSLPort=${defaultSSLPort:-"636"}
defaultLDAPServer=${defaultLDAPServer:-"ldap:389"}
defaultBackupServer=${defaultBackupServer:-"ldap1:389,ldap2:389,ldap3:389"}
defaultAdminUser=${defaultAdminUser:-"admin"}
defaultWorkstationContext=${defaultWorkstationContext:-""}
version="0.5.1"


##############################################################################
# Below is the code responsible for producing a Selection menu               #
##############################################################################
function browseldap 
{
	current=$1
	parent=`echo $current | sed 's|^[^,]*,||'`
	if [ "$current" == "$parent" ]; then
		parent=""
	fi
	filter="(|(objectClass=organization)(objectClass=organizationalUnit)(objectClass=country)(objectClass=locality))"

	if [ -n "$current" ]; then
		currentcontext="\n(Current Context is $current)"
	else
		currentcontext=""
	fi


	echo -e "\nSelect the Workstation context in LDAP syntax.$currentcontext"
	declare -a array
	declare -i i=0

	for context in $(ldapsearch -h "$LDAPServer" -b "$current" -x -s one -S dn "$filter" dn | grep "^dn:" | sed 's|^dn: ||'g);
	do
		array[i++]="$context"
	done



	PS3="Workstation context: "
	if [ -n "$current" ]; then
		if [ -n "$parent" ]; then
			select context in "Manually Enter Context" "Select Current Context" "$parent" ${array[*]} ;
			do
				test "$context" && break
			done
		else
			select context in "Manually Enter Context" "Select Current Context" ${array[*]} ;
			do
				test "$context" && break
			done
		fi
	else
		select context in "Manually Enter Context" ${array[*]} ;
		do
			test "$context" && break
		done
	fi

	case "$context" in
		"Manually Enter Context" ) WorkstationContext="" && return ;;
		"Select Current Context" ) WorkstationContext="$current" && return ;;
		*  ) browseldap "$context"
	esac
}


##############################################################################
# Below is the code responsible for Redirecting Linux authentication to      #
#  eDirectory using LUM                                                      #
##############################################################################
function run_namconfig
{
	echo -e "\n\nDo you wish to continue with this information?"
	echo -e "Primary LDAP Server \t\t= $LDAPServer"
	echo -e "Secondary Backup LDAP Servers \t= $BackupServer"
	echo -e "Admin User \t\t\t= $AdminUser"
	echo -e "Linux Config Context \t\t= $LinuxConfigContext"
	echo -e "Workstation Context \t\t= $WorkstationContext"
	echo -e "SSL Port \t\t\t= $SSLPort"
	echo -e -n "(Yes/No): "
	read answer
	if echo ${answer:0:1} | grep -i "y" > /dev/null ;
	then
		if [ -n "$AdminPassword" ]; then
			AdminPassword="-p $AdminPassword"
		fi
		if [ -n "$BackupServer" ]; then
			BackupServer="-R $BackupServer"
		fi
		if [ -n "$SSLPort" ]; then
			SSLPort="-l $SSLPort"
		fi
		namconfig add -a "$AdminUser" "$AdminPassword" -r "$LinuxConfigContext" -w "$WorkstationContext" "$SSLPort" -S "$LDAPServer" "$BackupServer"
		return $?
	else
		return 3
	fi
}


##############################################################################
# Below is the code responsible for modifing the /etc/nsswitch.conf file     #
##############################################################################
function modify_nsswitch
{
	if [ -e /etc/nsswitch.conf.nam ]; then
		mv -v /etc/nsswitch.conf /etc/nsswitch.conf.nam.bkp
		cp -v /etc/nsswitch.conf.nam /etc/nsswitch.conf
	fi
}


##############################################################################
# Below is the code responsible for modifing the /etc/pam.d files            #
##############################################################################
function modify_pamd
{
	mv -v /etc/pam.d/common-account /etc/pam.d/common-account.nam
	grep -v "pam_nam.so" /etc/pam.d/common-account.nam > /etc/pam.d/common-account
	echo -e "account\trequired\tpam_nam.so\tuse_first_pass" >> /etc/pam.d/common-account
	echo "'/etc/pam.d/common-account' modified for nam"

	mv -v /etc/pam.d/common-password /etc/pam.d/common-password.nam
	grep -v "pam_nam.so" /etc/pam.d/common-password.nam > /etc/pam.d/common-password
	echo -e "password\trequired\tpam_nam.so\ttry_first_pass" >> /etc/pam.d/common-password
	echo "'/etc/pam.d/common-password' modified for nam"

	mv -v /etc/pam.d/common-session /etc/pam.d/common-session.nam
	grep -v "pam_nam.so" /etc/pam.d/common-session.nam > /etc/pam.d/common-session
	echo -e "session\toptional\tpam_nam.so" >> /etc/pam.d/common-session
	echo "'/etc/pam.d/common-session' modified for nam"
}


##############################################################################
# Below is the code responsible for modifing the pam_unix2.conf file         #
##############################################################################
function modify_pam_unix2
{
	mv -v /etc/security/pam_unix2.conf /etc/security/pam_unix2.conf.nambkp
	grep -v "call_modules=nam" /etc/security/pam_unix2.conf.nambkp > /etc/security/pam_unix2.conf
	echo "auth:           call_modules=nam" >> /etc/security/pam_unix2.conf
	echo "'/etc/security/pam_unix2.conf' modified for nam"
}


##############################################################################
# Below is the code responsible for running the LUM cache deamon (namcd)     #
#  instead of the name server cache deamon (nscd)                            #
##############################################################################

function start_namcd
{
	chkconfig ncsd off
	chkconfig namcd on
	rcnscd stop
	rcnamcd restart
}


##############################################################################
# Below is the code responsible for displaying the help screen.              #
##############################################################################
function display_help
{
	echo -e "\n    ${0##*/} [Options]\n"
	echo -e "    Options:"
	echo -e "     -r | --config-context = The LDAP context of the Linux/Unix config object"
	echo -e "                             that contains the list of workstation contexts."
	echo -e "     -w | --context        = The LDAP format, the context where the server or"
	echo -e "                             workstation object will be created."
	echo -e "     -l | --ssl-port       = LDAP SSL port to be used. (636 is default)"
	echo -e "     -S | --ldap-server    = The preferred LDAP eDirectory server to be used."
	echo -e "                             Can be specified by IP address or DNS name."
	echo -e "     -R | --backup-server  = A comma-separated list of other LDAP servers. Can"
	echo -e "                             be specified by IP address or DNS name."
	echo -e "     -a | --admin-user     = The fully qualified LDAP administrator's username."
	echo -e "     -p | --admin-password = The administrators password."
	echo -e "     -c | --cache          = Refresh the NAM Cache."
	echo -e "     -k | --ssl-key        = Import the SSL certificate file into the workstation."
	echo -e "     -h, --help            = show this help"
	echo -e "     -v, --version         = output version\n"

	exit 0
}


##############################################################################
# Below is the code responsible for displaying the version screen.           #
##############################################################################
function display_version
{
	echo -e "\nGNU ${0##*/} $version\n"
	echo -e "This program is distributed in the hope that it will be useful,"
	echo -e "but WITHOUT ANY WARRANTY; without even the implied warranty of"
	echo -e "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the"
	echo -e "GNU General Public License for more details.\n"
	echo -e "Originally written by Bob Brandt <projects@brandt.ie>.\n"
	exit 0
}


##############################################################################
# Below is the main code of the script                                       #
##############################################################################


# Process all the parameters.  Since we do not know what order the parameters will 
#  be given, we need to process all the parameters before we act upon them.
while [ "$1" != "" ]; do
	case "$1" in
		"-r" |"--config-context" )
			shift
			LinuxConfigContext="$1"
		;;
		"-w" | "--context" )
			shift
			WorkstationContext="$1"
		;;
		"-l" | "--ssl-port" )
			shift
			SSLPort="$1"
		;;
		"-S" | "--ldap-server" )
			shift
			LDAPServer="$1"
		;;
		"-R" | "--backup-server" )
			shift
			BackupServer="$1"
		;;
		"-a" | "--admin-user" )
			shift
			AdminUser="$1"
		;;
		"-p" | "--admin-password" )
			shift
			AdminPassword="$1"
		;;
		"-k" | "--ssl-key" )
			namconfig -k
			exit $?
		;;
		"-c" | "--cache" | "--refresh" | "cache_refresh" )
			namconfig cache_refresh
			exit $?
		;;

		"/?" | "/h" | "-?" | "-h" | "--help" )
			display_help
			exit 0
		;;
		"/v" | "-v" | "--version" )
			display_version
			exit 0
		;;
		* )
			echo "Options Error: option $1 not recognized."
			display_help
			exit 1
		;;
	esac
	shift
done


# Make sure the user is root
if ! [ "`id -u`" == "0" ]; then
	echo "You must be root to run this script!" && exit 1
fi

if ! [ -x "/usr/bin/namconfig" ]; then
	echo "Novell NAM (LUM) must be installed to use this script!" && exit 2
fi

# Get defaults from /etc/nam.conf
if [ -f "/etc/nam.conf" ]; then
	temp=`grep "^base-name=" /etc/nam.conf | sed 's|[^=]*=||'`
	defaultLinuxConfigContext=${temp:-$defaultLinuxConfigContext}
	temp=`grep "^ldap-ssl-port=" /etc/nam.conf | sed 's|[^=]*=||'`
	defaultSSLPort=${temp:-$defaultSSLPort}
	temp=`grep "^preferred-server=" /etc/nam.conf | sed 's|[^=]*=||'`
	defaultLDAPServer=${temp:-$defaultLDAPServer}
	temp=`grep "^alternative-ldap-server-list=" /etc/nam.conf | sed 's|[^=]*=||'`
	defaultBackupServer=${temp:-$defaultBackupServer}
	temp=`grep "^admin-fdn=" /etc/nam.conf | sed -e 's|[^=]*=||' -e 's|.*cn=||' -e 's|,.*||'`
	defaultAdminUser=${temp:-$defaultAdminUser}
	temp=`grep "^workstation-context=" /etc/nam.conf | sed 's|[^=]*=||'`
	defaultWorkstationContext=${temp:-$defaultWorkstationContext}
fi

if [ -z "$LDAPServer" ]; then
	while true;
	do
		echo -e -n "Enter the preferred LDAP eDirectory server to be used.\n[$defaultLDAPServer]: "
		read LDAPServer
		LDAPServer=${LDAPServer:-$defaultLDAPServer}
		if ping -c 1 $LDAPServer > /dev/null;
		then
			echo "" && break
		fi
		echo "The server ($LDAPServer) does not appear to be live!"
	done

	if [ -z $BackupServer ]; then
		echo -e -n "Enter a comma-separated list of other LDAP servers.\n[$defaultBackupServer]: "
		read BackupServer
		BackupServer=${BackupServer:-$defaultBackupServer}
	fi
fi

if [ -z "$LinuxConfigContext" ]; then
	echo -e "\nSelect the Linux/Unix config object context in LDAP syntax."
	declare -a array
	declare -i i=1

	array[0]="$defaultLinuxConfigContext"
	for context in $(ldapsearch -h "$LDAPServer" -x -s sub "(objectClass=uamPosixConfig)" dn | grep "^dn:" | sed 's|.*cn=[^,]*,||');
	do
		# Make sure that the value is not already present.
		test="false"
		for (( j=0 ; j <= i ; j++ ))
		do
			if echo "$context" | sed 's| ||g' | grep -i `echo "${array[j]}" | sed 's| ||g'` > /dev/null
			then
				test="true"
				break
			fi
		done

		if [ "$test" == "false" ]; then
			array[i++]="$context"		
		fi
	done

	PS3="Linux/Unix config object context: "
	select context in "Manually Enter Context" ${array[*]};
	do
		if ! [ "$context" ]; then
			context=""
		fi
		break
	done
	if [ "$context" == "Manually Enter Context" ] || [ -z "$context" ];
	then
		echo -e -n "Manually enter the Linux/Unix config object context in LDAP syntax.\n[$defaultLinuxConfigContext]: "
		read LinuxConfigContext
		LinuxConfigContext=${LinuxConfigContext:-$defaultLinuxConfigContext}
	else
		LinuxConfigContext=$context
	fi
fi
if [ -z "$WorkstationContext" ]; then
	browseldap ""

	defaultWorkstationContext=${defaultWorkstationContext:-$LinuxConfigContext}
	if [ -z "$WorkstationContext" ]; then
		echo -e -n "Manually enter the Workstation context in LDAP syntax.\n[$defaultWorkstationContext]: "
		read WorkstationContext
		WorkstationContext=${WorkstationContext:-$defaultWorkstationContext}
	fi
fi

if [ -z "$AdminUser" ]; then
	defaultAdminUser=${defaultAdminUser:-"admin"}
	while true;
	do
		echo -e -n "\nEnter the administrator's username\n[$defaultAdminUser]: "
		read AdminUser

		AdminUser=${AdminUser:-$defaultAdminUser}
		temp=`ldapsearch -h $LDAPServer -x -s sub -LLL cn=$AdminUser dn`

		if [ -z "$temp" ]; then
			echo -e "Sorry but the username ($AdminUser) does not appear in the directory."
		elif [ "`echo $temp | sed -e 's|^dn: ||' -e 's|dn: |\n|g'| wc -l`" == "1" ]; then
			AdminUser="`echo $temp | sed -e 's|^dn: ||' -e 's|dn: |\n|g'| wc -l`"
			break
		else
			PS3="Administrator's LDAP FDN: "
			echo -e "\nThe username ($AdminUser) matches multiple users.  Select one."
			select AdminUser in `echo $temp | sed -e 's|dn: ||g'`
			do
				if ! [ "$AdminUser" ]; then
					AdminUser=""
				fi
				break
			done
			if [ "$AdminUser" ]; then
				break
			fi
		fi
	done
fi

# Assign defaults incase any variables are missing
SSLPort=${SSLPort:-$defaultSSLPort}

run_namconfig && modify_nsswitch && modify_pamd && modify_pam_unix2 && start_namcd && sleep 2s && namconfig -k
status=$?
if [ "$status" == "0" ]; then
	echo -e "workstation-context=$WorkstationContext\n" >> /etc/nam.conf

	echo -e "You can now verify that eDirectory users resolve on the workstation using (id username).\n"
	id --help
fi
exit $status
Retrieved from /projects/pmwiki.php?n=SLED.SLED10NAM
Page last modified on January 30, 2009, at 10:49 AM