Disable Your Mac from Automatically Booting On Lid Open

The other day I was “flipping” through Flipboard and came across an article on OSXDaily that discussed how one could prevent a Mac from automatically booting when the lid is opened.

The command to enable or disable this setting is quite simple.  By leveraging Terminal, all you need to do is set the AutoBoot value.

Disable AutoBoot:

sudo nvram AutoBoot=%00

Enable AutoBoot:

sudo nvram AutoBoot=%03

While I personally like the AutoBoot feature, I can see why some people may choose to disable it; especially in an academic or corporate setting.

Using LANDESK Security Suite 2016, the NVRAM AutoBoot setting can easily be scanned for with every vulnerability scan, by building a custom definition to evaluate the NVRAM AutoBoot value.  Then, using the repair logic, you can maintain a desired state in your organization even if an administrative user opts to change it.

And, the best part is, I’ve created the custom definition for you – no scripting needed on your behalf.  Download the custom definition from GitHub here and import it to your core server.

Custom Definition Import

  1. Open the LANDESK console
  2. Go to Tools > Security and Compliance > Patch and Compliance
  3. From the definition types dropdown menu, ensure you have selected Custom definitionpatch and compliance dropdown menu.png
  4. In the white space area, right click and select Import custom definition import.png
  5. Browse to the custom definition file and click the Open button to import

Once imported, set the definition to Autofix and it will maintain the AutoBoot state for you.  It’s that easy to maintain, pretty nice, isn’t?  It doesn’t matter if a person changes the value themselves, using Autofix it will continually set the value back to the state defined in the defintiion.

Understanding the Custom Definition

If you’re like me and want to understand how I built the custom definition, as opposed to just blindly importing the file I created, then read on.

There are 5 basic steps to building a Mac custom definition.  First, you need to create the custom definition and add in the Properties Details.  Secondly, you need to create a detection rule and set the affected platform state.  The third step is to provide a script to do the detection work, add that to the Custom Script panel. The forth step is to specify the repair process in the Patch Information panel.  Lastly, you need to provide Patch Install Commands to make the changes necessary if you initiate a repair.

  1. Create a custom definition by clicking on the green circle with a white plus symbol when inside the Custom Definition dropdown panel screen-shot-2017-02-03-at-1-19-16-pm
  2. Enter in your desired information on the General tab and Description tab, like the severity and notes around what the custom definition will do.  Properties Panel.png
  3. Click the Add button under Detection Rules panel and specify your Affected Platforms.  I check both Mac OS X and Mac OS X Server.Affected Platforms.png
  4. Now you need to add in your detection logic in the Custom Script panel.  For the AutoBoot feature, we really only need two lines.  We need to specify the shebang environment and we need to capture the AutoBoot value.  Now, I have added a few extra lines for documentation, which you can leave to assist your coworkers.  My scripts are all pasted below or available on GitHub.  Also, in every custom definition, you need to return the Found state, Reason state, Expected state and a Detected State of either 0 or 1.  I don’t get into the details of this, so for more info see the Interchange Presentation regarding Custom Definitions.Detection Logic.png
  5. Finally, we need to add in the repair logic on the Patch Install Commands.  Patch Install Commands.png

That’s all there is to it.  Just hit OK at this point.

Now, if you’re wondering why I didn’t add in some Uninstall logic to revert our change back, if we desire, it is because the Mac agent doesn’t support it at this time.  Feel free to put in a request with Product Management if you think this would be helpful.

Scripts

Detection Logic
#!/bin/sh

# autoBootNVRAMDetection.sh
# Created by Bennett Norton on 2/2/17.
# Detects the state of AutoBoot set in the NVRAM

# nvram AutoBoot will call and obtain the value for just the AutoBoot variable
# calling nvram -px will show all values and put the output in an XML format
# awk filters out the AutoBoot text and leaves us with just the value

autoBoot=( $( nvram AutoBoot| awk '{print $2}') )

# compare the nvram state with your desired state
# a value of %00 means the autoboot is disabled
# a value of %03 means the autoboot is enabled
# any other value means the autoboot state is undefined

if [[ $autoBoot == *"%00"* ]] ; then
 echo "Found: NVRAM AutoBoot value is $autoBoot"
 echo "Reason: NVRAM AutoBoot value is $autoBoot"
 echo "Expected: NVRAM AutoBoot to be disabled or set to %00"
 echo "Detected: 0"
exit 0
else
 echo "Found: NVRAM AutoBoot value is $autoBoot"
 echo "Reason: NNVRAM AutoBoot value is $autoBoot"
 echo "Expected: NVRAM AutoBoot to be disabled or set to %00"
 echo "Detected: 1"
exit 1
fi
Disable Logic
#!/bin/sh

# autoBootNVRAMDisable.sh
# Created by Bennett Norton on 2/2/17.
# Sets the AutoBoot state in the NVRAM

# nvram AutoBoot=### sets the state
# a value of %00 means the autoboot is disabled
# a value of %03 means the autoboot is enabled

nvram AutoBoot=%00
Enable Logic

While I don’t use the next script in the custom definition, if you wanted to enable the setting for all machines, you’d use this script instead.

#!/bin/sh

# autoBootNVRAMEnable.sh
# Created by Bennett Norton on 2/2/17.
# Sets the AutoBoot state in the NVRAM

# nvram AutoBoot=### sets the state
# a value of %00 means the autoboot is disabled
# a value of %03 means the autoboot is enabled

nvram AutoBoot=%03

 

Efficiently Transfer Files to an OS X Device with SDClient

Have you ever needed to copy a file from a share to a more than one Mac in your environment?  My guess is the answer to that is yes, I know it was for the potential customer I spoke with on the phone today.  Whether you’re trying to apply a configuration file for a package, settings for a proxy server, VPN configuration files or any of the myriad of other reasons, what you’re transferring isn’t the important question, it’s how do you do it.

Luckily sdclient, the tool that is the brains behind all things software distribution for the Mac, has a bunch of goodness via command line switches that can be used to download files and place them into specific locations; all the while still taking advantage of the download technologies built into the agent.

To leverage sdclient, we’ll write a shell script that will tell sdclient what file to download and where to place it.  The entire script is very short.  There will be two variables, one for the source file location and the second for the destination location.

The only thing you need to really pay attention to in regards to the source location is to ensure the file is accessible via http.  You can setup a variable or just supply the location.  I like to create a variable so that the code can be better documented and easier to read for others.  Here is my source variable.

fileToCopy="http://ldserver.ldlab.org/SoftwareDist/MacPackages/ExampleFile.txt"

We’ll repeat the process for the destination location.

destinationLocation="/Path/To/Your/Destination/Folder"

In addition to the destination variable, the script will include a quick check to ensure the destination folder exists on the end node and if not, create it.

if [ ! -d "$destinationLocation" ]; then
echo "Location doesn't exist.  Creating directory"
mkdir $destinationLocation
echo "$destinationLocation created"
fi

The actual download and placement of the file will be done by sdclient with three switches: -noinstall, -package and –destdir.  The switch names are pretty self-explanatory, the –noinstall tells sdclient to not execute the file that will be downloaded.  The –package switch is where you insert the path to the source file available, again available on the http share.  Lastly, the –destdir switch tells sdclient where to place the file on the Mac client.

All done, your command sdclient command should look something like:

/Library/Application\ Support/LANDesk/bin/sdclient -noinstall -package "$fileToCopy" -destdir "$destinationLocation"

Here is the entire example script.

#!/bin/sh
#  FileTransfer.sh
#  Created by Bennett Norton on 5/16/16.
#  This script will copy a file from the source destination and place it on the Mac into the destination folder
#  Change the path variables

#File to copy
#change this to match your hosted path, it needs to be http
fileToCopy="http://ldserver.ldlab.org/SoftwareDist/MacPackages/ExampleFile.txt"

#Location to copy file to
#change this to match your destination path
destinationLocation="/Path/To/Your/Destination/Folder "

#Check to see if destination exists and if not, create it
if [ ! -d "$destinationLocation" ]; then
echo "Location doesn't exist.  Creating directory"
mkdir $destinationLocation
echo "$destinationLocation created"
fi

#Download and execute command
#You shouldn't need to make any changes here
#-noinstall ensure the package does not get executed
#-package is the source url path
#-destdir is the destination url path
/Library/Application\ Support/LANDesk/bin/sdclient -noinstall -package "$fileToCopy" -destdir "$destinationLocation"

As discussed in previous posts, save this file as a .sh file and set the execute permission on it by running the command below.

sudo chmod +x /path/to/script.sh

Once you’ve set the execute permissions, copy the script to your package repository and create a LANDESK Software Distribution package to deploy.

Creating LANDESK Management Suite Mac Packages

  1. Open the LANDESK Console
  2. Navigate to the top menu bar, select Tools > Distribution > Distribution Packages.
  3. In the lower left menu tree, highlight My Packages or Public Packages from within the Distribution Packages window
  4. On the Distribution menu bar, press the New Package button and select New Macintosh Package.
  5. Give the package a name
  6. Provide a description as well as any metadata information desired
  7. Set the primary file to the script file you previously transferred to your package share
  8. Fill out the Metadata details if desired, specifically supplying a logo so it shows up properly in the portal
  9. Save the package

Creating a Scheduled Mac Software Distribution Task

  1. Right click on the Mac software distribution package created and select Create Scheduled Task
  2. From the network view, select and drag the desired machine(s), user(s) or query(ies) and drop them onto the task
  3. Now, right click on the task and select properties
  4. Set the desired Task type under Task Settings as to whether you want a push, a policy or a hybrid of the two types in a policy-supported push
  5. Set the radio button in the Portal Settings to either Recommended or Optional if you desire to put the package into Workspaces.  If you’d like to automatically deploy the app, select Run automatically
  6. Change the Reboot Settings or Distribution and Patch settings if desired
  7. Set the schedule task settings with the appropriate start time

 

Automating the Mundane…Scripting for VMWare Fusion Efficiency

Growing up, it was not uncommon to hear someone quote the phrase “you tell me what you think about when you do not have to think, and I’ll tell you what you are.”  It’s a quote that can be deep, philosophical and ignite some serious introspection.

For me, the answer is easy.  It’s efficiency.  My brain is constantly chewing on how to make whatever insufferable process I’ve been experiencing in the last hour, day, week, etc; more palatable, more efficient, less…well, less sufferable.

Now, I know that declaring war on inefficiency should not be humanity’s primary purpose in life; not everything is a race to the finish line with as limited wasted movement as possible, but tell that to some other guy who’s brain doesn’t dissect every tiny amount of wasted time as potential opportunity for improvement.

When a former employer was asked by a potential new employer what my biggest weakness was, he responded with “well, I don’t know if this is exactly a weakness, but Bennett will constantly be looking for a way to improve a process, to make things more streamlined, even if he spends weeks devising a plan to save a minute’s worth of work during an 8 hour work day.”

Personally I hear that and I think, “wow, look how inefficient I’m being on spending such time to save so little.”

Nonetheless, hear I sit, a self-proclaimed efficiency hunter ready to tell you how I spent last week efficiency hunting within my daily workflow, to save not only time, but frustration and to improve the consistency of my work.

My daily routine as a LANDESK Sales Engineer consists of demonstrating one or more of our products to potential customers.  Due to the number of different products desired to be seen and the potential use cases from the customer that may require an integration demo, I may have up to 8 different virtual machines that need to be spun up.

In order to maintain consistency in my demo environment, I will take snapshots of each VM so I can demo the full capabilities of the software products and quickly reset back to square one for the next demo.

As such, I’m often starting a number of machines, stopping a number of machines, snapshotting them, reverting to snapshots, deleting old snapshots and even just needing to see what snapshots I’ve created.  All of this can be a bit cumbersome when you do it many times a day.

So when I received my new MacBook Pro last week, my efficiency brain kicked in, it was time to automate the entire process.  Luckily for me, VMWare has a utility that allows command line access to do all of the starting and stopping of the machines, as well as the snapshot management.

Perfect right?  Well almost, I didn’t want to write my own script, I wanted to just borrow someone else’s.  Alas, I scoured page one and even page 2 of Google (I know, page 2!) for a number of different search criteria hoping to find a hit, only to come away empty handed.

My efficiency brain wouldn’t let me just quit and give up though.  So I went to work and spent from 9 PM to 3 AM writing my own script and am now making that script available to you for your own efficiency pleasure.

Enjoy!  All you should have to do is fill out the variables at the top and you’ll soon be on your way to VMWare Fusion Management efficiency bliss.  I’ve saved my script as a .command file so I can execute directly from my desktop.

#/bin/bash 


# Version history 
# v1.0 - initial release
# 

# Add the paths to all of your VMs
declare -a arrayPathForVMs=("Documents/VMs/LDSERVER/LDSERVER.vmx" "Documents/VMs/OSX/OSX.vmx" "Documents/VMs/Win8/Win8.vmx")


# Create a directory location variable
vmrunPath="/Applications/VMware Fusion.app/Contents/Library/vmrun"
setScriptPath="$HOME"


while :
do
 clear
 cat <<EOF
 =========================================
 VM Fusion Management
 -----------------------------------------
 Please enter your choice:
 
 (1) Start VMs
 (2) Revert to a Snapshot
 (3) Create a Snapshot
 (4) Delete a Snapshot
 (5) List Snapshots
 (6) Suspend all VMs
 (7) Exit
 
 -----------------------------------------
EOF
 read -n1 -s
 case "$REPLY" in
 

 "1")
 echo "Starting your VMs..."
 cd "${setScriptPath}"
 for i in "${arrayPathForVMs[@]}"; 
 do
 echo "Launching" "$i"
 "${vmrunPath}" -T fusion start "${i}";
 done
 echo "All VMs started."
 Sleep 2
 exit 0
 ;;

 "2")
 echo -n "Which snapshot do you want to revert to?"
 read snapshotName
 cd "${setScriptPath}"
 for i in "${arrayPathForVMs[@]}"; 
 do
 echo "Reverting to" "$snapshotName" "on" "$i"
 "${vmrunPath}" -T fusion revertToSnapshot "${i}" "${snapshotName}";
 done
 echo "All VMs reverted."
 Sleep 2
 exit 0
 ;;

 "3") 
 echo -n "What will the snapshot name be?"
 read newSnapshotName
 cd "${setScriptPath}"
 for i in "${arrayPathForVMs[@]}"; 
 do
 echo "Creating" "$newSnapshotName" "on" "$i"
 "${vmrunPath}" -T fusion snapshot "${i}" "${newSnapshotName}";
 done
 echo "Snapshots created for all VMs"
 Sleep 2
 exit 0
 ;;

 "4")
 echo -n "Are you sure you want to delete a snapshot (y/n)? "
 read answer
 if echo "$answer" | grep -iq "^y" ;then
 echo -n "What snapshot do you want to delete?"
 read snapshotToDelete
 cd "${setScriptPath}"
 for i in "${arrayPathForVMs[@]}"; 
 do
 echo "Deleting" "$snapshotToDelete" "on" "$i"
 "${vmrunPath}" -T fusion deleteSnapshot "${i}" "${snapshotToDelete}";
 done
 echo "Snapshot deleted for all VMs"
 read -p "Press [Enter] to close."
 exit 0
 else
 echo "No changes have been made."
 read -p "Press [Enter] to close."
 exit 0
 fi
 ;;

 "5")
 echo "Listing your snapshots..."
 for i in "${arrayPathForVMs[@]}"; 
 do
 echo "Snapshots for" "$i"
 "${vmrunPath}" -T fusion listSnapshots "${setScriptPath}/""${i}";
 done
 echo "All snapshots displayed"
 read -p "Press [Enter] to close."
 exit 0
 ;;
 
 
 
 "6")
 echo "Suspending your VMs..."
 cd "${setScriptPath}"
 for i in "${arrayPathForVMs[@]}"; 
 do
 echo "Suspending" "$i"
 "${vmrunPath}" -T fusion suspend "${i}";
 done
 echo "All VMs suspended."
 Sleep 2
 exit 0

 ;;
 
 "7")
 echo "Exiting..."
 exit 0

 ;;
 
 "Quit")
 break
 ;;

 *) echo invalid option;;
 esac
done

The 3 Step Process of Bundling Scripts with Pkgbuild for a Payload-less Package Deployment

We all love Terminal and its simplicity, right?  After all, that’s why we’ve written scripts to help us in our enterprise Mac management, just so we can spend more time in Terminal.

Can you sense my sarcasm?

While Terminal is definitely simple, it’s quite probable that it’s not your love unless you’re a programmer or have a programming background. For the rest of us, Terminal is the place we go when we’re Googling how to accomplish some task; because the instructions we find have been written by a Terminal lover — despite the fact there is quite likely a fantastic graphical interface method to use.

Well, today is no different.  Chances are you’re a LANDESK administrator and found this page because you want to figure out how to deploy a script you’ve written and the easiest way to do that is to push a package inside of LANDESK’s Management Suite.

To convert our script into a package, we’re going to use Terminal and Apple’s pkgbuild command line tool.

Should I preface now there are graphical options to accomplish what we’re going to do? See Iceberg.  Apple, however, has deprecated their graphical package builder, PackageMaker, relegating it to the far flung corners of their developer website, making it difficult to even find.

Since there are a number of blogs explaining the granular details around pkgbuild available on the Internet, The Grey Blog being one of them, I’m only going to focus on the basics of creating a payload-less package using the -nopayload option on pkgbuild.

As outlined in the man pages for pkgbuild, the -nopayload option “indicates that the package will contain only scripts, with no payload.”  In other words, we’re not installing bits, we’re simply going to invoke some commands the OS can interpret as prescribed in our scripts bundled inside the package.

Using the example from the previous blog post, we’re going to take the script we wrote to create an XML file that the LANDESK inventory scanner can pick up and deliver to the LANDESK core server.  However, any script will work with the steps below, so manipulate as needed.

Our 3 step process is as follows:

  1. Create the folder structure and build script for pkgbuild
  2. Write your script
  3. Create the package
Step 1 – Create the Folder Structure and Build Script for PkgBuild

Alright, let’s create a folder to house our scripts.  In my example, using Finder, I’m going to create a new folder on my Desktop called SMART HD Detection.  Secondly, I’m going to create a second folder inside my SMART HD Detection folder titled ‘scripts’.

Using TextWrangler or Xcode or some other text editor, I need to create a blank file called postinstall and save it to the scripts folder.  We’ll come back to it later.

Now I need to create a my pkgbuild script.  Again, using TextWrangler or Xcode, create a file  titled package_the_script.sh and save it to the primary folder you created, in my example, the SMART HD Detection.

SMARTHDDetection

We will now add the requisite pkgbuild code to create a payload-less inside the package_the_script.sh script.  This script will be quite generic and essentially reusable for all of the packages you need to create now and in the future.

The code is:


PKG_ID=Gather_SMART_Disk_Status

sudo pkgbuild --identifier com.appleintheenterprise.$PKG_ID --nopayload --scripts ./scripts ./$PKG_ID.pkg

Alright, let’s break this down by the line of code.  Hopefully the #!/bin/bash is straight forward for you.

PKG_ID=Gather_SMART_Disk_Status is specifying a variable, PKG_ID, and it will be used as the name of the package we’re going to create.  You’ll want to replace Gather_SMART_Disk_Status with the desired name of your package.

The sudo pkgbuild has several arguments, which will break down individually. Please note, however, there are a number of other arguments you may want to add.  Again, refer to the man pages.

The –identifier is specifying you as the creator, so add in your domain or unique identifier bundled with the package ID.  The OS X Installer recognizes a package as being an upgrade to an already-installed package only if the package identifiers match, so it is advisable to set a meaningful, consistent identifier when you build the package.

The –nopayload option tells pkgbuilder we will be creating a payload-less package.

The –scripts ./scripts identifies the location of our script files that we want bundled up.

Now we can wrap everything up and name it ./$PKG_ID.pkg. Using the name variable allows us to reuse the same command line over and over.

Lastly, I need to save the script and mark it for execution by opening Terminal and browsing to my folder location.  In my instance, it’ll be ~/Desktop/“SMART HD Detection”  Once inside the folder structure, I’ll run the command “sudo chmod a+x package_the_script.sh”.

As can be seen, I didn’t sign this package.  If you need your package to work with Gatekeeper introduced in OS X 10.8, you’re going to need to use the –sign argument.

Step 2 – Write Your Script

Again, using TextWrangler or Xcode, I’m going to open the postinstall I created earlier and write my custom script into it.  My script is going to detect the status of the SMART HD.  However, you can write scripts to install printers, run software updates, reboot the machine, or any other number of tasks.  Just write or copy your script into the postinstall file and save it.

#!/bin/bash

OUTPUT_FILE="/Library/Application Support/LANDesk/CustomData/SmartHardDriveStatus.xml"

echo "&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;" &gt; "$OUTPUT_FILE"

echo "&lt;SMART_info&gt;" &gt;&gt; "$OUTPUT_FILE"

diskutil list | egrep "^/" | while read drive
do
     DRIVE=`basename $drive`
     STATUS=`diskutil info $drive | grep SMART | awk '{ $1=$2="" ;print $0 }'`
     echo "&lt;$DRIVE&gt; $STATUS &lt;/$DRIVE&gt;" &gt;&gt; "$OUTPUT_FILE"
done

echo "&lt;/SMART_info&gt;" &gt;&gt; "$OUTPUT_FILE"
Step 3 – Create the Package

OK, we’re nearly there.  All I need to do now is to execute the script ‘package_the_script.sh’ and it will run pkgbuild and create the package for us.

To do this, again open Terminal and browse to your folder structure you created.  Again, mine will be ~/Desktop/“SMART HD Detection”

Once there, type “sudo ./package_the_script.sh”.  So doing should create a package inside your folder with the name you provided under the PKG_ID variable.

That’s it, we’re all done.  We can now double click on our package inside of Finder and it will execute.

If you desire to push the script with LANDESK Management Suite to one or more machines, you just will need to zip the pkg file and copy it to your software distribution share.

To build the LANDESK software package that’ll distribute your shiny new package, do the following:

  • From the LANDESK Console, open Tools > Distribution > Distribution Packages
  • Inside the menu tree, highlight My Packages or Public Packages and then select the New Package button on the menubar and select New Macintosh Package
  • Give the package a name, description and point the primary file to the zip file created previously
  • Fill out the Metadata details if desired
  • Save the package

To create a task to deploy your LANDESK package, walk through the steps below:

  • Right click on the package created and select Create Scheduled Task
  • Target the desired machine(s), user(s) or query(ies)
  • Right click on the task and select properties
  • Set the desired Task type under Task Settings
  • If you desire the end user to be able to initiate the task, set the radio button in the Portal Settings to either Recommended or Optional, otherwise set it to Required and it will automatically begin the upgrade during the next maintenance window
  • Change the Reboot Settings on the task to one that forces a reboot
  • Schedule the task