#!/bin/bash # $Id: sa_ds_master 1584 2011-09-11 22:10:54Z jhealy $ # # sa_ds_master - Suffield Academy DeployStudio library and scripts # # This file defines all of the custom actions for our DS workflows, # pre- and post-imaging actions, and other support. It also includes # functions to persist exported variables between script invocations # and reboots (through the use of temporary files). # # You should run this script directly using "bootstrap" as the first # argument, which will copy the script to /tmp. From that point on, # run the script from /tmp and it will self-modify as you progress # through the workflow. # # The persistence option works by saving a copy of the script to the # /tmp/ directory, with environment variables exported inline. # This is the location of the file, which should be hard-coded into # any scripts that call this one. PERSIST="/tmp/sa_ds_master" ###################################################################### ###################################################################### ### ### ### VARIABLES ### ### ### ###################################################################### ###################################################################### # Available Variables: # # DS_USER_LOGIN, # DS_REPOSITORY_PATH, # DS_LAST_SELECTED_TARGET, # DS_LAST_RESTORED_VOLUME, # DS_LAST_RESTORED_DEVICE, # DS_LAST_RESTORED_DISK_IMAGE_NAME, # DS_LAST_CREATED_DISK_IMAGE_NAME, # DS_BOOT_DEVICE, # DS_STARTUP_VOLUME, # DS_HOSTNAME, # DS_COMPUTERNAME, # DS_BOOTCAMP_WINDOWS_COMPUTER_NAME, # DS_BOOTCAMP_WINDOWS_PRODUCT_KEY, # DS_PRIMARY_MAC_ADDRESS, # DS_ASSIGNED_IP_ADDRESS, # DS_ASSIGNED_SUBNET, # DS_ASSIGNED_ROUTER, # DS_ASSIGNED_HOSTNAME, # DS_ASSIGNED_DNS, # DS_ASSIGNED_DOMAIN, # DS_COMPUTER_GROUP, # DS_SUPERDRIVE, # DS_ARCHITECTURE, # DS_SERIAL_NUMBER, # DS_MODEL_IDENTIFIER, # DS_BOOTROM_VERSION, # DS_CURRENT_WORKFLOW_TITLE, # DS_CURRENT_WORKFLOW_ID # are environment variables defined by DeployStudio Server Runtime # # Suffield Academy variables # SA_AUTO=YES|NO (is this an unattended/automatic boot?) # SA_UTYPE=facstaff|student (user type) # SA_MTYPE=loaner|unregistered|workstation (machine type) ###################################################################### ###################################################################### ### ### ### FUNCTIONS ### ### ### ###################################################################### ###################################################################### ## ## Terminate with an error message ## function sa_ds_die() { echo "$0: sa_ds_master: die: $1" 1>&2 echo "RuntimeAbortWorkflow: $0: sa_ds_master: $1" exit 1 } ## ## Overwrite the persistent file with current environment vars ## function sa_ds_envwrite() { # ensure only one process can create the temp file lock="${PERSIST}.lock" if (umask 222; echo $$ >"$lock") 2>/dev/null; then tmpwrite="${PERSIST}.tmp" envbeg=$(egrep -n '^#{3} SA_DS_BEGIN_ENV' "$PERSIST" | awk -F: '{print $1}') envend=$(egrep -n '^#{3} SA_DS_END_ENV' "$PERSIST" | awk -F: '{print $1}') head -n "$envbeg" "$PERSIST" > "$tmpwrite" export | egrep '^declare -x (DS|SA)_' >> "$tmpwrite" tail -n "+$envend" "$PERSIST" >> "$tmpwrite" mv "$tmpwrite" "$PERSIST" chmod 755 "$PERSIST" rm -f "$lock" else sa_ds_die "Could not get lockfile '$lock' for persisting environment" fi } ## ## Determine the Suffield variables based on workflow name ## function sa_ds_initvars() { # user type SA_UTYPE='unknown' # machine type SA_MTYPE='unknown' # unattended install SA_AUTO='NO' # preserve current case-preserving behavior if shopt -q nocasematch; then REVERTCASE=0 else REVERTCASE=1 shopt -s nocasematch fi for user in student facstaff; do if [[ ${DS_CURRENT_WORKFLOW_TITLE} =~ $user ]]; then SA_UTYPE=$user; fi done for mac in unregistered loaner workstation; do if [[ ${DS_CURRENT_WORKFLOW_TITLE} =~ $mac ]]; then SA_MTYPE=$mac; fi done # determine if this is an automatic install or not if [[ ${DS_CURRENT_WORKFLOW_TITLE} =~ ' auto ' ]]; then SA_AUTO='YES'; fi # revert the case matching behavior if [[ $REVERTCASE == 1 ]]; then shopt -u nocasematch fi # Final sanity checks if [[ $SA_UTYPE == 'unknown' || $SA_UTYPE == '' ]]; then sa_ds_die "RuntimeAbortWorkflow: unable to determine user type from workflow title '${DS_CURRENT_WORKFLOW_TITLE}'" fi if [[ $SA_MTYPE == 'unknown' || $SA_MTYPE == '' ]]; then sa_ds_die "RuntimeAbortWorkflow: unable to determine machine type from workflow title '${DS_CURRENT_WORKFLOW_TITLE}'" fi # # Echo a KEY=value pair with the prefix RuntimeSetCustomProperty to make # DeployStudio Runtime set or update a custom property # export SA_UTYPE echo "RuntimeSetCustomProperty: SA_UTYPE=${SA_UTYPE}" export SA_MTYPE echo "RuntimeSetCustomProperty: SA_MTYPE=${SA_MTYPE}" export SA_AUTO echo "RuntimeSetCustomProperty: SA_AUTO=${SA_AUTO}" } ## ## Suffield Academy post-install cleanup script ## ## Installs a run-once script on the target that performs one or ## more of the following actions, depending on the type of machine: ## ## 1) Remove local admin account and set back to unregistered state ## 2) Join machine to our LDAP directory ## 3) Set preferences for hardware and other settings ## function sa_ds_post_install() { kickstart="/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart" systemsetup="/usr/sbin/systemsetup" networksetup="/usr/sbin/networksetup" ### ### Debugging ### echo 'DS_USER_LOGIN =('${DS_USER_LOGIN}')' echo 'DS_REPOSITORY_PATH =('${DS_REPOSITORY_PATH}')' echo 'DS_LAST_SELECTED_TARGET =('${DS_LAST_SELECTED_TARGET}')' echo 'DS_LAST_RESTORED_VOLUME =('${DS_LAST_RESTORED_VOLUME}')' echo 'DS_LAST_RESTORED_DEVICE =('${DS_LAST_RESTORED_DEVICE}')' echo 'DS_LAST_RESTORED_DISK_IMAGE_NAME =('${DS_LAST_RESTORED_DISK_IMAGE_NAME}')' echo 'DS_LAST_CREATED_DISK_IMAGE_NAME =('${DS_LAST_CREATED_DISK_IMAGE_NAME}')' echo 'DS_BOOT_DEVICE =('${DS_BOOT_DEVICE}')' echo 'DS_STARTUP_VOLUME =('${DS_STARTUP_VOLUME}')' echo 'DS_HOSTNAME =('${DS_HOSTNAME}')' echo 'DS_COMPUTERNAME =('${DS_COMPUTERNAME}')' echo 'DS_BOOTCAMP_WINDOWS_COMPUTER_NAME=('${DS_BOOTCAMP_WINDOWS_COMPUTER_NAME}')' echo 'DS_BOOTCAMP_WINDOWS_PRODUCT_KEY =('${DS_BOOTCAMP_WINDOWS_PRODUCT_KEY}')' echo 'DS_PRIMARY_MAC_ADDRESS =('${DS_PRIMARY_MAC_ADDRESS}')' echo 'DS_ASSIGNED_IP_ADDRESS =('${DS_ASSIGNED_IP_ADDRESS}')' echo 'DS_ASSIGNED_SUBNET =('${DS_ASSIGNED_SUBNET}')' echo 'DS_ASSIGNED_ROUTER =('${DS_ASSIGNED_ROUTER}')' echo 'DS_ASSIGNED_HOSTNAME =('${DS_ASSIGNED_HOSTNAME}')' echo 'DS_ASSIGNED_DNS =('${DS_ASSIGNED_DNS}')' echo 'DS_ASSIGNED_DOMAIN =('${DS_ASSIGNED_DOMAIN}')' echo 'DS_COMPUTER_GROUP =('${DS_COMPUTER_GROUP}')' echo 'DS_SUPERDRIVE =('${DS_SUPERDRIVE}')' echo 'DS_ARCHITECTURE =('${DS_ARCHITECTURE}')' echo 'DS_SERIAL_NUMBER =('${DS_SERIAL_NUMBER}')' echo 'DS_MODEL_IDENTIFIER =('${DS_MODEL_IDENTIFIER}')' echo 'DS_BOOTROM_VERSION =('${DS_BOOTROM_VERSION}')' echo 'DS_CURRENT_WORKFLOW_TITLE =('${DS_CURRENT_WORKFLOW_TITLE}')' echo 'DS_CURRENT_WORKFLOW_ID =('${DS_CURRENT_WORKFLOW_ID}')' echo '' echo 'SA_UTYPE =('${SA_UTYPE}')' echo 'SA_MTYPE =('${SA_MTYPE}')' echo 'SA_AUTO =('${SA_AUTO}')' echo '' ### ### Generic ### $networksetup -detectnewhardware $networksetup -setdhcp Ethernet $networksetup -setdhcp Airport if [[ $MTYPE == 'workstation' ]]; then echo "Enabling 'Suffield Gear' as primary SSID" $networksetup -setairportnetwork AirPort "Suffield Gear" $networksetup -addpreferredwirelessnetworkatindex AirPort "Suffield Gear" 0 OPEN else echo "Enabling 'Suffield Auth' as primary SSID" $networksetup -setairportnetwork AirPort "Suffield Auth" $networksetup -addpreferredwirelessnetworkatindex AirPort "Suffield Auth" 0 WPA2E fi # set hostname to a unique value echo "Setting hostname to '${DS_SERIAL_NUMBER}'" scutil --set ComputerName "${DS_SERIAL_NUMBER}" scutil --set LocalHostName "Suffield-Image-${DS_SERIAL_NUMBER}" # Microsoft Office seems to get stupid permsisions (only for the # user that installed the package) chown -R 0:admin "/Applications/Microsoft Office 2011" chmod u+rwX,g+rwX,o+rX "/Applications/Microsoft Office 2011" ### ### Local account settings ### lwpref='/Library/Preferences/com.apple.loginwindow' # disable auto-login by default if [ -f "${lwpref}.plist" ]; then echo "Disabling auto-login..." defaults delete "$lwpref" autoLoginUser fi ## Delete local admin for unregistered machines if [[ $SA_MTYPE == 'unregistered' ]]; then echo "Deleting suffieldacademy account from all groups" for group in $(dscl . -list /Groups GroupMembership | awk '/suffieldacademy/ {print $1}'); do dscl . -delete /Groups/$group GroupMembership suffieldacademy done echo "Deleting suffieldacademy user account" dscl . -delete /Users/suffieldacademy echo "Deleting suffieldacademy user folder" rm -rf /Users/suffieldacademy # Remove machine registration (use DeployStudio framework to # accomodate reboots) echo "Removing AppleSetupDone flag" touch /private/var/db/.ds.delete.AppleSetupDone rm -f /private/var/db/.AppleSetupDone # Set the background image back the way it should be if [ -f "/System/Library/CoreServices/DefaultDesktop_original.jpg" ]; then echo "Restoring default background image" mv "/System/Library/CoreServices/DefaultDesktop_original.jpg" "/System/Library/CoreServices/DefaultDesktop.jpg" fi fi ## Change password to 1833 for loaners if [[ $SA_MTYPE == 'loaner' ]]; then echo "Changing suffieldacademy password to '1833'" dscl . -passwd /Users/suffieldacademy 1833 # delete and re-create the keychain echo "Updating keychain" sudo -n -u suffieldacademy -H -s -- security -v delete-keychain '~/Library/Keychains/login.keychain' sudo -n -u suffieldacademy -H -s -- security -v create-keychain -p 1833 '~/Library/Keychains/login.keychain' # set autologin for the suffieldacademy user echo "Setting autologin to suffieldacademy" defaults write "$lwpref" autoLoginUser suffieldacademy #defaults write "$lwpref" autoLoginUserUID 501 defaults write "$lwpref" lastUser Restart # Set the encrypted version of "1833" as the new login password # (use DeployStudio framework to accomodate reboots) echo -ne "\x4c\xb1\x61\x10\xd2\xdb\x1b\x83\xd0\xe8\xe0\x37" > /private/etc/deploystudio/etc/kcpassword chown root:wheel /private/etc/deploystudio/etc/kcpassword chmod 600 /private/etc/deploystudio/etc/kcpassword fi ## Leave alone for others ## fix permissions echo "Fixing permissions on ${lwpref}.plist" chown root:admin "${lwpref}.plist" chmod 664 "${lwpref}.plist" ### ### Time server settings ### systemsetup -settimezone "America/New_York" $systemsetup -setusingnetworktime off if [[ $SA_MTYPE == 'workstation' ]]; then # use local time server for school-owned desktops echo "Setting time server to suffieldacademy trio" echo "server ntp0.suffieldacademy.org" > /etc/ntp.conf echo "server ntp1.suffieldacademy.org" >> /etc/ntp.conf echo "server ntp2.suffieldacademy.org" >> /etc/ntp.conf else # use Apple for everything else echo "Setting time server to Apple" echo "server time.apple.com" > /etc/ntp.conf fi $systemsetup -setusingnetworktime on echo "Syncing clock immediately" ntpdate -bvs ntp.suffieldacademy.org ### ### Apple Remote Desktop ### # set ARD directory groups in Workgroup Manager under com.apple.remotedesktop # (See ARD Admin Guide for more info) if [[ $SA_MTYPE == 'workstation' ]]; then echo "Enabling ARD" $kickstart -configure -allowAccessFor -specifiedUsers $kickstart -configure -clientopts -setmenuextra -menuextra yes -setdirlogins -dirlogins yes $kickstart -activate else echo "Disabling ARD" $kickstart -deactivate -stop fi ### ### Networked Admins ### if [[ $SA_MTYPE == 'workstation' ]]; then # add our "helpdesk" group as a sub-group of administrators echo "Adding network admins" dscl . -append /Groups/admin NestedGroups $(dscl -q /LDAPv3/ldap.suffieldacademy.org -read /Groups/helpdesk GeneratedUID | awk '{print $2}') # allow anyone on the machine to add/delete printers echo "Allowing all to printer group" dseditgroup -o edit -n /Local/Default -a suffield -t group _lpadmin #dscl . -append /Groups/_lpadmin NestedGroups $(dscl -q /LDAPv3/ldap.suffieldacademy.org -read /Groups/suffield GeneratedUID | awk '{print $2}') fi ### ### Kerberos ### # machines bound to LDAP automatically get Kerberos settings if [[ $SA_MTYPE != 'workstation' ]]; then echo "Installing Kerberos defaults" cat > '/Library/Preferences/edu.mit.Kerberos' <