You are not logged in.

Announcement

[2017.09.08] DeployStudio build v1.7.8 (checksum, release note).
[2016.08.26] DeployStudio build v1.6.19 (release note).
[2013.02.23] DeployStudio last universal build v1.5.17 (release note).

#1 2016-09-16 21:47:13

Nathan Fisher
Member
Registered: 2014-08-13

auto disable SIP

add to your rc.install somewhere shortly before DS runtime window loads

# disable SIP if necessary
# requires csrutil.  copy it from /usr/bin/csrutil on the recovery image to same location on the netboot
# it will run on the netboot since it thinks its running the OS installer or setup assistant
csr=/usr/bin/csrutil
if [ -f "$csr" ] ; then
  csrutil status | grep -q "disabled"
  enabled=$?
  if [ $enabled == 0 ] ; then
    echo "SIP is already disabled"
  else
    "$csr" disable ; rc=$?
    if [ $rc == 0 ] ; then
      echo "SIP successfully disabled, restart required to make changes effective"
    else
      echo "RC=$rc attempting to disable SIP"
    fi
  fi
else
  echo "CSRUTIL unavailable, SIP unmodified"
fi


You can use option key first boot up to select your DS netboot, and this will disable SIP for you to set your netboot server as startup later.  Or you can modify it to whitelist just your server.

DS team: maybe add this to the rc.installer, and have it whitelist the specified server during the boot image build?  It's easier to just option boot and select the netboot than to boot up and get into utilities etc.  at least it's easier for the interns to manage on labs full of computers.  Also required if the recovery partition isn't there anymore. (due to oh.... imaging maybe!)

Offline

#2 2016-09-16 22:12:06

meca62793
Member
Registered: 2015-11-06

Re: auto disable SIP

All my images include restore partitions.

Offline

#3 2016-09-16 22:13:53

Nathan Fisher
Member
Registered: 2014-08-13

Re: auto disable SIP

> meca62793 wrote:

> All my images include restore partitions.

you do realize this gives all your users (and any random person that walks by the computer) root access to their computer?

Offline

#4 2016-09-22 07:53:59

darkmuncan
Member
Registered: 2014-05-28

Re: auto disable SIP

> Nathan Fisher wrote:

> > meca62793 wrote:

> All my images include restore partitions.

you do realize this gives all your users (and any random person that walks by the computer) root access to their computer?


That's why we encrypt ours :)

The only reason we have the recovery partition is for FileVault

Offline

#5 2016-11-01 19:24:38

techsupport
Member
Registered: 2012-06-06

Re: auto disable SIP

Nathan Fisher - This is an outstanding idea, and exactly the sort of thing I have been looking for! Would it be possible to clarify some items in your original post?
- Can you please be more specific about where to place this script?
- What did you mean by "rc.install?" Are you referring to the /etc/rc.netboot config file? If so, where would I insert this script?

Additionally, do you know of any way to put this in as a step in a workflow? I might make this question a separate post if this does not work.

Thanks very much for your help.

Offline

#6 2016-11-01 20:18:31

Nathan Fisher
Member
Registered: 2014-08-13

Re: auto disable SIP

rc.install is the name of the script that a Mac OS X restore image runs when it boots up, it runs the installer.  DS creates a bootable image from the installer by modifying it.  They simply replace the rc.install with one of their own, to do the work of the restore.  So this file is on your DS runtime bootable image, the one you may have on a flash drive or the .DMG file on your netboot server.  It's in the /etc/ folder.

Normally csrutil won't run when booted normally, but thankfully since it sees it's running off a restore disk (of sorts) it allows it.  I'm almost worried to say this in public, as Apple has had a nasty habit of trolling the forums I'm in and disabling handy things like that as fast as I find them. (I was unintentionally involved in an "update war" with apple a few years ago, and I apologize for several bits of BS apple applied to SUDO as a result of my trying to help people - I'm almost certainly/partly responsible for sudo no longer working with blank passwords, among other things)  I hope they either don't notice this or leave it alone this time.

I haven't spent any time to see how often the DS team changes the rc.install script, but it's probably safe to assume that you'd want to just make a few changes to your script rather than have a copy of mine, as it may operate differently and not be compatible with the version of DS you are running.  So just edit theirs (after backing it up!) and paste in that bit above.

The block of code above can be pasted in anywhere before the runtime is loaded, which is near the very bottom and is commented as to what it does, so you shouldn't have any problem finding it.  The file on the flash drive should be trivial to edit.  You can edit the netboot by mounting it, it will mount read/write.  It would probably require another "scan for restore" to multicast, but I don't do that here so I just edit files on that netboot anytime I need to.

You must also install the csrutil app on the netboot image, it's not there by default. (it WAS there, but DS's cleanup script that builds the DS image from the installer deletes it during the build, along with a number of other useful yet trivially small things like 'clear'')  Get a copy of the Install OS X El Capitan.app etc that has the CSR 'feature', and then you will have to do a bit of digging to get to it.

Ctrl-click on the app, show package contents.  Open Contents, Shared Support, and double click to mount InstallESD.dmg

The image that mounts has a HIDDEN file on it called BaseSystem.dmg, you need to mount THAT now by whatever means you have handy to access the hidden file. 

On the image that pops up, dig into /usr/bin and you will find csrutil.  Copy that to /usr/bin/ on your DS runtime so the rc.install code can run it.

You will still have to manually select the netboot server the first time, but the above bit will allow changing of the startup drive so that you can do things like use ARD to change a computers startup disk to it and reboot.  But it's a lot easier/safer to send an intern or three into the labs and have them run around and do that simple task rather than having to go out with flash drives or something and muck internal.  I have a default script that saves computer serial numbers into a text file on my server, that makes it easier to get them into my ARD console to start with.  Not sure when DS will be implementing something like that, they need to tighten up their integration with ARD.

I can post my entire rc.install here if you're morbidly curious.  It's quite a bit more complicated and customized, but well commented.

I haven't explored putting it in a workflow, but it shouldn't be that difficult.  You will need to follow the above steps for getting csrutil onto the runtime or by some other method make it available at workflow time, and then just use the lines above to invoke csrutil.  I put it in rc.install rather than a workflow so it runs every time, even without any workflow. (I also happened to be getting ssh working, VNC more reliable, stopping tmp from running out of space, proper logging, improved reliability, backlight maintenance.... there was a lot to do with rc.install, so it just got rolled in there where it fit in)

Last edited by Nathan Fisher (2016-11-01 20:45:59)

Offline

#7 2016-11-02 14:46:27

techsupport
Member
Registered: 2012-06-06

Re: auto disable SIP

Thanks so much for your reply! It is nice to know that some people out there are still fighting Apple's stranglehold on hardware and software. With every OS and hardware release, it becomes more and more difficult to put Macs in deployment situations.

Anyway, I like the idea of doing it this way rather than a workflow, since this way I can more easily re-enable it if it gets disabled down the line.

I just did my first round of experimenting with this, but it did not work. I inserted your script into the rc.install file in the NetBoot image I have, booted to it, checked csrutil status in Terminal after DeployStudio booting had completed, and it was still enabled. Any thoughts on this?

Interestingly, csrutil is already present in usr/bin. That is why I am able to query status and disable it manually via Terminal when I boot into DeployStudio with the NetBoot image I made using 10.12.1. Are you saying that DeployStudio deletes csrutil from etc/bin at some other point?

Last edited by techsupport (2016-11-02 14:54:22)

Offline

#8 2016-11-02 15:16:08

techsupport
Member
Registered: 2012-06-06

Re: auto disable SIP

Okay, so an update - I moved your script around within rc.install, and it worked!

I think this is a great solution because it has nothing to do with imaging or workflows, and requires no further interaction after booting from the NetBoot image.

Out of curiosity, are you doing any other work regarding SIP?

Offline

#9 2016-11-02 15:37:28

Nathan Fisher
Member
Registered: 2014-08-13

Re: auto disable SIP

Not sure why you found csrutil, you may be running a newer version of DS than me.  They change stuff like that from time to time.  I'm not doing anything specific with SIP.

Here's some food for thought.  Hope you're hungry!

#!/bin/sh

vers=2016.09.29.A # NOT copied, more up to date than what's on TASK

# be sure to copy this to the DS installation notes folder if changes are made

# original script Copyright 2000-2011, Apple Inc.
# DEPLOYSTUDIO startup
# http://www.deploystudio.com
# extensive modifications by Nathan Fisher

# this script MUST be tolerant of being run more than once, as it may be restarted after a
# manual runtime action has completed

# log progress in the install.log file
# a forked process will shuttle entries from the local to the repo log as it appears
local_logfile="/var/log/install.log"
local_repo_logfile="/var/log/repo.log"
temp_logfile="/tmp/install_log.temp"
timestamp_format="+%b %d %T"  # this is how the runtime stamps things.  wouldn't be my first choice.  lets be consistent though.


log () {
local line
if [ -n "$1" ] ; then
  echo "$(date "$timestamp_format") ==RC==> $1" >> "$local_logfile"  # this is how DS logs it so we'll be consistent
else
  # caller probably piped something to us, like output of something else or cat a file etc
  log "Streamed output starting now"
  log "----------------------------"
  while read line ; do
    echo "$(date "$timestamp_format") ==RC==> $line" >> "$local_logfile"
  done
  log "============================"
fi
}
touch "$local_logfile"
log "===================================================================================================="
log "DS RUNTIME RC.INSTALL $vers"


log "Show default desktop background image"
/Applications/DefaultDesktopViewer.app/Contents/MacOS/DefaultDesktopViewer &
forked_wallpaper=$! # so we can kill it later


# vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

log "Fork ADA watcher"
(
log "ADA: started"
log "ADA: waiting for ADA to launch"
local ticks
ticks=0
while true ; do
  ps -ax | grep -v grep | grep com.apple.AmbientDisplayAgent > /dev/null
  if [ $? == 0 ] ; then
    break
  fi
  sleep 1
  ((ticks++))
  if [ $ticks == 10 ] ; then
    # remind them periodically that we're still waiting
    log "ADA: still waiting for launch"
    ticks=0
  fi
done
log "ADA: AmbientDisplayAgent process detected, initiating"
sleep 5
log "ADA: Start check for computer and backlight sleep"
while [ true ] ; do
  # we will exit when we get sigkill'd
  x=$(pmset -g live | grep displaysleep)  # " displaysleep         10"
  x=${x##* }  # "10"
  if [ -z "$x" ] ; then
    # unsleepable backlight?  no such key found
    x=0
  fi
  if [ $x != 0 ] ; then
    log "ADA: pmset found programmed to sleep display in $x, disabling sleep"
    /usr/bin/pmset force -a sleep 0 displaysleep 0 lessbright 0 disksleep 0
    pmset -g live | log
  fi
  sleep 30
done
) &
forked_ada=$!  # so we can kill it later
log "Forked watcher (PID $forked_ada) to set power management after ADA comes up"

# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


log "Load custom environment variables"
if [ -e /etc/deploystudio-env.conf ] ;then
  . /etc/deploystudio-env.conf
fi


log "Wait for network services to become available"
a=12  # will try a dozen times for a default interface, once every five seconds
while [ $a -gt 0 ] ; do
  i=$(netstat -rn -f inet | grep default | tr -s ' ' | cut -d ' ' -f 6 | tr '\n' ' ')
  if [ -n "$i" ] ; then
    ip=$(ifconfig $i | grep $'\tinet ' | cut -d ' ' -f 2)
    log "Network is up on interface(s) $i with IP address $ip"
    break
  fi
  sleep 5
  ((a--))
done
if [ $a == 0 ] ; then
  log "Network not configured, repo will probably be unavailable this session"
fi


log "Generate temporary computer name and hostname based on motherboard serial number"
serial_number=$(ioreg -rd1 -c IOPlatformExpertDevice | awk -F= '/(IOPlatformSerialNumber)/ { gsub("[ \"]", ""); print $2 }')
if [ -z "$serial_number" ] ; then
  comp_name="Mac-noserialnum" # 15 character limit for winders
  log "NO SERIAL NUMBER FOUND"
else
  comp_name="Mac-${serial_number}"
fi
host_name=$(echo "$comp_name" | tr '[A-Z]' '[a-z]')
log "Set computer name to $comp_name, hostname to $host_name"
scutil --set ComputerName  "$comp_name"
scutil --set LocalHostName "$host_name"
# will also use serial number for logging on the repo
repo_logfile="/tmp/DSNetworkRepository/Logs/${serial_number}.rclog"
# give them easy access to the repo log file, since that's where everything is going to go
ln -s "$repo_logfile" "$local_repo_logfile"


# function to preen a file of a string, by removing lines that match a grep pattern
# currently only used by the log shuttler, but could be used to keep other log files tidy and small
preen () {
local file pattern lines
file=$1
pattern=$2
lines=$3
if [ -z "$lines" ] ; then
  cat "$file" | grep -v "$pattern" > "$temp_logfile"
else
  cat "$file" | grep -v "$pattern" | head -n $lines > "$temp_logfile"
fi
rm "$file"  # some files must be rm'd, others must be one-line-echoed to.
# wifi.log must be echoed to in order to clear it, system.log must be rm'd.  do it wrong and it just grows back...
cp "$temp_logfile" "$file"
rm "$temp_logfile"
}


# vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

log "Fork log maintenance"
(
log "LOGGER: started"
# set a trap for sigio, to stop the 10 second delay in logging
we_are_leaving=
trap we_are_leaving=1 SIGIO
# wait for repo to connect
log "LOGGER: waiting for repo to connect"
ticks=0
while ! [ -d "${repo_logfile%/*}" ] ; do
  # repo parent folder does not exist yet
  sleep 1
  ((ticks++))
  if [ $ticks == 10 ] ; then
    # remind them periodically that we're still waiting
    log "LOGGER: still waiting for repo"
    ticks=0
  fi
done
#  repo is connected
repo_connected=1
# 1=connected, supposedly usable
# 2=connected but unusable
# 3=disconnected (terminal state)
log "Repository has connected, will move filtered log entries to $repo_logfile"  # surprisingly, defined functions are accessible from forked processes
if ! [ -f "$repo_logfile" ] ; then
  # repo log file doesn't exist yet, create it
  log "Runtime creating log file at \"$repo_logfile\""
  touch "$repo_logfile" ; rc=$?
  if [ $rc != 0 ] ; then
    log "RC=$rc creating repo log file, probably permissions problem on the share, logging locally only"
    # don't exit, we still need to keep the install.log file tidy and small
    repo_connected=2
  fi
fi

# work hard to try to keep space on the (5MB) virtual volume /var/log as free as possible
# the computer will become very slow to respond when this volume fills up
while [ true ] ; do  # we will exit when we get sigkill'd

  # run once a second, not nonstop
  for ((sleeper=0;sleeper<10;sleeper++)) ; do
    # sigio will abort this loop immediately to get the last of the logs shuttled
    if [ $we_are_leaving ] ; then
      break
    fi
    sleep 1
  done

  # wipe the wifi log, which grows uncontrollably
  # I tried to redirect this to /dev/null but something deletes the symlink
  echo "log is kept cleared to preserve space on this virtual volume" > /var/log/wifi.log

  # delete yesterday's ASL logs.  (frees space on /var/log at midnight)
  ls /var/log/$(date -j -v-1d "+%Y.%m.%d")* | while read f ; do rm "$f" ; done
  # at the rate these grow, it's still quite possible ASL will run this virtual drive out of space
  # over the course of a day.  it's only 5MB

  # preen log files - remove entries that tend to roll in frequently and burn through space
  preen "/var/log/system.log" "Failed to find KerberosKDC node" 500

  # filter entries in local log file to a temp file and wipe it
  cat "$local_logfile" | grep -v opendirectoryd  | grep -v "last message repeated" > "$temp_logfile"
  echo "\c" > "$local_logfile" # have to use that instead of 'echo -n' because sh

  if [ -s "$temp_logfile" ] ; then
    # the filtered local log file has something useful in it

    # if the repo disconnects, resume local logging (it will never reconnect, this is a terminal state)
    if [[ (! -d "${repo_logfile%/*}") && ($repo_connected != 3) ]] ; then
      # repo just disconnected
      log "REPO JUST DISCONNECTED, it will not reconnect this session"
      repo_connected=3
    fi

    # process useful entries
    if [ $repo_connected == 1 ] ; then
      # repo is connected and we haven't gotten an error on it yet, append useful log entries to repo log and keep local log cleared
      cat "$temp_logfile" >> "$repo_logfile" ; rc=$?
      if [ $rc != 0 ] ; then
        log "RC=$rc appending to repo log file, probably permissions problem on the share, logging locally only"
        repo_connected=2  # switch to "repo connected but unusable" state
      fi
    else
      # repo is not connected or is connected but is unusable (can't write to it)
      #  move any (filtered) log entries back into local log file
      cp "$temp_logfile" "$local_logfile"
    fi

    # remove temp file
    rm "$temp_logfile"

  fi

done

) &
forked_logger=$!  # so we can kill it later
log "Forked log maintenance process (PID $forked_logger) to transfer logs to repo and manage space on /var/log"

# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


# allow any app to run without restriction
log "Disable assessments checks"
/usr/sbin/spctl --master-disable


# this looks like a small custom binary that turns on or maintains display mirroring mode
log "Enable display mirroring"
/usr/bin/enableDisplayMirroring &
forked_mirror=$!  # so we can kill it later


# use an NTP time server if available to reset the clock, for more accurate logging
log "Fix system date"
if [ -f /etc/ntp.conf ] ; then
  NTP_SERVERS=$(cat /etc/ntp.conf | awk '{ print $NF }')
  for NTP_SERVER in $NTP_SERVERS ; do
    ntpdate -u "$NTP_SERVER" 2>/dev/null
    if [ ${?} -eq 0 ] ; then
      break
    fi
  done
fi


# enable VNC / ARD basic screen sharing if it was configured during runtime setup
log "Checking VNC"
if [ -e /Library/Preferences/com.apple.VNCSettings.txt ] ; then
  log "Launch a VNC server"
  label=com.apple.screensharing.MessagesAgent  # 10.11 label
  # note this label has changed more than once, it was "com.apple.screensharing" in 10.10
  # Dear Apple, MAKE UP YOUR MIND
  launchctl list $label > /dev/null ; rc=$?
  if [ $rc == 0 ] ; then
    log "VNC server already loaded"
    launchctl list $label >> "$local_logfile"
  else
    log "Loading VNC agent"
    launchctl load /System/Library/LaunchAgents/com.apple.screensharing.MessagesAgent.plist ; rc=$?
    if [ $rc == 0 ] ; then
      log "VNC loaded successully"
    else
      log "RC=$rc trying to load VNC launch agent"
    fi
  fi
else
  log "VNC is not configured, will not start a listener"
fi


# it would be nice to have the Debug menu in Disk Utility, particularly for the "Show Every Partition" option
#log "Update Disk Utility preferences to display every partition (EFI, recovery, ...)"
#this no longer works in 10.11
#defaults write com.apple.DiskUtility DUShowEveryPartition -bool YES


# DS's runtime for some reason is unable to turn the backlight back on after shutting it off
# caffeinate is ineffective for unknown reasons, el cap seems to have problems in this area
# will rely on power management settings instead below
#caf=/usr/bin/caffeinate
#if [ -x "$caf" ] ; then
#  log "Prevent display dim/sleep by generating simulated user activity using caffeinate"
#  /usr/bin/caffeinate -u &
#else
#  log "caffeinate binary not found at $caf, copy it into the runtime image.  backight may dim or go out"
#fi


# disable SIP if necessary
# requires csrutil.  copy it from /usr/bin/csrutil on the recovery image to same location on the netboot
# it will run on the DS netboot since it thinks its running the OS installer or setup assistant
log "Checking SIP"
csr=/usr/bin/csrutil
if [ -x "$csr" ] ; then
  csrutil status | grep -q "disabled"
  enabled=$?
  if [ $enabled == 0 ] ; then
    log "SIP is already disabled"
  else
    "$csr" disable ; rc=$?
    if [ $rc == 0 ] ; then
      log "SIP successfully disabled, restart required to make changes effective"
    else
      log "RC=$rc attempting to disable SIP"
    fi
  fi
else
  log "csrutil binary not found at $csr, copy it into the runtime image to use.  SIP unmodified"
fi


# we probably have other things that need trimming too, but install.log is now being pruned and transferred to the repo
# so keep this code and modify it later
# log "forking process to trim /private/var/log/install.log if the virtual disk /private/var/log gets low on space"
#(
#vol=/private/var/log
#log1=$vol/install.log
#log2=$vol/install.log2
#while true ; do
#  kfree=$(df -k $vol | tail -n1 | tr -s ' ' | cut -d ' ' -f 7)  # kilobytes free on $vol
#  if [ $kfree -lt 100 ] ; then
#    echo "$(date "+%Y/%m/%d %H:%M:%S") - trimming log due to low disk space ($kfree KB) on $vol" > $log2
#    tail -n 100 $log1 >> $log2
#    mv $log2 $log1
#  fi
#  sleep 30
#done
#) &


##
## DS runtime window opens now.  if a workflow is set to run automatically on this machine, it will start now
##


log "Launch DeployStudio Runtime"
DS_APP="/Applications/Utilities/DeployStudio Admin.app/Contents/Applications/DeployStudio Runtime.app/Contents/MacOS/DeployStudio Runtime"
DS_PARAMS=--netboot
if [ -x "$DS_APP" ] ; then
  # Disable App Nap just in case...
  defaults write com.deploystudio.admin   NSAppSleepDisabled -bool YES
  defaults write com.deploystudio.runtime NSAppSleepDisabled -bool YES
  "$DS_APP" $DS_PARAMS
  if [ $? != 0 ] ; then
    /Applications/Utilities/Terminal.app/Contents/MacOS/Terminal
  fi
fi


##
## we get here after a workflow has completed.  either the automatic one or one manually selected
##


log "Stop displaying ads (depreciated?)"
# apparently DS has/had something to display ads.  I've never seen it.  this closes it if running
kill `ps -axww | awk '/AdViewer/ {print $1}'` 2>/dev/null


log "Stop the ADA watcher / pmset display sleep setter"
kill $forked_ada


log "Stop display mirroring"
# kill `ps -axww | awk '/enableDisplayMirroring/ {print $1}'` 2>/dev/null
kill $forked_mirror


log Stop displaying the background wallpaper"
# this was commented out, they may have decided to not bother with stopping it
# kill `ps -axww | awk '/DefaultDesktopViewer/ {print $1}'` 2>/dev/null
kill $forked_wallpaper

# try to trigger shutdown now
log "Restarting, stop the logfile shuttler"
sleep 2
kill -SIGIO $forked_logger  # tell it to shuttle one last time, immediately
sleep 5

shutdown -r now

kill $forked_logger
# no more logs will be shuttled, so this should be the last step in the script

# again maybe
sleep 1
shutdown -r now

# rc.install will be re-executed now unless we did an automated restore, in which case it will
# restart on the restored image, to complete the imaging post-process

Offline

#10 2016-11-02 16:02:27

techsupport
Member
Registered: 2012-06-06

Re: auto disable SIP

Wow! That script is a beast! Thanks! I am going to thoroughly dig into it a bit later. I am sure there will be useful/inspiring things to be found.

And I am running the latest DeployStudio version (1.7.5) on a 10.11.6 Xserve.

Offline

Board footer

Powered by FluxBB