def RunPostflight(runtype): """Run the full postflight script.""" # support enterprise/802.1x user-context wifi auth. # don't bother to perform postflight and exit OK immediately since there's no # network connection. if runtype == 'logoutinstall': sys.exit(0) # Ensure MSU is installed to /Applications if not IsAppInPlace(): flight_common.RepairClient() url = flight_common.GetServerURL() client = mac_client.SimianAuthClient( flight_common.GetClientIdentifier('auto')['uuid'], hostname=url) client.SetAuthToken(flight_common.GetAuth1Token()) # read SecureConfig.plist. plist = munkicommon.SecureManagedInstallsPreferences() # Post client_id to server. client_id = flight_common.GetClientIdentifier(runtype) pkgs_to_install, apple_updates_to_install = ( flight_common.GetRemainingPackagesToInstall()) params = { 'client_id': flight_common.DictToStr(client_id), 'pkgs_to_install': pkgs_to_install, 'apple_updates_to_install': apple_updates_to_install, } client.PostReport('postflight', params) # Report installs/etc to server. flight_common.UploadAllManagedInstallReports( client, client_id.get('on_corp', 'None')) if not client.LogoutAuthToken(): logging.error('Logout failed') # expire auth token and remove cookie from plist. RemoveAuthTokenHeaderFromPlist(plist) # Delete the temp dir that munkicommon creates on import. munkicommon.cleanUpTmpDir() # Mark successful run by writing to last success file. NoteLastSuccess() logging.debug('Postflight completed successfully.')
def RunPreflight(runtype, server_url=None): """Run the full Preflight script.""" NoteLastRun() # support enterprise/802.1x user-context wifi auth. # don't bother to perform preflight and exit OK immediately since there's no # network connection. if runtype == 'logoutinstall': sys.exit(0) # load the NONSECURE ManagedInstalls.plist regular_config = munkicommon.ManagedInstallsPreferences() if server_url: regular_config['SoftwareRepoURL'] = server_url secure_config = munkicommon.SecureManagedInstallsPreferences() # update the ClientIdentifier key with the custom client id. client_id = flight_common.GetClientIdentifier(runtype) secure_config['ClientIdentifier'] = client_id['track'] # load user settings try: user_settings = flight_common.GetUserSettings() except ValueError, e: logging.warning('User settings are malformed: %s', str(e)) user_settings = {'__malformed': True}
def main(): optparser = optparse.OptionParser() optparser.add_option('-r', '--reason', dest='reason', default='Unknown', help='Reason for brokenness.') optparser.add_option('-d', '--detail-file', dest='detail_file', help='File with error details.') options, _ = optparser.parse_args() detail_parts = [] if options.detail_file: try: detail_parts.append('Failure detail:\n%s' % open(options.detail_file, 'r').read()) except IOError as e: detail_parts.append('Could not read detail file %r:\n%s' % (options.detail_file, e)) return_code, stdout, stderr = flight_common.Exec(['facter', '-p'], timeout=60, waitfor=0.5) facter_parts = [ 'Facter Return Code: %s' % return_code, 'Facter StdOut:\n%s' % stdout, ] if stderr: facter_parts.append('Facter StdErr:\n%s' % stderr) detail_parts.append('\n\n'.join(facter_parts)) details = ('\n\n' + ('*' * 60) + '\n\n').join( [part.strip() for part in detail_parts]) params = {'details': details, 'reason': options.reason} url = flight_common.GetServerURL() c = client.SimianAuthClient( flight_common.GetClientIdentifier('auto')['uuid'], hostname=url) c.GetAuthToken() c.PostReport('broken_client', params) print 'Reported broken client to server.'
def RunPreflight(runtype, server_url=None): """Run the full Preflight script.""" NoteLastRun() # support enterprise/802.1x user-context wifi auth. # don't bother to perform preflight and exit OK immediately since there's no # network connection. if runtype == 'logoutinstall': sys.exit(0) # load the NONSECURE ManagedInstalls.plist regular_config = munkicommon.ManagedInstallsPreferences() if server_url: regular_config['SoftwareRepoURL'] = server_url secure_config = munkicommon.SecureManagedInstallsPreferences() # update the ClientIdentifier key with the custom client id. client_id = flight_common.GetClientIdentifier(runtype) secure_config['ClientIdentifier'] = client_id['track'] # load user settings try: user_settings = flight_common.GetUserSettings() except ValueError as e: logging.warning('User settings are malformed: %s', str(e)) user_settings = {'__malformed': True} # If the munki exec is an auto run (launchd), exit if on WWAN or Android WAP. client_exit = None if runtype == 'auto': if network_detect.IsOnWwan(): client_exit = 'WWAN device ppp0 is active' elif network_detect.IsOnAndroidWap(): client_exit = 'Android WAP tether is active' elif network_detect.IsOnIosWap(): client_exit = 'iOS WAP tether is active' elif network_detect.IsOnMifi(): client_exit = 'MiFi tether is active' elif network_detect.IsOnBackoffWLAN(): client_exit = 'Backoff WLAN SSID detected' # get a client auth token/cookie from the server, and post connection data. client, feedback = LoginToServer( secure_config, client_id, user_settings, client_exit) WriteRootCaCerts(client) if feedback.get('upload_logs'): # write new token/client_id headers to secure plist and upload logs. flight_common.UploadClientLogFiles(client) if feedback.get('pkill_installd'): # terminate any pending installations, like misbehaving Apple updates. flight_common.Pkill(process='installd', waitfor=2) if feedback.get('pkill_softwareupdated'): # terminate potentially hung softareupdated processes. flight_common.Pkill(process='softwareupdated', waitfor=2) if feedback.get('repair'): # write new token/client_id headers to secure plist and repair client. try: logging.info('Reinstalling Munki client....') flight_common.RepairClient() logging.info('Client successfully reinstalled.') except flight_common.RepairClientError as e: logging.exception(u'RepairClientError: %s', e) if feedback.get('logging_level'): regular_config['LoggingLevel'] = feedback.get('logging_level') else: regular_config['LoggingLevel'] = 1 # default to 1 if not set by server. if feedback.get('exit'): logging.warning('preflight received EXIT feedback from server; exiting....') sys.exit(STATUS_SERVER_EXIT_FEEDBACK[0]) # post recent MSU logs logs = GetManagedSoftwareUpdateLogs() PostManagedSoftwareUpdateLogs(client, logs) # load user settings if user_settings: regular_config['UserSettings'] = user_settings else: if 'UserSettings' in regular_config: del regular_config['UserSettings'] # wipe existing UserSettings. # setup blank directory for capath setting path = CreateEmptyDirectory() regular_config['SoftwareRepoCAPath'] = path # enable MSU logging regular_config['MSULogEnabled'] = True # If setting is enabled, force Simian Apple SUS integration. if client_id.get('applesus'): regular_config['InstallAppleSoftwareUpdates'] = True # Get Apple Software Update Service catalog from server and set locally. flight_common.GetAppleSUSCatalog() # Report installs/etc to server. flight_common.UploadAllManagedInstallReports( client, client_id.get('on_corp', 'None')) # Delete the temp dir that munkicommon creates on import. munkicommon.cleanUpTmpDir() logging.debug('Preflight completed successfully.')
def LoginToServer(secure_config, client_id, user_settings, client_exit=None): """Sets an auth token cookie header to a plist object. Args: secure_config: secure Preferences object. client_id: dict client identifier. user_settings: dict of user settings. client_exit: optional, default None, str explaining why the client is requesting to exit its execution. Returns: Tuple of a SimianAuthClient, a dict containing feedback from the server. """ headers = [] # Preserve all non-Cookie and non-ClientID headers that may exist. if munkicommon.ADDITIONAL_HTTP_HEADERS_KEY in secure_config: for header in secure_config[munkicommon.ADDITIONAL_HTTP_HEADERS_KEY]: if (not header.startswith('Cookie:') and not header.startswith( flight_common.MUNKI_CLIENT_ID_HEADER_KEY) and not header.startswith('User-Agent:')): headers.append(header) client_id_str = flight_common.DictToStr(client_id) if user_settings: try: user_settings_str = urllib.quote( json.dumps(flight_common.Flatten(user_settings))) except TypeError: logging.error('preflight cannot flatten user_settings: %s', str(user_settings)) user_settings_str = '' else: user_settings_str = '' client_params = { '_report_type': 'preflight', 'client_id': client_id_str, 'user_settings': user_settings_str, 'json': '1', } if client_exit: client_params['client_exit'] = client_exit client_params = urllib.urlencode(client_params) url = flight_common.GetServerURL() client = mac_client.SimianAuthClient( flight_common.GetClientIdentifier('auto')['uuid'], hostname=url) token = client.GetAuthToken() response = client.PostReportBody(client_params) feedback = {} try: feedback = json.loads(response[len(JSON_PREFIX):]) except ValueError: logging.exception('Error parsing JSON') if not isinstance(feedback, dict): logging.error('preflight failure getting feedback dict (%r)', feedback) # Add the Cookie and client id to the headers. headers.append('User-Agent: gzip') # enforce GFE compression headers.append('Cookie: %s' % token) headers.append('%s: %s' % (flight_common.MUNKI_CLIENT_ID_HEADER_KEY, client_id_str)) # Replace AdditionalHttpHeaders with the new headers list. secure_config[munkicommon.ADDITIONAL_HTTP_HEADERS_KEY] = headers return client, feedback