Home > AutoPkg, Jamf Pro, JSSImporter, Scripting > Automating AutoPkg and JSSImporter setup

Automating AutoPkg and JSSImporter setup

As part of building my autopkg-conductor solution for automating AutoPkg runs, I also wanted to automate the setup of AutoPkg and JSSImporter. My colleague Graham Pugh has written a setup script for his environment, which I was able to adapt and extend for my own needs. For more details, please see below the jump.

This script is designed to set up a Mac running macOS 10.13.x or later with the following:

  • AutoPkg
  • JSSImporter
  • The AutoPkg recipe repos defined in the script.

The script checks to see if the following components are installed. If any are missing, they’re installed on an as-needed basis:

It also installs the following Python tools and modules on an as-needed basis:

The script also includes the following features:

  • The ability to set JSSImporter to use a Jamf Pro cloud distribution point as the master distribution point

Screen Shot 2018 07 10 at 9 37 35 AM

  • The ability to install either the latest release of JSSImporter or JSSImporter 0.5.1.

Screen Shot 2018 07 10 at 9 37 49 AM

 

The reason that JSSImporter 0.5.1 is set as a specific install option is that JSSImporter 1.0 does not currently support uploading to a Jamf Pro cloud distribution point. JSSImporter 0.5.1 does support uploading to a cloud distribution point, so while the upload issues are being worked out with JSSImporter 1.x, using the older JSSImporter 0.5.1 is the currently recommended workaround.

Once these tools and modules are installed, the script does the following:

1. Configures AutoPkg to use the recipe repos defined in the AutoPkg repos section.

Autopkg repos variable

 

2. Configures JSSImporter to connect to the desired Jamf Pro server with the correct distribution point settings.

This script should not be run with root privileges or you will receive the following warning:

Screen Shot 2018 07 10 at 10 46 07 AM

Instead, the script should be run by an account with sudo privileges, so that entering the account’s password will allow sudo to run specified processes with root privileges. If you try to run this script using an account without sudo privileges, you will receive the following warning:

Screen Shot 2018 07 10 at 11 33 52 AM

If the script is successfully run, the script output should look similar to what is shown below.

If a Jamf Pro cloud distribution point is set as the master distribution point:

Screen Shot 2018 07 13 at 6 11 00 AM

If a Jamf Pro file share distribution point is set as the master distribution point:

Screen Shot 2018 07 13 at 5 44 19 AM

The script is available below. It’s also available from GitHub using the following link:

https://github.com/rtrouton/autopkg_setup_for_jamf_pro

#!/bin/bash
# This script is designed to set up a Mac running macOS 10.13.x or later to be able to run the following:
#
# git
# AutoPkg
# JSSImporter
#
# It also installs the following Python tools and modules:
#
# pip
# cryptography
# requests (if not otherwise installed by AutoPkg or JSSImporter)
#
# Once these tools and modules are installed, the script configures AutoPkg
# to use the recipe repos defined in the AutoPkg repos section.
# Original script credits below:
# AutoPkg_Setup_for_JSS
# by Graham Pugh
# AutoPkg_Setup_for_JSS automates the installation of the latest version of AutoPkg and prerequisites for using JSS_Importer
# Acknowledgements
# Excerpts from https://github.com/grahampugh/run-munki-run
# which in turn borrows from https://github.com/tbridge/munki-in-a-box
# JSSImporter processor and settings from https://github.com/sheagcraig/JSSImporter
# AutoPkg SubDirectoryList processor from https://github.com/facebook/Recipes-for-AutoPkg
# ————————————————————————————– #
## Editable locations and settings
## AutoPkg repos:
#
# Enter the list of AutoPkg repos which need
# to be set up.
#
# All listed recipe repos should go between the two ENDMSG lines.
# The list should look similar to the one shown below:
#
# read -r -d '' autopkg_repos <<ENDMSG
# recipes
# rtrouton-recipes
# jss-recipes
# additional recipe repo
# another recipe repo
# https://github.com/username/recipe-repo-name-here.git
# ENDMSG
#
read -r -d '' autopkg_repos <<ENDMSG
ENDMSG
# If you choose to hardcode API information into the script, uncomment the lines below
# and set one or more of the following values:
#
# The username for an account on the Jamf Pro server with sufficient API privileges
# The password for the account
# The Jamf Pro URL
#jamfproURL="" ## Set the Jamf Pro URL here if you want it hardcoded.
#apiUser="" ## Set the username here if you want it hardcoded.
#apiPass="" ## Set the password here if you want it hardcoded.
# Jamf Pro distribution point account name and password, used by
# file share distribution points.
#
# In normal usage, this is sufficient to get access to the
# distribution point information stored in the Jamf Pro server.
#jamfdp_repo_name="" ## Set the distribution point repository name here if you want it hardcoded.
#jamfdp_repo_password="" ## Set the distribution point repository password here if you want it hardcoded.
# User Home Directory
userhome="$HOME"
# AutoPkg preferences file
autopkg_prefs="$userhome/Library/Preferences/com.github.autopkg.plist"
# Define log location
log_location="$userhome/Library/Logs/autopkg-setup-for-$(date +%Y-%m-%d-%H%M%S).log"
# If you're using a Jamf Pro cloud distribution point as your master distribution point,
# the cloud_distribution_point variable should look like this:
#
# cloud_distribution_point="yes"
#
# Otherwise, it should look like this:
#
# cloud_distribution_point=""
cloud_distribution_point=""
# If you need to install JSSImporter 0.5.1 because you're supporting a Jamf Pro
# cloud distribution point, the jssimporter051 variable should look like this:
#
# jssimporter051="yes"
#
# Otherwise, it should look like this:
#
# jssimporter051=""
jssimporter051=""
# ————————————————————————————– #
## No editing required below here
rootCheck() {
# Check that the script is NOT running as root
if [[ $EUID -eq 0 ]]; then
echo "### AutoPkg's user-level processes should not be run as root,"
echo "### so this script is NOT MEANT to run with root privileges."
echo ""
echo "### When needed, it will prompt for an admin account's password."
echo "### This will allow sudo to run specific functions using root privileges."
echo ""
echo "### Script will now exit. Please try running it again without root privileges."
echo ""
exit 4 # Running as root.
fi
}
adminCheck() {
# Check that the script is being run by an account with admin rights
if [[ -z $(id -nG | grep -ow admin) ]]; then
echo "### This script may need to use sudo to run specific functions"
echo "### using root privileges. The $(id -nu) account does not have"
echo "### administrator rights associated with it, so it will not be"
echo "### able to use sudo."
echo ""
echo "### Script will now exit."
echo "### Please try running this script again using an admin account."
echo ""
exit 4 # Running as root.
fi
}
# define ScriptLogging behavior
ScriptLogging(){
DATE=$(date +%Y-%m-%d\ %H:%M:%S)
LOG="$log_location"
echo "$DATE" " $1" >> $LOG
}
installCommandLineTools() {
# Installing the Xcode command line tools on 10.10 and later
echo "### Installing git via installing the Xcode command line tools…"
echo
osx_vers=$(sw_vers -productVersion | awk -F "." '{print $2}')
cmd_line_tools_temp_file="/tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress"
# Installing the latest Xcode command line tools on 10.10.x or later.
if [[ "$osx_vers" -ge 10 ]]; then
# Create the placeholder file which is checked by the softwareupdate tool
# before allowing the installation of the Xcode command line tools.
touch "$cmd_line_tools_temp_file"
# Identify the correct update in the Software Update feed with "Command Line Tools" in the name for the OS version in question.
cmd_line_tools=$(softwareupdate -l | awk '/\*\ Command Line Tools/ { $1=$1;print }' | grep "$osx_vers" | sed 's/^[[ \t]]*//;s/[[ \t]]*$//;s/*//' | cut -c 2-)
# Check to see if the softwareupdate tool has returned more than one Xcode
# command line tool installation option. If it has, use the last one listed
# as that should be the latest Xcode command line tool installer.
if (( $(grep c . <<<"$cmd_line_tools") > 1 )); then
cmd_line_tools_output="$cmd_line_tools"
cmd_line_tools=$(printf "$cmd_line_tools_output" | tail -1)
fi
# Install the command line tools
sudo softwareupdate -i "$cmd_line_tools" –verbose >> "$log_location" 2>&1
# Remove the temp file
if [[ -f "$cmd_line_tools_temp_file" ]]; then
rm "$cmd_line_tools_temp_file"
fi
else
echo "Sorry, this script is only for use on OS X/macOS >= 10.10"
fi
}
installAutoPkg() {
# Install the latest release of AutoPkg
autopkg_location_LATEST=$(curl https://api.github.com/repos/autopkg/autopkg/releases | python -c 'import json,sys;obj=json.load(sys.stdin);print obj[0]["assets"][0]["browser_download_url"]')
/usr/bin/curl -L -s "${autopkg_location_LATEST}" -o "$userhome/autopkg-latest.pkg"
ScriptLogging "Installing AutoPkg"
sudo installer -verboseR -pkg "$userhome/autopkg-latest.pkg" -target / >> "$log_location" 2>&1
ScriptLogging "AutoPkg Installed"
echo
echo "### AutoPkg Installed"
echo
}
installJSSImporter() {
# Install JSSImporter
if [[ "$jssimporter051" = "yes" ]]; then
# JSSImporter 0.5.1 is needed for now for Jamf Pro cloud distribution point support.
# Once JSSImporter 1.x is updated to support cloud DPs, this option will be removed.
JSSIMPORTER_051=$(curl https://api.github.com/repos/jssimporter/jssimporter/releases/1892051 | awk '/browser_download_url/ {print $2}' | sed 's/\"//g')
/usr/bin/curl -L -s "${JSSIMPORTER_051}" -o "$userhome/jssimporter.pkg"
ScriptLogging "Installing JSSImporter"
sudo installer -verboseR -pkg "$userhome/jssimporter.pkg" -target / >> "$log_location" 2>&1
else
# Install the latest release of JSSImporter by adding the
# rtrouton-recipes AutoPkg recipe repo and installing JSSImporter
# using the JSSImporter.install recipe available from that repo.
#
# Once installed, the rtrouton-recipes AutoPkg recipe repo is
# deleted from the Mac to avoid possibly causing issues when adding
# receipe repos later in the process.
autopkg repo-add rtrouton-recipes >> "$log_location" 2>&1
ScriptLogging "Installing JSSImporter"
autopkg run JSSImporter.install >> "$log_location" 2>&1
autopkg repo-delete rtrouton-recipes >> "$log_location" 2>&1
fi
ScriptLogging "JSSImporter Installed"
echo
echo "### JSSImporter Installed"
echo
}
installPythonPip() {
# Get Python Pip install tool
ScriptLogging "Installing Python Pip install tool"
sudo easy_install pip >> "$log_location" 2>&1
ScriptLogging "Pip Installed"
echo
echo "### Pip Installed"
echo
}
installPythonCryptographyModule() {
# Install pyopenssl to add the cryptography module
# needed by AutoPkg on macOS Sierra and later.
ScriptLogging "Installing Python PyOpenSSL module to add the cryptography module."
pip install -I –user pyopenssl >> "$log_location" 2>&1
ScriptLogging "PyOpenSSL Installed"
echo
echo "### PyOpenSSL Installed"
echo
}
installPythonRequestsModule() {
# Install the Python requests module.
ScriptLogging "Installing Python requests module."
pip install -I –user requests >> "$log_location" 2>&1
ScriptLogging "Requests Installed"
echo
echo "### Requests Installed"
echo
}
## Main section
# Make sure that the script is not being run as root.
rootCheck
# Make sure that the script is being run by an admin account.
adminCheck
# If the log file is not available, create it
if [[ ! -r "$log_location" ]]; then
touch "$log_location"
fi
# If the Jamf Pro URL, the account username or the account password aren't available
# otherwise, you will be prompted to enter the requested URL or account credentials.
if [[ -z "$jamfproURL" ]]; then
read -p "Please enter your Jamf Pro server URL : " jamfproURL
fi
if [[ -z "$apiUser" ]]; then
read -p "Please enter your Jamf Pro user account : " apiUser
fi
if [[ -z "$apiPass" ]]; then
read -p "Please enter the password for the $apiUser account: " -s apiPass
echo ""
if [[ $cloud_distribution_point = "yes" ]]; then
echo "Any follow-up password requests will be for sudo rights."
fi
fi
if [[ $cloud_distribution_point != "yes" ]]; then
if [[ -z "$jamfdp_repo_name" ]]; then
read -p "Please enter your Jamf Pro distribution point repository name : " jamfdp_repo_name
fi
if [[ -z "$jamfdp_repo_password" ]]; then
read -p "Please enter your Jamf Pro distribution point password : " -s jamfdp_repo_password
echo ""
echo "Any follow-up password requests will be for sudo rights."
fi
fi
echo ""
# Commands
autopkg_location="/usr/local/bin/autopkg"
defaults_location="/usr/bin/defaults"
jssimporter_location="/Library/AutoPkg/autopkglib/JSSImporter.py"
pip_location="/usr/local/bin/pip"
plistbuddy_location="/usr/libexec/PlistBuddy"
# Find git's installed location. There will be an executable stub
# binary available at /usr/bin/git, but that doesn't necessarily mean
# git is actually installed. Instead, without git installed, the stub
# binary will trigger a GUI window which requests the installation of
# install the Xcode command line tools.
# If Xcode.app is installed in /Applications, set /usr/bin/git as
# git's location.
if [[ -x "/Applications/Xcode.app/Contents/Developer/usr/libexec/git-core/git" ]]; then
git_location="/usr/bin/git"
# If the Xcode command line tools are installed, set /usr/bin/git as
# git's location.
elif [[ -x "/Library/Developer/CommandLineTools/usr/libexec/git-core/git" ]]; then
git_location="/usr/bin/git"
# If the standalone git is installed, set /usr/local/bin/git as
# git's location.
elif [[ -x "/usr/local/git/bin/git" ]]; then
git_location="/usr/local/bin/git"
# Otherwise, explicitly set git_location to be a null value.
# That will trigger the script to install the Xcode command line tools.
else
git_location=""
fi
# Check for Xcode command line tools and install if needed.
if [[ ! -x "$git_location" ]]; then
installCommandLineTools
else
ScriptLogging "Git installed"
echo "### Git Installed"
fi
# Check for Python pip installer tool and install if needed.
if [[ ! -x "$pip_location" ]]; then
installPythonPip
else
ScriptLogging "Pip installed"
echo "### Pip Installed"
fi
# Get AutoPkg if not already installed
if [[ ! -x ${autopkg_location} ]]; then
installAutoPkg "${userhome}"
# Clean up if necessary.
if [[ -e "$userhome/autopkg-latest.pkg" ]]; then
rm "$userhome/autopkg-latest.pkg"
fi
else
ScriptLogging "AutoPkg installed"
echo "### AutoPkg Installed"
fi
# Check for Python cryptography module and install if needed.
if [[ $(pip list | awk '/cryptography/ {print $1}') = "" ]]; then
installPythonCryptographyModule
else
ScriptLogging "Python cryptography module installed"
echo "### PyOpenSSL Installed"
fi
# Check for Python requests module and install if needed.
if [[ $(pip list | awk '/requests/ {print $1}') = "" ]]; then
installPythonRequestsModule
else
ScriptLogging "Python requests module installed"
echo "### Requests Installed"
fi
# Check for JSSImporter and install if needed
if [[ ! -x "$jssimporter_location" ]]; then
installJSSImporter
# Clean up if necessary
if [[ -e "$userhome/jssimporter.pkg" ]]; then
rm "$userhome/jssimporter.pkg"
fi
else
ScriptLogging "JSSImporter installed"
echo "### JSSImporter Installed"
fi
if [[ -x ${autopkg_location} ]] && [[ $(pip list | awk '/cryptography/ {print $1}') = "cryptography" ]] && [[ $(pip list | awk '/requests/ {print $1}') = "requests" ]] && [[ -x "$jssimporter_location" ]]; then
ScriptLogging "AutoPkg and JSSImporter verified as installed. All necessary Python modules verified as installed."
echo
echo "### AutoPkg and JSSImporter verified as installed."
echo "### All necessary Python modules verified as installed."
# Add AutoPkg repos (checks if already added)
${autopkg_location} repo-add ${autopkg_repos} >> "$log_location" 2>&1
# Update AutoPkg repos (if the repos were already there no update would otherwise happen)
${autopkg_location} repo-update ${autopkg_repos} >> "$log_location" 2>&1
ScriptLogging "AutoPkg Repos Configured"
echo
echo "### AutoPkg Repos Configured"
# Configure JSSImporter with the following information:
#
# Jamf Pro address
# Jamf Pro API account username
# Jamf Pro API account username
${defaults_location} write com.github.autopkg JSS_URL "${jamfproURL}" >> "$log_location" 2>&1
${defaults_location} write com.github.autopkg API_USERNAME ${apiUser} >> "$log_location" 2>&1
${defaults_location} write com.github.autopkg API_PASSWORD ${apiPass} >> "$log_location" 2>&1
# Remove any existing Jamf Pro distribution point settings
${plistbuddy_location} -c "Delete :JSS_REPOS array" ${autopkg_prefs} >> "$log_location" 2>&1
if [[ "$cloud_distribution_point" = "yes" ]]; then
# Add Cloud Distribution Point (CDP) to the JSSImporter settings.
${plistbuddy_location} -c "Add :JSS_REPOS array" ${autopkg_prefs} >> "$log_location" 2>&1
${plistbuddy_location} -c "Add :JSS_REPOS:0 dict" ${autopkg_prefs} >> "$log_location" 2>&1
${plistbuddy_location} -c "Add :JSS_REPOS:0:type string CDP" ${autopkg_prefs} >> "$log_location" 2>&1
else
# Add the distribution point repository name and repository password
# to the JSSImporter settings, which is necessary to access the file
# share distribution point info stored in your Jamf Pro server.
${plistbuddy_location} -c "Add :JSS_REPOS array" ${autopkg_prefs} >> "$log_location" 2>&1
${plistbuddy_location} -c "Add :JSS_REPOS:0 dict" ${autopkg_prefs} >> "$log_location" 2>&1
${plistbuddy_location} -c "Add :JSS_REPOS:0:name string ${jamfdp_repo_name}" ${autopkg_prefs} >> "$log_location" 2>&1
${plistbuddy_location} -c "Add :JSS_REPOS:0:password string ${jamfdp_repo_password}" ${autopkg_prefs} >> "$log_location" 2>&1
fi
ScriptLogging "AutoPkg and JSSImporter configured and ready for use."
echo
echo "### AutoPkg and JSSImporter configured and ready for use with the following repos. For setup details, please see $log_location."
echo "$(autopkg repo-list)"
else
ScriptLogging "AutoPkg and JSSImporter not installed properly."
echo
echo "### AutoPkg and JSSImporter not installed properly. For setup details, please see $log_location."
fi

  1. kevind
    July 13, 2018 at 6:03 pm

    is there an alternative for jssimporter to munki? I know that the previous post was inspired by autopkgr’s issues on 10.13.5, so I’m looking into alternatives for that (we’re still on 10.13.4 on the mac currently running autopkgr). will probably end up using a launchd item or cronjob to do the scheduling

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: