Beispiel #1
0
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.')
Beispiel #2
0
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.'
Beispiel #4
0
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.')
Beispiel #5
0
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