Skip navigation

Directory Binding Script (Active and Open Directory)

14313 Views 34 Replies Latest reply: Jan 9, 2014 12:37 PM by atperseghin RSS
1 2 3 Previous Next
seegorkesolot Calculating status...
Currently Being Moderated
May 31, 2011 5:20 AM

Hi everyone

 

I wrote quite a lengthy script to perform a proper binding to Active- and Open Directory Services in the local network. Since I've done the work, I'd like to share it with others in need of such a thing.

I'm well aware that it is far from perfection, there's no error handling but it's doing a good job. The script is based on two sources I like to mention and thank here:

- The Script written by Ross Hamilton and postet on HowToMac: http://www.howtomac.co.uk/?p=247

- And of course, Mike Bombich's AD Binding Script for Leopard found in http://www.afp548.com/netboot/mactips/scripts.html

 

It is mainly copy-pasted from the sources above and slightly modified to perform a good and stable job in what it is intended for..

 

 

#!/bin/sh

## Script to automate OD and AD Binding to the Servers
## Script written by Marc Horat, URZ Basel, 11.6.2010

# With the use of the following sources as inspiration:

# http://www.howtomac.co.uk/?p=247
#####################################
#Created by Ross Hamilton
#Clock restart / Remove existing settings
#Join to Open Directory and Active Directory
#
#####################################

# Bombich's AD-Bind Script:
# This script binds to AD and configures advanced options of the AD plugin
# As this scripts contains a password, be sure to take appropriate security
# precautions
# 
# A good way to run this script is to set it as a login hook on your master machine
# Because it only needs to be run once, the last thing this script does is to delete
# itself. If you have another login script that you typically run, include the 
# script on your master machine, and indicate its path in the "newLoginScript"
# variable.
#
# If running this as a one-time login hook to bind to AD after imaging,
# be sure to enable auto-login (for any local user) before creating your master image



############ Begin

# Host-specific parameters
# computerid should be set dynamically, this value must be machine-specific
# This value may be restricted to 19 characters! The only error you'll receive upon entering
# an invalid computer id is to the effect of not having appropriate privileges to perform the requested operation
#computerid=`/sbin/ifconfig en0 | awk '/ether/ { gsub(":", ""); print $2 }'` # MAC Address
#computerid=`hostname | sed 's/.unibas.ch//'`
#computerid=`/usr/sbin/scutil --get LocalHostName | cut -c 1-19` # Assure that this will produce unique names!
#computerid=`/usr/sbin/scutil --get LocalHostName`
computerid=`scutil --get ComputerName`
adcomputerid=`echo $computerid | tr [:lower:] [:upper:]`


#####################OD CONFIG#############################
# These variables need to be configured for your env
odAdmin="ENTERODADMIN" #enter your OD admin name between the quotes
odPassword="ENTERODADMINPW"  # Enter your OD admin password between the quotes
oddomain="ENTERODDOMAIN" # FQDN of your OD domain
computerGroup="ENTERODCOMPGROUP"  # Add appropriate computer group you want machines to be added to, case sensitive
oldComputerGroup="ENTEROLDODCOMPGROUP" # If the Computer is in a Group already

#####################END OD CONFIG#############################

# These variables probably don't need to be changed
nicAddress=`ifconfig en0 | grep ether | awk '{print $2}'`
check4OD=`dscl localhost -list /LDAPv3 | grep -n 1 | sed 's/1://' | sed 's/2://'`
check4ODacct=`dscl /LDAPv3/$check4OD -read Computers/"${computerid}" RealName | cut -c 11-`
check4AD=`dscl /Search -read / CSPSearchPath | grep /Active`
osversionlong=`sw_vers -productVersion`
osvers=${osversionlong:3:1}


#####################AD CONFIG#############################
# Standard parameters
domain="ENTERADDOMAIN"            # fully qualified DNS name of Active Directory Domain
udn="ENTERADADMINNAME"            # username of a privileged network user
password="ENTERADADMINPW"                    # password of a privileged network user
ou="OU=ENTER,OU=TARGET,OU=OU,OU=OF,DC=THE,DC=MAC,DC=IN,DC=AD"        # Distinguished name of container for the computer

# Advanced options AD Plugin
alldomains="disable"            # 'enable' or 'disable' automatic multi-domain authentication
localhome="disable"            # 'enable' or 'disable' force home directory to local drive
protocol="smb"                # 'afp' or 'smb' change how home is mounted from server
mobile="disable"            # 'enable' or 'disable' mobile account support for offline logon
mobileconfirm="disable"        # 'enable' or 'disable' warn the user that a mobile acct will be created
useuncpath="enable"            # 'enable' or 'disable' use AD SMBHome attribute to determine the home dir
user_shell="/bin/bash"        # e.g., /bin/bash or "none"
preferred="-nopreferred"    # Use the specified server for all Directory lookups and authentication
                            # (e.g. "-nopreferred" or "-preferred ad.server.edu")
admingroups="ENTERADGROUPSANDUSERSFORADMINISTRATION"                # These comma-separated AD groups may administer the machine (e.g. "" or "APPLE\mac admins")
packetsign="allow"            # allow | disable | require
packetencrypt="allow"        # allow | disable | require
passinterval="14"            # number of days
namespace="domain"            # forest | domain

# Login hook setting -- specify the path to a login hook that you want to run instead of this script
newLoginHook="PATHTOLOGINHOOK"        # e.g., "/Library/Management/login.sh"


#####################END AD CONFIG#############################

#Time Sync

#Restart ntpdate
StartService ()
{
if [ "${TIMESYNC:=-YES-}" = "-YES-" ] && ! GetPID ntpd > /dev/null; then

CheckForNetwork

if [ -f /var/run/NetworkTime.StartupItem -o "${NETWORKUP}" = "-NO-" ]; then exit; fi
touch /var/run/NetworkTime.StartupItem

echo "Starting network time synchronization"

# Synchronize our clock to the network’s time,
# then fire off ntpd to keep the clock in sync.
ntpdate -bvs
ntpd -f /var/run/ntp.drift -p /var/run/ntpd.pid
fi
}

#List existing Directories
echo "This computer is bound to the following Open Directory Services:"
dscl /Search -read / CSPSearchPath | grep /LDAP

sleep 5

echo "This computer is bound to the following Active Directory Services:"
dscl /Search -read / CSPSearchPath | grep /Active

sleep 5
# Removing any existing directory bindings

# Removing any existing directory bindings

if [ "${check4ODacct}" == "${computerid}" ]; then
    echo "This machine already has a computer account on "${oddomain}"."
    if [ "$oldComputerGroup" != "" ]; then
        echo "Removing entry from group $oldComputerGroup"
        dscl -u "${odAdmin}" -P "${odPassword}" /LDAPv3/"$check4OD" -delete /ComputerGroups/"$oldComputerGroup" GroupMembership "${computerid}"
    fi
    echo "Removing Computer entry $computerid in OD"
    dscl -u "${odAdmin}" -P "${odPassword}" /LDAPv3/"$check4OD" -delete /Computers/"${computerid}"
fi
#A second time..
if [ "${check4ODacct}" == "${computerid}" ]; then
    echo "This machine already has a computer account on "${oddomain}"."
    if [ "$oldComputerGroup" != "" ]; then
        echo "Removing entry from group $oldComputerGroup"
        dscl -u "${odAdmin}" -P "${odPassword}" /LDAPv3/"$check4OD" -delete /ComputerGroups/"$oldComputerGroup" GroupMembership "${computerid}"
    fi
    echo "Removing Computer entry $computerid in OD"
    dscl -u "${odAdmin}" -P "${odPassword}" /LDAPv3/"$check4OD" -delete /Computers/"${computerid}"
fi


sleep 10

echo "Removing any existing AD-Binding to "$check4AD""
dsconfigad -v -r -u $udn -p "$password"
dscl /Search -delete / CSPSearchPath "$check4AD"
dscl /Search/Contacts -delete / CSPSearchPath "$check4AD"
dscl /Search -delete / CSPSearchPath "$check4AD"
sleep 10

echo "Removing OD-Binding to "$check4OD""
# Check a second time in order to delete any remaining LDAP-Bindings
echo "Removing OD-Binding to "$check4OD""
dsconfigldap -v -r "$check4OD"
dsconfigldap -v -r "$check4OD"
dscl /Search -delete / CSPSearchPath /LDAPv3/"$check4OD"
dscl /Search/Contacts -delete / CSPSearchPath /LDAPv3/"$check4OD"
dscl /Search -delete / CSPSearchPath /LDAPv3/"$check4OD"



#Remove Existing Directory Services Config
echo "Removing existing DS Config"

if [ ! -d "/Library/Preferences/DirectoryService/ActiveDirectory" ]; then
rm -R /Library/Preferences/DirectoryService/ActiveDirectory*
fi

if [ ! -d "/Library/Preferences/DirectoryService/DSLDAPv3PlugInConfig" ]; then
rm -R /Library/Preferences/DirectoryService/DSLDAPv3PlugInConfig*
fi

if [ ! -d "/Library/Preferences/DirectoryService/SearchNode" ]; then
rm -R /Library/Preferences/DirectoryService/SearchNode*
fi

if [ ! -d "/Library/Preferences/DirectoryService/ContactsNode" ]; then
rm -R /Library/Preferences/DirectoryService/ContactsNode*
fi

if [ ! -d "/Library/Preferences/edu.mit.Kerberos" ]; then
rm -R /Library/Preferences/edu.mit.Kerberos
fi

if [ ! -d "/etc/krb5.keytab" ]; then
rm -R /etc/krb5.keytab
fi

# Clean up the DirectoryService configuration files
rm -vfR "/Library/Preferences/DirectoryService/*"
rm -vfR "/Library/Preferences/DirectoryService/.*" 

#############################################################
#OD
#############################################################

echo "Binding to OD-Damin $oddomain"
dsconfigldap -v -a $oddomain -n $oddomain -c $computerid
sleep 5


echo "Killing DirectoryService"
killall DirectoryService

sleep 10

echo "Adding computer account to /LDAPv3/${oddomain}"
dscl -u "${odAdmin}" -P "${odPassword}" /LDAPv3/"${oddomain}" -create /Computers/"${computerid}" ENetAddress "$nicAddress"
dscl -u "${odAdmin}" -P "${odPassword}" /LDAPv3/"${oddomain}" -merge /Computers/"${computerid}" RealName "${computerid}"
# Add computer to ComputerList
dscl -u "${odAdmin}" -P "${odPassword}" /LDAPv3/"${oddomain}" -merge /ComputerLists/${computerGroup} apple-computers "${computerid}"

# Set the GUID
GUID="$(dscl /LDAPv3/${oddomain} -read /Computers/"${computerid}" GeneratedUID | awk '{ print $2 }')"
# Add to computergroup
dscl -u "${odAdmin}" -P "${odPassword}" /LDAPv3/"${oddomain}" -merge /ComputerGroups/"${computerGroup}" apple-group-memberguid "${GUID}"
dscl -u "${odAdmin}" -P "${odPassword}" /LDAPv3/"${oddomain}" -merge /ComputerGroups/"${computerGroup}" memberUid "${computerid}"


sleep 15 # Give DS a chance to catch up

echo "Finished OD Binding."
#############################################################
#AD
#############################################################

# Activate the AD plugin
defaults write /Library/Preferences/DirectoryService/DirectoryService "Active Directory" "Active"
plutil -convert xml1 /Library/Preferences/DirectoryService/DirectoryService.plist

computeridtmp="default"
LEN=$(echo ${#adcomputerid})

if [ $LEN -lt 15 ]; then
        echo "ComputerID "$adcomputerid " has 15 characters or less and is therefore suitable for AD-Binding. It is $adcomputerid"
        computeridtmp=$adcomputerid
else
        echo "ComputerID "$adcomputerid " has 16 or more characters and needs to be modified for AD-Binding."
    echo "Removing any -"
        computeridtmp=${adcomputerid//-/}
        LEN=$(echo ${#computeridtmp})
        if [ $LEN -lt 15 ]; then
            echo "ComputerID "$computeridtmp" has now 15 characters or less and is therefore suitable for AD-Binding."
        else
            echo "Only using the last 15 characters of the Computer name to be able to bind to AD."
            computeridtmp=${computeridtmp:(-15)}
        fi
        echo "Cropped Computername to "$computeridtmp 


fi

# Bind to AD
dsconfigad -f -a $computeridtmp -domain $domain -u $udn -p "$password" -ou "$ou"

# Configure advanced AD plugin options
if [ "$admingroups" = "" ]; then
    dsconfigad -nogroups
else
    dsconfigad -groups "$admingroups"
fi

dsconfigad -alldomains $alldomains -localhome $localhome -protocol $protocol \
    -mobile $mobile -mobileconfirm $mobileconfirm -useuncpath $useuncpath \
    -shell $user_shell $preferred -packetsign $packetsign -packetencrypt $packetencrypt \
    -passinterval $passinterval -namespace $namespace

sleep 20


# Add the OD & AD node to the search path
if [ "$alldomains" = "enable" ]; then
    csp="/Active Directory/All Domains"
else
    csp="/Active Directory/$domain"
fi

echo "Finished AD Binding."

echo "Adding Domain /LDAPv3/"$oddomain" and "$csp" to Search Path"

dscl /Search -create / SearchPolicy CSPSearchPath
#dscl /Search -append / CSPSearchPath /LDAPv3/OD_SERVER
dscl /Search -append / CSPSearchPath /LDAPv3/"$oddomain"
#dscl /Search -append / CSPSearchPath /Active Directory/AD_Domain
dscl /Search -append / CSPSearchPath "$csp"

dscl /Search/Contacts -create / SearchPolicy CSPSearchPath
#dscl /Search/Contacts -append / CSPSearchPath /LDAPv3/OD_SERVER
dscl /Search/Contacts -append / CSPSearchPath /LDAPv3/"$oddomain"
#dscl /Search/Contacts -append / CSPSearchPath /Active Directory/All Domains
dscl /Search/Contacts -append / CSPSearchPath "$csp"

echo "Finished Updating Search Paths."

# Restart DirectoryService (necessary to reload AD plugin activation settings)
killall DirectoryService


# Destroy the login hook (or change it)
if [ "${newLoginHook}" == "" ]; then
    defaults delete /var/root/Library/Preferences/com.apple.loginwindow LoginHook
else
    defaults write /var/root/Library/Preferences/com.apple.loginwindow LoginHook $newLoginHook
fi

sleep 5

# Customizing the login-Window
#defaults write /Library/Preferences/com.apple.loginwindow AdminHostInfo DSStatus
#defaults write /Library/Preferences/com.apple.loginwindow showInputMenu -bool TRUE
#defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME -bool TRUE


# Disable autologin
defaults delete /Library/Preferences/com.apple.loginwindow autoLoginUser
srm /etc/kcpassword

# Kill loginwindow to return to the login screen
#killall loginwindow


exit 0        ## Success
exit 1        ## Failure

 

If anyone has inputs, critics, optimization suggestions or experience reports feel free to post them here ;-)

 

Cheers

  • M@CMAN2011 Level 1 Level 1 (20 points)

    Holy smoke, has christmas come early!

     

    This script is going to make my life so much easier after "imaging" an iMac. I can't wait to try it out!

     

    Thanks for sharing this, I'm sure a lot of people will benefit from it!

     

    Cheers,

  • sthrom Calculating status...

    Hi I have ben looking for a script that does exactly this thanks. just one thing tho as i am kind of new to this. Do i copy this and save it as a .sh file? or should i copy it into applescript and compile it? I know when i copy it into applescript and try to compile i get errors with a bunch of lines pretty much any line that starts with ` or $

  • sthrom Level 1 Level 1 (0 points)

    Thanks I tried that but the script came back with errors was there something else i was supposed to change?

     

    I even tried just copying the computer id section and making that its own script and i still get these errors

     

    /Users/macadmin/Desktop/name.sh: line 1: {rtf1ansiansicpg1252cocoartf1038cocoasubrtf350: command not found

    /Users/macadmin/Desktop/name.sh: line 2: syntax error near unexpected token `}'

    /Users/macadmin/Desktop/name.sh: line 2: `{\fonttbl\f0\fmodern\fcharset0 Courier;}'

     

    Thanks again for your help

  • M@CMAN2011 Level 1 Level 1 (20 points)

    I use text edit but you need to save the file as plain text:

     

    http://support.apple.com/kb/ta20406

  • sthrom Level 1 Level 1 (0 points)

    Thanks that worked.

  • sthrom Level 1 Level 1 (0 points)

    Hi See, I just have one other question? For some reason this script isn't adding my AD to my search policy, it adds the OD fine but will not add the AD. I checked the script for errors but I don't see any. I tried both enabling and disabling alldomains but the same thing occurs. If I open Open Directory utility and click the add button the AD will be there for me to add, same within the contacts. Thanks for your help

  • sthrom Level 1 Level 1 (0 points)

    Hi See,

     

    Thanks your quick replies. I think I may have figured out on how to add the search policy with 10.6. If you want to try it with 10.7 go ahead

     

    imidified these lines

     

     

    echo "Adding Domain /LDAPv3/"$oddomain" and "$csp" to Search Path"
    
    
    dscl /Search -create / SearchPolicy CSPSearchPath
    #dscl /Search -append / CSPSearchPath /LDAPv3/OD_SERVER
    dscl /Search -append / CSPSearchPath /LDAPv3/"$oddomain"
    #dscl /Search -append / CSPSearchPath /Active Directory/AD_Domain
    dscl /Search -append / CSPSearchPath "$csp"
    
    
    dscl /Search/Contacts -create / SearchPolicy CSPSearchPath
    #dscl /Search/Contacts -append / CSPSearchPath /LDAPv3/OD_SERVER
    dscl /Search/Contacts -append / CSPSearchPath /LDAPv3/"$oddomain"
    #dscl /Search/Contacts -append / CSPSearchPath /Active Directory/All Domains
    dscl /Search/Contacts -append / CSPSearchPath "$csp"
    
    

     

    with this

     

     

    echo "Adding Domain /LDAPv3/"$oddomain" and "$csp" to Search Path"
    
    
    dscl /Search -create / SearchPolicy CSPSearchPath
    dscl /Search/Contacts -create / SearchPolicy CSPSearchPath
    dscl /Search -append / CSPSearchPath /LDAPv3/"$oddomain"
    
    
    dscl /Search/Contacts -create / SearchPolicy CSPSearchPath
    dscl /Search/Contacts -append / CSPSearchPath /LDAPv3/"$oddomain"
    dscl /Search/Contacts -append / CSPSearchPath "$csp"
    dscl /Search -append / CSPSearchPath "$csp"
    
    

     

    After doing that it seems to work. I found another AD binding script online for 10.6 that was a little differnt but just used the search policy lines and edited them a bit for this script

     

    the exact lines i took were these

     

     

    ## Create the search paths in DS for authentication and contacts.
    dscl /Search -create / SearchPolicy CSPSearchPath
    dscl /Search/Contacts -create / SearchPolicy CSPSearchPath
    ## Add our AD domain to the search paths.
    dscl /Search/Contacts -append / CSPSearchPath “Active Directory/All Domains”
    dscl /Search -append / CSPSearchPath “Active Directory/All Domains”
    
    
    MacBook, Mac OS X (10.6.8)
  • Kevin Trumbull Calculating status...

    First off, thank you for what you've provided here.

     

    I'm working on a revised version of the above scripts.  While I'm not done with it, I wanted ask a few questions regarding the original scripts and offer to share the finished script I come up with.

     

    Given that this was posted more than 6 months ago, I suppose that the first thing I should ask is whether you're interested in revisiting this?

     

     

    The following should provide an idea of what I'm working on:

     

    Due to a number of factors, I really want a single script that works on any version of MacOS X that I need to support.  I'm also strongly interested in 'self-healing' technology, so I'll likely create a version of this that can unbind and rebind a machine that has fallen off of the domain (This can easly be done without having the password on the machine by triggering a remote secured machine to ssh in and run the script).

     

    In combining the 2 scripts, I've making some changes along the way.  Mostly along the following lines:

    1. Some structural changes required to support multiple OS revisions in a single script.
    2. The structural changes should make it easier  to update the script for new OSX revisions
    3. A new config variable and support for logging in the script. ( error log and output log ).
    4. The script can retrieve the computer name from Open Directory if it's been bound before (using en0 MAC address).  This does not requires authentication or  the machine being bound to OD.
    5. I've heavily reformatted and commented the combined script.
    6. If possible, I use delimiters instead of referencing character positions.  It's made my scripts far less prone to breakage.  I've rewritten all lines that specify character positions.
    7. The variable "domainname" changed to "domainName" due to the existence of "/bin/domainname"
1 2 3 Previous Next

Actions

More Like This

  • Retrieving data ...

Bookmarked By (2)

This site contains user submitted content, comments and opinions and is for informational purposes only. Apple disclaims any and all liability for the acts, omissions and conduct of any third parties in connection with or related to your use of the site. All postings and use of the content on this site are subject to the Apple Support Communities Terms of Use.