From dc2725e4e752a95d4c4bbf8be89364ec2cb0cb85 Mon Sep 17 00:00:00 2001 From: macmule Date: Tue, 26 Mar 2024 18:04:26 +0000 Subject: [PATCH] Relocate MunkiStatus.app and Munki-notifier.app to ../Contents/Helpers/ from ../Contents/Resources/ - Munki6dev base (#1207) * Relocate MunkiStatus.app and Munki-notifier.app to ../Contents/Helpers/ from ../Contents/Resources/ - Updated location of munki-notifier in code/apps/Managed Software Center/Managed Software Center/Controllers/MainWindowController.swift - Added code/client/installhelper script - Amended code/tools/make_munki_mpkg.sh with new locations for munki-notifier and MunkiStatus as well as changes required to leverage `installhelper` - Amended code/tools/pkgresources/Scripts_app_usage/postinstall to leverage `installhelper` - Deleted code/tools/pkgresources/Scripts_app_usage/preinstall as the actions within should be handled now by `installhelper` - Amended code/tools/pkgresources/Scripts_launchd/postinstall to leverage `installhelper` - Amended launchd/LaunchAgents/com.googlecode.munki.munki-notifier.plist to use the new path to munki-notifier.app - Amended launchd/LaunchAgents/com.googlecode.munki.MunkiStatus.plist to use the new path to MunkiStatus.app This is a resubmission of https://github.com/munki/munki/pull/1203, which needed it's base branch changing from `main` to `Munki6dev` * Update installhelper - Removed CHECK_TIME global - https://github.com/munki/munki/pull/1207/files/374fbaf9220144740d0d0cef5acba20fd6ac554a#r1515000516 - Remove erroneous login window comments - https://github.com/munki/munki/pull/1207/files/374fbaf9220144740d0d0cef5acba20fd6ac554a#r1515006835 and https://github.com/munki/munki/pull/1207/files/374fbaf9220144740d0d0cef5acba20fd6ac554a#r1515006962 - Simplified IF condition - https://github.com/munki/munki/pull/1207/files/374fbaf9220144740d0d0cef5acba20fd6ac554a#r1515005565 this was in place incase LimitLoadToSessionType contained multiple values (as it can). * Update installhelper - Reverted changes made for - https://github.com/munki/munki/pull/1207/commits/374fbaf9220144740d0d0cef5acba20fd6ac554a#r1515005565 - Changed constant/global PASSED_ARG to local: launchd_group - https://github.com/munki/munki/pull/1207#discussion_r1515002646 and https://github.com/munki/munki/pull/1207#discussion_r1515002968 * Update installhelper * Update installhelper * Update installhelper * Update installhelper * Update make_munki_mpkg.sh Amended so that the launchd pkg is installed by default --- .../Controllers/MainWindowController.swift | 4 +- code/client/installhelper | 484 ++++++++++++++++++ code/tools/make_munki_mpkg.sh | 32 +- .../Scripts_app_usage/postinstall | 35 +- .../pkgresources/Scripts_app_usage/preinstall | 29 -- .../pkgresources/Scripts_launchd/postinstall | 60 +-- .../com.googlecode.munki.MunkiStatus.plist | 2 +- .../com.googlecode.munki.munki-notifier.plist | 2 +- 8 files changed, 529 insertions(+), 119 deletions(-) create mode 100755 code/client/installhelper delete mode 100755 code/tools/pkgresources/Scripts_app_usage/preinstall diff --git a/code/apps/Managed Software Center/Managed Software Center/Controllers/MainWindowController.swift b/code/apps/Managed Software Center/Managed Software Center/Controllers/MainWindowController.swift index 02fbe456..a6cb55cc 100755 --- a/code/apps/Managed Software Center/Managed Software Center/Controllers/MainWindowController.swift +++ b/code/apps/Managed Software Center/Managed Software Center/Controllers/MainWindowController.swift @@ -961,8 +961,8 @@ class MainWindowController: NSWindowController, NSWindowDelegate, WKNavigationDe // we can't remove them directly since we didn't actually post them // so we can't use // NSUserNotificationCenter.default.removeAllDeliveredNotifications() - let munkiNotifierPath = Bundle.main.path(forResource: "munki-notifier", ofType: "app") - if let munkiNotifierPath = munkiNotifierPath { + let munkiNotifierPath = Bundle.main.bundlePath + "/Contents/Helpers/munki-notifier.app" + if FileManager.default.fileExists(atPath: munkiNotifierPath) { NSLog("munki-notifier path: %@", munkiNotifierPath as String) // now make sure it's not already running let executablePath = munkiNotifierPath + "/Contents/MacOS/munki-notifier" diff --git a/code/client/installhelper b/code/client/installhelper new file mode 100755 index 00000000..9996fd4c --- /dev/null +++ b/code/client/installhelper @@ -0,0 +1,484 @@ +#!/usr/local/munki/munki-python +# encoding: utf-8 +# +# Copyright 2011-2024 Greg Neagle. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +installhelper + +Created 2024-02-28. + +A helper tool for handling launchd items when installing Munki + +""" +from __future__ import absolute_import + +# standard libs +import glob +import os +import logging +import logging.handlers +import re +import subprocess +import time +import sys +from pathlib import Path + +# Append munki's path, to load our libs when not running under munki +# pylint: disable = C0413 +sys.path.append('/usr/local/munki') + +# our libs +from munkilib import osutils +from munkilib import prefs +from munkilib import FoundationPlist + +# globals +LAUNCHD_PREFIX = 'com.googlecode.munki.' +APPUSAGE_AGENT = LAUNCHD_PREFIX + 'app_usage_monitor' +APPUSAGE_DAEMON = LAUNCHD_PREFIX + 'appusaged' +INSTALL_HELPER = LAUNCHD_PREFIX + 'installhelper' +PROG_NAME = 'managedsoftwareupdate' +APP_NAME = 'installhelper' +APP_VERSION = '0.1' + + +def main(): + '''Main function''' + + # If INSTALLHELPER_RUN_TYPE isn't set + if not os.environ.get('INSTALLHELPER_RUN_TYPE'): + # Set launchd_group to the first value passed + launchd_group = sys.argv[1].lower() + # If INSTALLHELPER_RUN_TYPE is set and we have a valid value passed + elif (os.environ.get('INSTALLHELPER_RUN_TYPE') == 'appusage' or + os.environ.get('INSTALLHELPER_RUN_TYPE') == 'launchd'): + # Set launchd_group to the value of INSTALLHELPER_RUN_TYPE + launchd_group = os.environ.get('INSTALLHELPER_RUN_TYPE') + # If we've got here, something isn't right + else: + # Error message + logging.info("ERROR: Cannot ascertain correct value for passed argument") + # Exit + sys.exit(1) + + # Setup logging + setup_logging() + + # If not launched via launchd + if not os.environ.get('INSTALLHELPER_RUN_TYPE'): + # Launched manually + logging.info("Launched manually - arg: %s", launchd_group) + create_launch_daemon(launchd_group) + # If launched via launchd + else: + # Launched via launchd + logging.info("Launched via launchd - arg: %s", launchd_group) + process_munki_launchd(launchd_group) + + +def create_launch_daemon(launchd_group): + '''Creates and loads the launch daemon''' + + # Set name and path based on the value of launchd_group + launch_daemon_name = 'com.googlecode.munki.installhelper-' + launchd_group + launch_daemon_path = '/Library/LaunchDaemons/' + launch_daemon_name + '.plist' + + # Progress notification + logging.info("Creating launch daemon") + + # Retrieve all running launch daemons + cmd = ['/bin/launchctl', 'list'] + cmd_out = subprocess.run(cmd, capture_output = True, check = False) + launchd_labels = split_launchctl_list(cmd_out) + + # Check to see if launch_daemon_name is already loaded, and stop if so + if launch_daemon_name in launchd_labels: + # Stop the launch daemon at the login window + cmd = ['/bin/launchctl', 'bootout', 'system/' + launch_daemon_name] + subprocess.call(cmd) + + # Populate launch deamon dict + launch_daemon = {} + launch_daemon['EnvironmentVariables'] = {'INSTALLHELPER_RUN_TYPE': launchd_group} + launch_daemon['Label'] = launch_daemon_name + launch_daemon['ProgramArguments'] = ['/usr/local/munki/installhelper'] + launch_daemon['RunAtLoad'] = True + + # Create the launch daemon + FoundationPlist.writePlist(launch_daemon, launch_daemon_path) + + # Set the launch daemons owner and perms + os.chown(launch_daemon_path, 0, 0) + os.chmod(launch_daemon_path, int('644', 8)) + + # Load the launch daemon + logging.info("Starting: %s", launch_daemon_path) + cmd = ['/bin/launchctl', 'bootstrap', 'system', launch_daemon_path] + subprocess.call(cmd) + + +def get_logged_in_users(): + '''Returns a dict containing any logged in users uid and username''' + + # Var declaration + user_details = {} + + # Retrieve details of all running processes + cmd = ['/bin/ps', '-axo', 'uid,login,args'] + cmd_out = subprocess.run(cmd, capture_output = True, check = False) + # Split out the above output + for some_process in cmd_out.stdout.decode().splitlines(): + # Retrieve details for users that are running loginwindow.app, excluding root + if "loginwindow.app" in some_process.lower() and some_process.split()[0] != "0": + # Capture the userid and username for all users running the loginwindow + user_details[some_process.split()[0]] = some_process.split()[1] + + # Returns either an empty dict, or a dict with userid and usernames + return user_details + + +def is_managedsoftwareupdate_running(): + '''If managedsoftwareupdate is running, check again in x seconds''' + + # Check to see if managedsoftwareupdate is running + managedsoftwareupdate_pid = osutils.pythonScriptRunning(PROG_NAME) + + # An instance of managedsoftwareupdate is running, so we need to try again later + while managedsoftwareupdate_pid: + logging.info("*" * 60) + logging.info("%s is running as pid %s.", managedsoftwareupdate_pid, os.getpid()) + logging.info("checking again in 10 seconds") + logging.info("*" * 60) + time.sleep(10) + + # If managedsoftwareupdate is not running.. return from function to proceed + logging.info("%s is not running, proceeding...", (PROG_NAME)) + + +def process_launch_daemons(launch_daemons, launchd_group, loginwindow_launchds): + '''Processes Munki's Launch Daemons''' + + # Progress notification + logging.info("Processing Launch Daemons") + + # Var declaration + matched_labels = [] + + # Retrieve all running launch daemons + cmd = ['/bin/launchctl', 'list'] + cmd_out = subprocess.run(cmd, capture_output = True, check = False) + launchd_labels = split_launchctl_list(cmd_out) + + # For each plist in /Library/LaunchDaemons/ prefixed with LAUNCHD_PREFIX + for launch_daemon in launch_daemons: + try: + # Make sure content is valid, before proceeding to reload + daemon_content = FoundationPlist.readPlist(launch_daemon) + except FoundationPlist.NSPropertyListSerializationException: + break + # Get the Label + daemon_label = daemon_content.get('Label') + # If we have a label and it's not an INSTALL_HELPER launchd item + if daemon_label and not INSTALL_HELPER in daemon_label: + # Check to see if the launch daemon is loaded, before stopping + if daemon_label in launchd_labels: + # Stop the launch daemon + logging.info("Stopping: %s", launch_daemon) + cmd = ['/bin/launchctl', 'bootout', 'system/' + daemon_label] + subprocess.call(cmd) + # Load the launch daemon + logging.info("Starting: %s", launch_daemon) + cmd = ['/bin/launchctl', 'bootstrap', 'system', launch_daemon] + subprocess.call(cmd) + # Append the launchd items label to matched_labels + matched_labels.append(daemon_label) + + # If we're to interact with all non-appusage launchd items + if launchd_group == 'launchd': + # For each label in launchd_labels + for launchd_label in launchd_labels: + # If we have a label, it's not in matched_labels or loginwindow_launchds, + # and it's not an APPUSAGE_DAEMON or a INSTALL_HELPER launchd item + if (launchd_label not in matched_labels + loginwindow_launchds + [APPUSAGE_DAEMON] + and not launchd_label.startswith(INSTALL_HELPER)): + # Stop the launch daemon + logging.info("Stopping: %s", launchd_label) + cmd = ['/bin/launchctl', 'bootout', 'system/' + launchd_label] + subprocess.call(cmd) + + +def process_loginwindow_launch_agents(launch_agents): + '''Processes Munki's LoginWindow Launch Agents''' + + # Progress notification + logging.info("Processing LoginWindow Launch Agents") + + # Var declaration + loginwindow_launchds = [] + + # Get the labels for any launchd running at the LoginWindow, this will only list LoginWindow + # launch agents when ran at the LoginWindow + cmd = ['/bin/launchctl', 'dumpstate'] + cmd_out = subprocess.run(cmd, capture_output = True, check = False) + launchd_labels = re.findall("loginwindow/.*/(" + LAUNCHD_PREFIX + ".*) =", + cmd_out.stdout.decode()) + + # For each plist in /Library/LaunchAgents/ prefixed with LAUNCHD_PREFIX + for launch_agent in launch_agents: + try: + # Make sure content is valid, before proceeding to reload + agent_content = FoundationPlist.readPlist(launch_agent) + except FoundationPlist.NSPropertyListSerializationException: + break + # If we're to limit loading + if agent_content.get('LimitLoadToSessionType'): + # If the launch agent includes LimitLoadToSessionType, and it contains LoginWindow + if 'LoginWindow' in agent_content.get('LimitLoadToSessionType'): + # If the launch agent is to be loaded at the login window, get the Label + agent_label = agent_content.get('Label') + # If we have a label and it's not an INSTALL_HELPER launchd item + if agent_label and not INSTALL_HELPER in agent_label: + # Check to see if the launch agent is loaded, before stopping + if agent_label in launchd_labels: + # Stop the launch agent at the login window + logging.info("Stopping: %s", launch_agent) + cmd = ['/bin/launchctl', 'unload', '-S', 'LoginWindow', launch_agent] + subprocess.call(cmd) + # Load the launch agent at the login window + logging.info("Starting: %s", launch_agent) + cmd = ['/bin/launchctl', 'load', '-S', 'LoginWindow', launch_agent] + subprocess.call(cmd) + # Append the launchd items label to loginwindow_launchds + loginwindow_launchds.append(agent_label) + + # For each label in launchd_labels + for launchd_label in launchd_labels: + # If we have a label, it's not in loginwindow_launchds and it's not an INSTALL_HELPER + # launchd item + if (launchd_label not in loginwindow_launchds + and not launchd_label.startswith(INSTALL_HELPER)): + # Stop the launch agent + logging.info("Stopping: %s", launchd_label) + cmd = ['/bin/launchctl', 'bootout', 'loginwindow/' + launchd_label] + subprocess.call(cmd) + + # Returns loginwindow_launchds + return loginwindow_launchds + + +def process_munki_launchd(launchd_group): + '''Reload Munki's launchd''' + + # If we're to interact only with the appusage launchd items + if launchd_group == 'appusage': + # returns a list containing just the path to the app_usage_monitor launch agent + launch_agents = ['/Library/LaunchAgents/' + APPUSAGE_AGENT+ '.plist'] + # returns a list containing just the path to the appusaged launch daemon + launch_daemons = ['/Library/LaunchDaemons/' + APPUSAGE_DAEMON + '.plist'] + + # If we're to interact with all non-appusage launchd items + if launchd_group == 'launchd': + # Returns a list of Munki's launch agents, excluding the APPUSAGE_AGENT agent + launch_agents = [launch_agent for launch_agent in + glob.glob('/Library/LaunchAgents/' + LAUNCHD_PREFIX + '*') if not + APPUSAGE_AGENT in launch_agent] + # Returns a list of Munki's launch daemons, excluding the APPUSAGE_DAEMON and + # INSTALL_HELPER launchd items + launch_daemons = [launch_daemon for launch_daemon in + glob.glob('/Library/LaunchDaemons/' + LAUNCHD_PREFIX + '*') if not + (APPUSAGE_DAEMON or INSTALL_HELPER) in launch_daemon] + + # Only proceed if PROG_NAME isn't running, looping until it's not running + is_managedsoftwareupdate_running() + + # Get the userid and username of any logged in users + user_details = get_logged_in_users() + + # If users are logged in + if user_details: + # If users are logged in, reload the required launch agents as them + process_user_launch_agents(launch_agents, launchd_group, user_details) + + # If we're not only looking to reload the appusage launchd's + if launchd_group != 'appusage': + # reload munki's loginwindow launch agents, returning a list of labels + loginwindow_launchds = process_loginwindow_launch_agents(launch_agents) + # If we're just looking to reload the appusage launchd's + else: + # Set to an empty list + loginwindow_launchds = [] + + # Reload launch daemons as needed + process_launch_daemons(launch_daemons, launchd_group, loginwindow_launchds) + + # Set name and path based on the value of launchd_group + launch_daemon_name = INSTALL_HELPER + '-' + launchd_group + launch_daemon_path = '/Library/LaunchDaemons/' + launch_daemon_name + '.plist' + + # If the launch daemon exists + if os.path.isfile(launch_daemon_path): + # Progress notification + logging.info("Completed tasks, tidying up") + # Delete the launch daemon + logging.info("Deleting: %s", launch_daemon_path) + os.unlink(launch_daemon_path) + # Unload the launch daemon + logging.info("Unloading: %s", launch_daemon_name) + cmd = ['/bin/launchctl', 'bootout', 'system/' + launch_daemon_name] + subprocess.call(cmd) + + +def process_user_launch_agents(launch_agents, launchd_group, user_details): + '''Processes Munki's user Launch Agents''' + + # For each logged in user + for userid, username in user_details.items(): + # Var declaration + matched_labels = [] + # Log who we're reloading the Launch Agents as + logging.info("Processing Launch Agents for: %s", username) + # Retrieve all running launch agents for the user + cmd = ['/bin/launchctl', 'asuser', str(userid), '/bin/launchctl', 'list'] + cmd_out = subprocess.run(cmd, capture_output = True, check = False) + launchd_labels = split_launchctl_list(cmd_out) + # For each plist in /Library/LaunchAgents/ prefixed with LAUNCHD_PREFIX + for launch_agent in launch_agents: + try: + # Make sure content is valid, before proceeding to reload + agent_content = FoundationPlist.readPlist(launch_agent) + except FoundationPlist.NSPropertyListSerializationException: + break + # If the launch agent doesn't contain LimitLoadToSessionType or + # LimitLoadToSessionType exists and it contains Aqua + if (not agent_content.get('LimitLoadToSessionType') or 'Aqua' in + agent_content.get('LimitLoadToSessionType')): + # If the launch agent is to be loaded at the login window, get the Label + agent_label = agent_content.get('Label') + # If we have a label and it's not an INSTALL_HELPER launchd item + if agent_label and not agent_label.startswith(INSTALL_HELPER): + # Check to see if the launch agent is loaded, before stopping + if agent_label in launchd_labels: + # Stop the launch agent + logging.info("Stopping: %s", launch_agent) + cmd = ['/bin/launchctl', 'asuser', str(userid), '/bin/launchctl', 'bootout', + 'gui/' + str(userid) + '/' + agent_label] + subprocess.call(cmd) + # Load the launch agent + logging.info("Starting: %s", launch_agent) + cmd = ['/bin/launchctl', 'asuser', str(userid), '/bin/launchctl', 'bootstrap', + 'gui/' + str(userid), launch_agent] + subprocess.call(cmd) + # Append the launchd items label to matched_labels + matched_labels.append(agent_label) + + # If we're to interact with all non-appusage launchd items + if launchd_group == 'launchd': + # For each label in launchd_labels + for launchd_label in launchd_labels: + # If we have a label, it's not in matched_labels and it's not an INSTALL_HELPER + # launchd item + if (launchd_label not in matched_labels + [APPUSAGE_AGENT] + and not launchd_label.startswith(INSTALL_HELPER)): + # Stop the launch agent + logging.info("Stopping: %s", launchd_label) + cmd = ['/bin/launchctl', 'asuser', str(userid), '/bin/launchctl', 'bootout', + 'gui/' + str(userid) + '/' + launchd_label] + subprocess.call(cmd) + + +def setup_logging(): + '''Configure logging''' + + # Creates the logging dir if doesn't exist + Path(os.path.dirname(prefs.pref('LogFile'))).mkdir(parents=True, exist_ok=True) + + # Store the log in the same directory as ManagedSoftwareUpdate.log + log_path = os.path.join(os.path.dirname(prefs.pref('LogFile')), APP_NAME + '.log') + + # Generic settings + log_level = logging.getLevelName('INFO') + + # Log format + log_format = logging.Formatter('%(asctime)s %(levelname)s %(message)s', '%b %d %Y %H:%M:%S %z') + + # Change root logger level from WARNING to NOTSET in order for all messages to be delegated. + # https://stackoverflow.com/a/59431653 + logging.getLogger('').setLevel(logging.NOTSET) + + # Create a rotating log file handler, rotate at 10MB, keeping 9 backups + file_logger = logging.handlers.RotatingFileHandler(log_path, 'a', 100000, 9, 'utf-8') + # Set file logging level + file_logger.setLevel(log_level) + # Set file log format + file_logger.setFormatter(log_format) + # Add to logger + logging.getLogger('').addHandler(file_logger) + + # Add console handler to logging object + console_logger = logging.StreamHandler() + # Set console logging level + console_logger.setLevel(log_level) + # Set console logging format + console_logger.setFormatter(log_format) + # Add to logger + logging.getLogger('').addHandler(console_logger) + + # Start log + logging.info("Starting %s - %s", APP_NAME, APP_VERSION) + + +def split_launchctl_list(cmd_out): + '''Takes launchctl list output and returns a list with just the labels''' + + # Var declaration + launchd_labels = [] + + # Strip cmd_out to just the labels of the running launch agents + for launchd_item in cmd_out.stdout.decode().splitlines(): + # If the launchd_item starts with LAUNCHD_PREFIX + if launchd_item.split('\t')[2].startswith(LAUNCHD_PREFIX): + # Add the label to launchd_labels + launchd_labels.append(launchd_item.split('\t')[2]) + + # Returns a list of launchd labels + return launchd_labels + + +if __name__ == '__main__': + + # Check to see if we're root + if os.geteuid() != 0: + print("ERROR: You must run this as root!", file=sys.stderr) + sys.exit(1) + + # If INSTALLHELPER_RUN_TYPE isn't set + if not os.environ.get('INSTALLHELPER_RUN_TYPE'): + # If we have no arguments passed or the arguments passed are not expected.. exit + if len(sys.argv) == 1 or not (sys.argv[1].lower() == 'appusage' or + sys.argv[1].lower() == 'launchd'): + print("ERROR: Requires either \'appusage\' or \'launchd\' arguments to be passed.") + sys.exit(1) + # If INSTALLHELPER_RUN_TYPE is set + else: + # Else if we have INSTALLHELPER_RUN_TYPE defined, and it's not what's expected.. exit + if not (os.environ.get('INSTALLHELPER_RUN_TYPE') != 'appusage' or + os.environ.get('INSTALLHELPER_RUN_TYPE') != 'launchd'): + # Set launchd_group to the value of INSTALLHELPER_RUN_TYPE + print("ERROR: Requires INSTALLHELPER_RUN_TYPE to be set to either \'appusage\' or " + "\'launchd\'") + sys.exit(1) + + # Proceed to run main + main() diff --git a/code/tools/make_munki_mpkg.sh b/code/tools/make_munki_mpkg.sh index 99717a90..83e20fdf 100755 --- a/code/tools/make_munki_mpkg.sh +++ b/code/tools/make_munki_mpkg.sh @@ -508,7 +508,7 @@ mkdir -m 755 "$ADMINROOT/usr/local" mkdir -m 755 "$ADMINROOT/usr/local/munki" # Copy command line admin utilities. # edit this if list of tools changes! -for TOOL in makecatalogs makepkginfo manifestutil munkiimport iconimporter repoclean +for TOOL in makecatalogs makepkginfo manifestutil munkiimport iconimporter repoclean installhelper do cp -X "$MUNKIROOT/code/client/$TOOL" "$ADMINROOT/usr/local/munki/" 2>&1 done @@ -544,10 +544,12 @@ mkdir -m 1775 "$APPROOT" mkdir -m 775 "$APPROOT/Applications" # Copy Managed Software Center application. cp -R "$MSCAPP" "$APPROOT/Applications/" +# Create Helper directory +mkdir -m 775 "$APPROOT/Applications/Managed Software Center.app/Contents/Helpers/" # Copy MunkiStatus helper app -cp -R "$MSAPP" "$APPROOT/Applications/Managed Software Center.app/Contents/Resources/" +cp -R "$MSAPP" "$APPROOT/Applications/Managed Software Center.app/Contents/Helpers/" # Copy notifier helper app -cp -R "$NOTIFIERAPP" "$APPROOT/Applications/Managed Software Center.app/Contents/Resources/" +cp -R "$NOTIFIERAPP" "$APPROOT/Applications/Managed Software Center.app/Contents/Helpers/" # make sure not writeable by group or other chmod -R go-w "$APPROOT/Applications/Managed Software Center.app" @@ -556,7 +558,7 @@ if [ "$APPSIGNINGCERT" != "" ]; then echo "Signing Managed Software Center.app Bundles..." /usr/bin/codesign -f -s "$APPSIGNINGCERT" --options runtime --timestamp --verbose \ "$APPROOT/Applications/Managed Software Center.app/Contents/PlugIns/MSCDockTilePlugin.docktileplugin" \ - "$APPROOT/Applications/Managed Software Center.app/Contents/Resources/munki-notifier.app" + "$APPROOT/Applications/Managed Software Center.app/Contents/Helpers/munki-notifier.app" SIGNING_RESULT="$?" if [ "$SIGNING_RESULT" -ne 0 ]; then echo "Error signing Managed Software Center.app: $SIGNING_RESULT" @@ -564,7 +566,7 @@ if [ "$APPSIGNINGCERT" != "" ]; then fi echo "Signing MunkiStatus.app Frameworks..." - /usr/bin/find "$APPROOT/Applications/Managed Software Center.app/Contents/Resources/MunkiStatus.app/Contents/Frameworks" -type f -perm -u=x -exec /usr/bin/codesign -f -s "$APPSIGNINGCERT" --options runtime --timestamp --verbose {} \; + /usr/bin/find "$APPROOT/Applications/Managed Software Center.app/Contents/Helpers/MunkiStatus.app/Contents/Frameworks" -type f -perm -u=x -exec /usr/bin/codesign -f -s "$APPSIGNINGCERT" --options runtime --timestamp --verbose {} \; SIGNING_RESULT="$?" if [ "$SIGNING_RESULT" -ne 0 ]; then echo "Error signing MunkiStatus.app Frameworks: $SIGNING_RESULT" @@ -580,7 +582,7 @@ if [ "$APPSIGNINGCERT" != "" ]; then echo "Signing Managed Software Center.app..." /usr/bin/codesign -f -s "$APPSIGNINGCERT" --options runtime --timestamp --verbose \ - "$APPROOT/Applications/Managed Software Center.app/Contents/Resources/MunkiStatus.app" \ + "$APPROOT/Applications/Managed Software Center.app/Contents/Helpers/MunkiStatus.app" \ "$APPROOT/Applications/Managed Software Center.app" SIGNING_RESULT="$?" if [ "$SIGNING_RESULT" -ne 0 ]; then @@ -914,18 +916,6 @@ cat > "$DISTFILE" < - @@ -951,7 +941,7 @@ cat > "$DISTFILE" < - + @@ -968,9 +958,9 @@ cat > "$DISTFILE" <${PKGPREFIX}munkitools_core.pkg ${PKGPREFIX}munkitools_admin.pkg ${PKGPREFIX}munkitools_app.pkg - ${PKGPREFIX}munkitools_launchd.pkg - ${PKGPREFIX}munkitools_app_usage.pkg ${PKGPREFIX}munkitools_python.pkg + ${PKGPREFIX}munkitools_launchd.pkg + ${PKGPREFIX}munkitools_app_usage.pkg $BOOTSTRAPREF $CONFREF $CLIENTCERTREF diff --git a/code/tools/pkgresources/Scripts_app_usage/postinstall b/code/tools/pkgresources/Scripts_app_usage/postinstall index 46dd0482..bcaf188b 100755 --- a/code/tools/pkgresources/Scripts_app_usage/postinstall +++ b/code/tools/pkgresources/Scripts_app_usage/postinstall @@ -1,22 +1,19 @@ #!/bin/sh -# Lovingly adapted from Per Olofsson -# https://github.com/MagerValp/Scripted-Mac-Package-Creation/blob/master/scripts/postinstall +# +# this postinstall should run installhelper in the background, with it then waiting until +# managedsoftwareupdate isn't running and then (re)load Munki's appusage launchditems items as needed +# -export PATH=/usr/bin:/bin:/usr/sbin:/sbin - -# Execute postinstall actions if we're installing on a live system. -# This is useful for loading launch daemons and agents. -if [ "$3" = "/" ]; then - - # Run postinstall actions for root. - launchctl bootstrap system/ /Library/LaunchDaemons/com.googlecode.munki.appusaged.plist - - # Run postinstall actions for all logged in users. - for uid in $(ps -axo uid,args | grep "/[F]inder.app/" | awk '{print $1}'); do - launchctl bootstrap gui/"$uid"/ /Library/LaunchAgents/com.googlecode.munki.app_usage_monitor.plist - done - -fi - -exit 0 \ No newline at end of file +# Only execute postinstall actions if we're installing on a live system. +if [ "$3" = "/" ] +then + installHelper='/usr/local/munki/installhelper' + if [ -f "${installHelper}" ] + then + /bin/echo "Loading ${installHelper}..." + "${installHelper}" appusage & + else + /bin/echo "Cannot locate: ${installHelper}..." + fi +fi \ No newline at end of file diff --git a/code/tools/pkgresources/Scripts_app_usage/preinstall b/code/tools/pkgresources/Scripts_app_usage/preinstall deleted file mode 100755 index c7063690..00000000 --- a/code/tools/pkgresources/Scripts_app_usage/preinstall +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh - -# Lovingly adapted from Per Olofsson -# https://github.com/MagerValp/Scripted-Mac-Package-Creation/blob/master/scripts/postinstall - -export PATH=/usr/bin:/bin:/usr/sbin:/sbin - -# Execute preinstall actions if we're installing on a live system. -# This is useful for unloading launch daemons and agents. -if [ "$3" = "/" ]; then - - # Run preinstall actions for root. - if launchctl print system/munki.app_usage_monitor > /dev/null 2>&1 ; then - launchctl bootout system/munki.app_usage_monitor - fi - if launchctl print system/com.googlecode.munki.appusaged. > /dev/null 2>&1 ; then - launchctl bootout system/com.googlecode.munki.appusaged - fi - - # Run preinstall actions for all logged in users. - for uid in $(ps -axo uid,args | grep "/[F]inder.app/" | awk '{print $1}'); do - if launchctl print gui/"$uid"/com.googlecode.munki.app_usage_monitor > /dev/null 2>&1 ; then - launchctl bootout gui/"$uid"/com.googlecode.munki.app_usage_monitor - fi - done - -fi - -exit 0 \ No newline at end of file diff --git a/code/tools/pkgresources/Scripts_launchd/postinstall b/code/tools/pkgresources/Scripts_launchd/postinstall index 4e430267..9a0534d5 100755 --- a/code/tools/pkgresources/Scripts_launchd/postinstall +++ b/code/tools/pkgresources/Scripts_launchd/postinstall @@ -1,51 +1,19 @@ #!/bin/sh -# Lovingly lifted from Per Olofsson -# https://github.com/MagerValp/Scripted-Mac-Package-Creation/blob/master/scripts/postinstall - -# this is intended for a new install of the Munki tools -- the tools will be -# installed and the launchagents/daemons will be activated without the need for -# a restart # -# This should not be used for "upgrade" installs of the munkitools, or by -# installs handled by Munki itself. +# this postinstall should run installhelper in the background, with it then waiting until +# managedsoftwareupdate isn't running and then (re)load Munki's launchd items as needed +# -export PATH=/usr/bin:/bin:/usr/sbin:/sbin - -# Execute postinstall actions if we're installing on a live system. -# This is useful for loading launch daemons and agents. -if [ "$3" = "/" ]; then - - # is a Munki launchd job already loaded? if so, exit now - for JOB in logouthelper managedsoftwareupdate-check managedsoftwareupdate-install managedsoftwareupdate-manualcheck - do - if launchctl list com.googlecode.munki.${JOB} >/dev/null 2>&1 ; then - echo "com.googlecode.munki.${JOB} is loaded: exiting postflight" - exit 0 - fi - done - - # Load all launch daemons. - launchctl bootstrap system/ /Library/LaunchDaemons/com.googlecode.munki.authrestartd.plist - launchctl bootstrap system/ /Library/LaunchDaemons/com.googlecode.munki.logouthelper.plist - launchctl bootstrap system/ /Library/LaunchDaemons/com.googlecode.munki.managedsoftwareupdate-check.plist - launchctl bootstrap system/ /Library/LaunchDaemons/com.googlecode.munki.managedsoftwareupdate-install.plist - launchctl bootstrap system/ /Library/LaunchDaemons/com.googlecode.munki.managedsoftwareupdate-manualcheck.plist - - loggedInUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ && ! /loginwindow/ { print $3 }' ) - if [ "$loggedInUser" = "" ] ; then - # no-one is logged in; I.E. we're at the loginwindow. - # Load the loginwindow launchagents - launchctl load -S LoginWindow /Library/LaunchAgents/com.googlecode.munki.managedsoftwareupdate-loginwindow.plist - launchctl load -S LoginWindow /Library/LaunchAgents/com.googlecode.munki.MunkiStatus.plist +# Only execute postinstall actions if we're installing on a live system. +if [ "$3" = "/" ] +then + installHelper='/usr/local/munki/installhelper' + if [ -f "${installHelper}" ] + then + /bin/echo "Loading ${installHelper}..." + "${installHelper}" launchd & + else + /bin/echo "Cannot locate: ${installHelper}..." fi - - # Load launch agents for all currently logged in users. - for uid in $(ps -axo uid,args | grep "/[F]inder.app/" | awk '{print $1}'); do - launchctl bootstrap gui/"$uid"/ /Library/LaunchAgents/com.googlecode.munki.ManagedSoftwareCenter.plist - launchctl bootstrap gui/"$uid"/ /Library/LaunchAgents/com.googlecode.munki.munki-notifier.plist - done - -fi - -exit 0 +fi \ No newline at end of file diff --git a/launchd/LaunchAgents/com.googlecode.munki.MunkiStatus.plist b/launchd/LaunchAgents/com.googlecode.munki.MunkiStatus.plist index abdbdb42..063139f7 100644 --- a/launchd/LaunchAgents/com.googlecode.munki.MunkiStatus.plist +++ b/launchd/LaunchAgents/com.googlecode.munki.MunkiStatus.plist @@ -24,7 +24,7 @@ ProgramArguments - /Applications/Managed Software Center.app/Contents/Resources/MunkiStatus.app/Contents/MacOS/MunkiStatus + /Applications/Managed Software Center.app/Contents/Helpers/MunkiStatus.app/Contents/MacOS/MunkiStatus diff --git a/launchd/LaunchAgents/com.googlecode.munki.munki-notifier.plist b/launchd/LaunchAgents/com.googlecode.munki.munki-notifier.plist index 40e24bc0..a81a6536 100644 --- a/launchd/LaunchAgents/com.googlecode.munki.munki-notifier.plist +++ b/launchd/LaunchAgents/com.googlecode.munki.munki-notifier.plist @@ -20,7 +20,7 @@ /usr/local/munki/launchapp -a - /Applications/Managed Software Center.app/Contents/Resources/munki-notifier.app + /Applications/Managed Software Center.app/Contents/Helpers/munki-notifier.app