def getMCXData(ds_object): '''Returns a dictionary representation of dsAttrTypeStandard:MCXSettings from the given DirectoryServices object''' ds_object_parts = ds_object.split('/') ds_node = '/'.join(ds_object_parts[0:3]) ds_object_path = '/' + '/'.join(ds_object_parts[3:]) cmd = ['/usr/bin/dscl', '-plist', ds_node, 'read', ds_object_path, 'dsAttrTypeStandard:MCXSettings'] proc = subprocess.Popen(cmd, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (pliststr, err) = proc.communicate() if proc.returncode: errorAndExit("dscl error: %s" % err) # decode plist string returned by dscl try: mcx_dict = FoundationPlist.readPlistFromString(pliststr) except FoundationPlist.FoundationPlistException: errorAndExit( "Could not decode plist data from dscl:\n" % pliststr) # mcx_settings is a plist encoded inside the plist! try: mcx_data_plist = mcx_dict['dsAttrTypeStandard:MCXSettings'][0] except KeyError: errorAndExit("No mcx_settings in %s:\n%s" % (ds_object, pliststr)) except IndexError: errorAndExit( "Unexpected mcx_settings format in %s:\n%s" % (ds_object, pliststr)) # decode the embedded plist mcx_data = FoundationPlist.readPlistFromString(str(mcx_data_plist)) return mcx_data['mcx_application_data']
def buildplist(nbiindex, nbidescription, nbiname, nbienabled, destdir=__file__): """buildplist takes a source, destination and name parameter that are used to create a valid plist for imagetool ingestion.""" nbipath = os.path.join(destdir, nbiname + '.nbi') platformsupport = FoundationPlist.readPlist( os.path.join(nbipath, 'i386', 'PlatformSupport.plist')) enabledsystems = platformsupport.get('SupportedModelProperties') nbimageinfo = { 'IsInstall': True, 'Index': nbiindex, 'Kind': 1, 'Description': nbidescription, 'Language': 'Default', 'IsEnabled': nbienabled, 'SupportsDiskless': False, 'RootPath': 'NetInstall.dmg', 'EnabledSystemIdentifiers': enabledsystems, 'BootFile': 'booter', 'Architectures': ['i386'], 'BackwardCompatible': False, 'DisabledSystemIdentifiers': [], 'Type': 'NFS', 'IsDefault': False, 'Name': nbiname, 'osVersion': '10.9' } plistfile = os.path.join(nbipath, 'NBImageInfo.plist') FoundationPlist.writePlist(nbimageinfo, plistfile)
def run_reports(args): expanded_cache, errors = build_expanded_cache() # TODO: Add sorting to output or reporting. report_results = [] report_results.append(PathIssuesReport(expanded_cache)) report_results.append(MissingInstallerReport(expanded_cache)) report_results.append(OrphanedInstallerReport(expanded_cache)) report_results.append(PkgsinfoWithErrorsReport(errors)) report_results.append(OutOfDateReport(expanded_cache)) report_results.append(NoUsageReport(expanded_cache)) # Add the results of the last two reports together to determine # wasted disk space. # expanded_cache["unused_items"] = [item for report in report_results[-2:] # for item in report.items] # report_results.append(UnusedDiskUsageReport(expanded_cache)) report_results.append(UnattendedTestingReport(expanded_cache)) report_results.append(UnattendedProdReport(expanded_cache)) report_results.append(ForceInstallTestingReport(expanded_cache)) report_results.append(ForceInstallProdReport(expanded_cache)) if args.plist: dict_reports = {report.name: report.as_dict() for report in report_results} print FoundationPlist.writePlistToString(dict_reports) else: for report in report_results: report.print_report()
def getPlistData(data): # Try the user's homedir try: # NSLog("Trying Home Location") homedir = os.path.expanduser("~") plist = FoundationPlist.readPlist( os.path.join(homedir, "Library", "Preferences", "com.grahamgilbert.Imagr.plist")) return plist[data] except: pass # Try the main prefs try: # NSLog("Trying System Location") plist = FoundationPlist.readPlist( os.path.join("/Library", "Preferences", "com.grahamgilbert.Imagr.plist")) return plist[data] except: pass # Hopefully we're in a netboot set, try in /System/Installation/Packages try: # NSLog("Trying NetBoot Location") plist = FoundationPlist.readPlist( os.path.join("/System", "Installation", "Packages", "com.grahamgilbert.Imagr.plist")) return plist[data] except: pass
def buildplist(nbiindex, nbidescription, nbiname, nbienabled, destdir=__file__): """buildplist takes a source, destination and name parameter that are used to create a valid plist for imagetool ingestion.""" nbipath = os.path.join(destdir, nbiname + '.nbi') platformsupport = FoundationPlist.readPlist(os.path.join(nbipath, 'i386', 'PlatformSupport.plist')) enabledsystems = platformsupport.get('SupportedModelProperties') nbimageinfo = {'IsInstall': True, 'Index': nbiindex, 'Kind': 1, 'Description': nbidescription, 'Language': 'Default', 'IsEnabled': nbienabled, 'SupportsDiskless': False, 'RootPath': 'NetInstall.dmg', 'EnabledSystemIdentifiers': enabledsystems, 'BootFile': 'booter', 'Architectures': ['i386'], 'BackwardCompatible': False, 'DisabledSystemIdentifiers': [], 'Type': 'NFS', 'IsDefault': False, 'Name': nbiname, 'osVersion': '10.9'} plistfile = os.path.join(nbipath, 'NBImageInfo.plist') FoundationPlist.writePlist(nbimageinfo, plistfile)
def escrowKey(key, username, runtype): ##submit this to the server fv_status['recovery_password'] theurl = pref('ServerURL')+"/checkin/" serial = GetMacSerial() macname = GetMacName() mydata=[('serial',serial),('recovery_password',key),('username',username),('macname',macname)] mydata=urllib.urlencode(mydata) req = Request(theurl, mydata) try: response = urlopen(req) except URLError, e: if hasattr(e, 'reason'): print 'We failed to reach a server.' print 'Reason: ', e.reason has_error = True #NSApp.terminate_(self) elif hasattr(e, 'code'): print 'The server couldn\'t fulfill the request' print 'Error code: ', e.code has_error = True #NSApp.terminate_(self) if has_error: plistData = {} plistData['recovery_key']=key plistData['username']=username FoundationPlist.writePlist(plistData, '/usr/local/crypt/recovery_key.plist') os.chmod('/usr/local/crypt/recovery_key.plist',0700) if runtype=="initial": the_command = "/sbin/reboot" reboot = subprocess.Popen(the_command,shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE).communicate()[0]
def copy_pkginfo_to_repo(self, pkginfo): """Saves pkginfo to munki_repo_path/pkgsinfo/subdirectory. Returns full path to the pkginfo in the repo.""" # less error checking because we copy the installer_item # first and bail if it fails... repo_path = self.env["MUNKI_REPO"] subdirectory = self.env.get("repo_subdirectory", "") destination_path = os.path.join(repo_path, "pkgsinfo", subdirectory) if not os.path.exists(destination_path): try: os.makedirs(destination_path) except OSError as err: raise ProcessorError("Could not create %s: %s" % (destination_path, err.strerror)) extension = self.env.get("MUNKI_PKGINFO_FILE_EXTENSION", "plist") if len(extension) > 0: extension = '.' + extension.strip(".") pkginfo_name = "%s-%s%s" % (pkginfo["name"], pkginfo["version"].strip(), extension) pkginfo_path = os.path.join(destination_path, pkginfo_name) index = 0 while os.path.exists(pkginfo_path): index += 1 pkginfo_name = "%s-%s__%s%s" % ( pkginfo["name"], pkginfo["version"], index, extension) pkginfo_path = os.path.join(destination_path, pkginfo_name) try: FoundationPlist.writePlist(pkginfo, pkginfo_path) except OSError as err: raise ProcessorError("Could not write pkginfo %s: %s" % (pkginfo_path, err.strerror)) return pkginfo_path
def main(): ard_path = "/Library/Preferences/com.apple.RemoteDesktop.plist" if os.path.exists(ard_path): ard_prefs = FoundationPlist.readPlist(ard_path) else: ard_prefs = {} sal_result_key = "ARD_Info_{}" prefs_key_prefix = "Text{}" data = { sal_result_key.format(i): ard_prefs.get(prefs_key_prefix.format(i), "") for i in xrange(1, 5) } formatted_results = { "plugin": "ARD_Info", "historical": False, "data": data } if os.path.exists(RESULTS_PATH): plugin_results = FoundationPlist.readPlist(RESULTS_PATH) else: plugin_results = [] plugin_results.append(formatted_results) FoundationPlist.writePlist(plugin_results, RESULTS_PATH)
def main(): """Set up arguments and start processing.""" args = get_argument_parser().parse_args() autopkg_plist_path = "~/Library/Preferences/com.github.autopkg.plist" # Read preferences. if os.path.exists(os.path.expanduser(autopkg_plist_path)): try: autopkg_prefs = FoundationPlist.readPlist( os.path.expanduser(autopkg_plist_path)) if "MUNKI_REPO" in autopkg_prefs: MUNKI_REPO = autopkg_prefs["MUNKI_REPO"] else: print_error("No MUNKI_REPO key in AutoPkg preferences.") except FoundationPlist.NSPropertyListSerializationException as e: print_error("Error reading preferences: %s" % e) else: print_error("No file exists at %s." % autopkg_plist_path) production_cat = FoundationPlist.readPlist( os.path.join(MUNKI_REPO, "catalogs/%s" % args.catalog)) pkginfo_template = (get_pkginfo_template(args.pkginfo) if args.pkginfo else {}) recipes = args.recipes if args.recipes else get_recipes(args.recipe_list) try: process_overrides(recipes, args, production_cat, pkginfo_template) except KeyboardInterrupt: print_error("Bailing!") finally: reset_term_colors()
def write_plist(self, data, pathname): """writes a plist to pathname""" # pylint: disable=no-self-use try: FoundationPlist.writePlist(data, pathname) except Exception as err: raise ProcessorError("Could not write %s: %s" % (pathname, err))
def __init__(self, cmd, environment_vars=None): tmpdir = munkicommon.tmpdir LABELPREFIX = 'com.googlecode.munki.' # create a unique id for this job jobid = str(uuid.uuid1()) self.label = LABELPREFIX + jobid self.stdout_path = os.path.join(tmpdir, self.label + '.stdout') self.stderr_path = os.path.join(tmpdir, self.label + '.stderr') self.plist_path = os.path.join(tmpdir, self.label + '.plist') self.stdout = None self.stderr = None self.plist = {} self.plist['Label'] = self.label self.plist['ProgramArguments'] = cmd self.plist['StandardOutPath'] = self.stdout_path self.plist['StandardErrorPath'] = self.stderr_path if environment_vars: self.plist['EnvironmentVariables'] = environment_vars # write out launchd plist FoundationPlist.writePlist(self.plist, self.plist_path) # set owner, group and mode to those required # by launchd os.chown(self.plist_path, 0, 0) os.chmod(self.plist_path, int('644', 8)) launchctl_cmd = ['/bin/launchctl', 'load', self.plist_path] proc = subprocess.Popen(launchctl_cmd, shell=False, bufsize=1, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (unused_out, err) = proc.communicate() if proc.returncode: raise LaunchdJobException(err)
def escrow_key(key, username, runtype): theurl = pref('ServerURL')+"/checkin/" serial = GetMacSerial() macname = GetMacName() mydata=[('serial',serial),('recovery_password',key),('username',username),('macname',macname)] mydata=urllib.urlencode(mydata) req = Request(theurl, mydata) try: response = urlopen(req) except URLError, e: if hasattr(e, 'reason'): print 'We failed to reach a server.' print 'Reason: ', e.reason has_error = True elif hasattr(e, 'code'): print 'The server couldn\'t fulfill the request' print 'Error code: ', e.code has_error = True if has_error: plistData = {} plistData['recovery_key']=key plistData['username']=username try: FoundationPlist.writePlist(plistData, '/private/var/root/recovery_key.plist') except: os.makedirs('/usr/local/crypt') FoundationPlist.writePlist(plistData, '/private/var/root/recovery_key.plist') os.chmod('/private/var/root/recovery_key.plist',0700) if runtype=="initial": the_command = "/sbin/reboot" reboot = subprocess.Popen(the_command,shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE).communicate()[0]
def getPlistData(data): # Try the user's homedir try: # NSLog("Trying Home Location") homedir = os.path.expanduser("~") plist = FoundationPlist.readPlist(os.path.join(homedir, "Library", "Preferences", "com.grahamgilbert.Imagr.plist")) return plist[data] except: pass # Try the main prefs try: # NSLog("Trying System Location") plist = FoundationPlist.readPlist(os.path.join("/Library", "Preferences", "com.grahamgilbert.Imagr.plist")) return plist[data] except: pass # Hopefully we're in a netboot set, try in /System/Installation/Packages try: # NSLog("Trying NetBoot Location") plist = FoundationPlist.readPlist(os.path.join("/System", "Installation", "Packages", "com.grahamgilbert.Imagr.plist")) return plist[data] except: pass # last chance; look for a file next to the app appPath = NSBundle.mainBundle().bundlePath() appDirPath = os.path.dirname(appPath) try: plistData = open(os.path.join(appDirPath, "com.grahamgilbert.Imagr.plist")).read() plistData = plistData.replace("{{current_volume_path}}", currentVolumePath()).encode("utf8") plist = FoundationPlist.readPlistFromString(plistData) return plist[data] except: pass
def write_plist(self, data, pathname): """Write a plist to pathname.""" # pylint: disable=no-self-use try: FoundationPlist.writePlist(data, pathname) except Exception as err: raise ProcessorError('Could not write %s: %s' % (pathname, err))
def main(): data = raw_battery_dict() # If this is not a laptop, data will just be empty. No need to do # more work. if data: adjusted_dict = adjusted_battery_dict() if adjusted_dict and "BatteryHealth" in adjusted_dict: data["BatteryHealth"] = adjusted_dict["BatteryHealth"] else: data["BatteryHealth"] = "Unkonwn" formatted_results = { "plugin": "Battery", "historical": False, "data": data } if os.path.exists(RESULTS_PATH): plugin_results = FoundationPlist.readPlist(RESULTS_PATH) else: plugin_results = [] plugin_results.append(formatted_results) FoundationPlist.writePlist(plugin_results, RESULTS_PATH)
def getServerURL(): # Try the user's homedir try: NSLog("Trying Home Location") homedir = os.path.expanduser("~") plist = FoundationPlist.readPlist(os.path.join(homedir, "Library", "Preferences", "com.grahamgilbert.Imagr.plist")) return plist['serverurl'] except: pass # Try the main prefs try: NSLog("Trying System Location") plist = FoundationPlist.readPlist(os.path.join("/Library", "Preferences", "com.grahamgilbert.Imagr.plist")) return plist['serverurl'] except: pass # Hopefully we're in a netboot set, try in /System/Installation/Packages try: NSLog("Trying NetBoot Location") plist = FoundationPlist.readPlist(os.path.join("/System", "Installation", "Packages", "com.grahamgilbert.Imagr.plist")) return plist['serverurl'] except: pass
def __init__(self, cmd, environment_vars=None): tmpdir = munkicommon.tmpdir() labelprefix = 'com.googlecode.munki.' # create a unique id for this job jobid = str(uuid.uuid1()) self.label = labelprefix + jobid self.stdout_path = os.path.join(tmpdir, self.label + '.stdout') self.stderr_path = os.path.join(tmpdir, self.label + '.stderr') self.plist_path = os.path.join(tmpdir, self.label + '.plist') self.stdout = None self.stderr = None self.plist = {} self.plist['Label'] = self.label self.plist['ProgramArguments'] = cmd self.plist['StandardOutPath'] = self.stdout_path self.plist['StandardErrorPath'] = self.stderr_path if environment_vars: self.plist['EnvironmentVariables'] = environment_vars # write out launchd plist FoundationPlist.writePlist(self.plist, self.plist_path) # set owner, group and mode to those required # by launchd os.chown(self.plist_path, 0, 0) os.chmod(self.plist_path, int('644', 8)) launchctl_cmd = ['/bin/launchctl', 'load', self.plist_path] proc = subprocess.Popen(launchctl_cmd, shell=False, bufsize=-1, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) err = proc.communicate()[1] if proc.returncode: raise LaunchdJobException(err)
def run_reports(args): expanded_cache, errors = build_expanded_cache() # TODO: Add sorting to output or reporting. report_results = [] report_results.append(PathIssuesReport(expanded_cache)) report_results.append(MissingInstallerReport(expanded_cache)) report_results.append(OrphanedInstallerReport(expanded_cache)) report_results.append(PkgsinfoWithErrorsReport(errors)) report_results.append(OutOfDateReport(expanded_cache)) report_results.append(NoUsageReport(expanded_cache)) # Add the results of the last two reports together to determine # wasted disk space. # expanded_cache["unused_items"] = [item for report in report_results[-2:] # for item in report.items] # report_results.append(UnusedDiskUsageReport(expanded_cache)) report_results.append(UnattendedTestingReport(expanded_cache)) report_results.append(UnattendedProdReport(expanded_cache)) report_results.append(ForceInstallTestingReport(expanded_cache)) report_results.append(ForceInstallProdReport(expanded_cache)) if args.plist: dict_reports = { report.name: report.as_dict() for report in report_results } print FoundationPlist.writePlistToString(dict_reports) else: for report in report_results: report.print_report()
def main(self): # Wrap in a try/finally so the temp_path is always removed. temp_path = None try: # Check munki version. if os.path.exists("/usr/local/munki/munkilib/version.plist"): # Assume 0.7.0 or higher. munkiopts = ("displayname", "description", "catalog") else: # Assume 0.6.0 munkiopts = ("catalog",) # Copy pkg to a temporary local directory, as installer -query # (which is called by makepkginfo) doesn't work on network drives. if self.env["pkg_path"].endswith("pkg"): # Create temporary directory. temp_path = tempfile.mkdtemp(prefix="autopkg", dir="/private/tmp") # Copy the pkg there pkg_for_makepkginfo = os.path.join(temp_path, os.path.basename(self.env["pkg_path"])) shutil.copyfile(self.env["pkg_path"], pkg_for_makepkginfo) else: pkg_for_makepkginfo = self.env["pkg_path"] # Generate arguments for makepkginfo. args = ["/usr/local/munki/makepkginfo"] for option in munkiopts: if option in self.env: args.append("--%s=%s" % (option, self.env[option])) args.append(pkg_for_makepkginfo) # Call makepkginfo. try: p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (out, err) = p.communicate() except OSError as e: raise ProcessorError("makepkginfo execution failed with error code %d: %s" % ( e.errno, e.strerror)) if p.returncode != 0: raise ProcessorError("creating pkginfo for %s failed: %s" % (self.env['pkg_path'], err)) # makepkginfo cleanup. finally: if temp_path is not None: shutil.rmtree(temp_path) # Read output plist. output = FoundationPlist.readPlistFromString(out) # Set version and name. if "version" in self.env: output["version"] = self.env["version"] if "name" in self.env: output["name"] = self.env["name"] # Save info. self.env["munki_info"] = output if "info_path" in self.env: FoundationPlist.writePlist(output, self.env["info_path"])
def autoset_timezone(): """enable timezone based on current location""" das_plist = '/Library/Preferences/com.apple.timezone.auto.plist' enabler = FoundationPlist.readPlist(das_plist) val = enabler.get('Active') if val != 1: enabler['Active'] = 1 FoundationPlist.writePlist(enabler, das_plist)
def writeSelfServiceManifest(optional_install_choices): '''Write out our self-serve manifest so managedsoftwareupdate can use it''' usermanifest = "/Users/Shared/.SelfServeManifest" try: FoundationPlist.writePlist(optional_install_choices, usermanifest) except FoundationPlist.FoundationPlistException: pass
def writeSelfServiceManifest(optional_install_choices): '''Write out our self-serve manifest so managedsoftwareupdate can use it''' usermanifest = WRITEABLE_SELF_SERVICE_MANIFEST_PATH try: FoundationPlist.writePlist(optional_install_choices, usermanifest) except FoundationPlist.FoundationPlistException: pass
def cacheSwupdMetadata(): '''Copies ServerMetadata (.smd), Metadata (.pkm), and Distribution (.dist) files for the available updates to the local machine and writes a new sucatalog that refers to the local copies of these files.''' filtered_catalogpath = os.path.join( swupdCacheDir(), 'content/catalogs/filtered_index.sucatalog') catalog = FoundationPlist.readPlist(filtered_catalogpath) if 'Products' in catalog: product_keys = list(catalog['Products'].keys()) for product_key in product_keys: munkicommon.display_status('Caching metadata for product ID %s', product_key) product = catalog['Products'][product_key] if 'ServerMetadataURL' in product: unused_path = replicateURLtoFilesystem( product['ServerMetadataURL'], copy_only_if_missing=True) for package in product.get('Packages', []): ### not replicating the packages themselves ### #if 'URL' in package: # unused_path = replicateURLtoFilesystem( # package['URL'], # copy_only_if_missing=fast_scan) if 'MetadataURL' in package: munkicommon.display_status( 'Caching package metadata for product ID %s', product_key) unused_path = replicateURLtoFilesystem( package['MetadataURL'], copy_only_if_missing=True) distributions = product['Distributions'] for dist_lang in distributions.keys(): munkicommon.display_status( 'Caching %s distribution for product ID %s', dist_lang, product_key) dist_url = distributions[dist_lang] unused_path = replicateURLtoFilesystem( dist_url, copy_only_if_missing=True) # rewrite URLs to point to local resources rewriteURLs(catalog, rewrite_pkg_urls=False) # write out the rewritten catalog localcatalogpath = os.path.join(swupdCacheDir(), 'content', 'catalogs') if not os.path.exists(localcatalogpath): try: os.makedirs(localcatalogpath) except OSError, oserr: raise ReplicationError(oserr) localcatalogpathname = os.path.join(localcatalogpath, 'local_download.sucatalog') FoundationPlist.writePlist(catalog, localcatalogpathname) rewriteURLs(catalog, rewrite_pkg_urls=True) localcatalogpathname = os.path.join(localcatalogpath, 'local_install.sucatalog') FoundationPlist.writePlist(catalog, localcatalogpathname)
def writeSelfServiceManifest(optional_install_choices): '''Write out our self-serve manifest so managedsoftwareupdate can use it. Returns True on success, False otherwise.''' usermanifest = WRITEABLE_SELF_SERVICE_MANIFEST_PATH try: FoundationPlist.writePlist(optional_install_choices, usermanifest) return True except FoundationPlist.FoundationPlistException: return False
def clear_clients(): """Clear clients.plist in locationd settings.""" auth_plist = {} das_plist = '/private/var/db/locationd/clients.plist' clients_dict = FoundationPlist.readPlist(das_plist) service_handler('unload') clients_dict = auth_plist FoundationPlist.writePlist(clients_dict, das_plist) os.chown(das_plist, 205, 205) service_handler('load')
def write_output_plist(self): """Write environment to output as plist.""" if self.env is None: return try: FoundationPlist.writePlist(self.env, self.outfile) except BaseException as err: raise ProcessorError(err)
def create_munkipkginfo(self): # Set pkginfo plist path self.env["pkginfo_path"] = ("%s/%s.plist") % (self.env.get("RECIPE_CACHE_DIR"), self.env.get("NAME")) # Generate arguments for makepkginfo. args = ["/usr/local/munki/makepkginfo", self.env["pkg_path"]] if self.env.get("munkiimport_pkgname"): args.extend(["--pkgname", self.env["munkiimport_pkgname"]]) if self.env.get("munkiimport_appname"): args.extend(["--appname", self.env["munkiimport_appname"]]) if self.env.get("additional_makepkginfo_options"): args.extend(self.env["additional_makepkginfo_options"]) if self.env.get("munkiimport_name"): args.extend(["--displayname", self.env["munkiimport_name"]]) # Call makepkginfo. try: proc = subprocess.Popen( args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (out, err_out) = proc.communicate() except OSError as err: raise ProcessorError( "makepkginfo execution failed with error code %d: %s" % (err.errno, err.strerror)) if proc.returncode != 0: raise ProcessorError( "creating pkginfo for %s failed: %s" % (self.env["pkg_path"], err_out)) # Get pkginfo from output plist. pkginfo = FoundationPlist.readPlistFromString(out) # copy any keys from pkginfo in self.env if "pkginfo" in self.env: for key in self.env["pkginfo"]: pkginfo[key] = self.env["pkginfo"][key] # set an alternate version_comparison_key # if pkginfo has an installs item if "installs" in pkginfo and self.env.get("version_comparison_key"): for item in pkginfo["installs"]: if not self.env["version_comparison_key"] in item: raise ProcessorError( ("version_comparison_key '%s' could not be found in " "the installs item for path '%s'") % (self.env["version_comparison_key"], item["path"])) item["version_comparison_key"] = ( self.env["version_comparison_key"]) try: pkginfo_path = self.env["pkginfo_path"] FoundationPlist.writePlist(pkginfo, pkginfo_path) except OSError, err: raise ProcessorError("Could not write pkginfo %s: %s" % (pkginfo_path, err.strerror))
def sysprefs_boxchk(): """Enables location services in sysprefs globally""" uuid = ioreg() path_stub = "/private/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd." das_plist = path_stub + uuid.strip() + ".plist" on_disk = FoundationPlist.readPlist(das_plist) val = on_disk.get('LocationServicesEnabled', None) if val != 1: on_disk['LocationServicesEnabled'] = 1 FoundationPlist.writePlist(on_disk, das_plist) os.chown(das_plist, 205, 205)
def userSelfServiceChoicesChanged(): """Is WRITEABLE_SELF_SERVICE_MANIFEST_PATH different from the 'system' version of this file?""" if not os.path.exists(WRITEABLE_SELF_SERVICE_MANIFEST_PATH): return False user_choices = FoundationPlist.readPlist(WRITEABLE_SELF_SERVICE_MANIFEST_PATH) managedinstallbase = pref("ManagedInstallDir") system_path = os.path.join(managedinstallbase, "manifests", "SelfServeManifest") if not os.path.exists(system_path): return True system_choices = FoundationPlist.readPlist(system_path) return user_choices != system_choices
def escrow_key(key, username, runtype): theurl = pref('ServerURL')+"/checkin/" serial = GetMacSerial() macname = GetMacName() mydata=[('serial',serial),('recovery_password',key),('username',username),('macname',macname)] mydata=urllib.urlencode(mydata) # req = Request(theurl, mydata) # try: # response = urlopen(req) # except URLError, e: # if hasattr(e, 'reason'): # print 'We failed to reach a server.' # print 'Reason: ', e.reason # has_error = True # elif hasattr(e, 'code'): # print 'The server couldn\'t fulfill the request' # print 'Error code: ', e.code # has_error = True cmd = ['/usr/bin/curl', '-fsSL', '--data', mydata, theurl] task = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) proc = task.communicate()[0] if task.returncode != 0: has_error = True else: has_error = False if has_error: plistData = {} plistData['recovery_key']=key plistData['username']=username try: FoundationPlist.writePlist(plistData, '/private/var/root/recovery_key.plist') except: os.makedirs('/usr/local/crypt') FoundationPlist.writePlist(plistData, '/private/var/root/recovery_key.plist') os.chmod('/private/var/root/recovery_key.plist',0700) if runtype=="initial": the_command = "/sbin/reboot" reboot = subprocess.Popen(the_command,shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE).communicate()[0] else: ##need some code to read in the json response from the server, and if the data matches, display success message, or failiure message, then reboot. If not, we need to cache it on disk somewhere - maybe pull it out with facter? #time to turn on filevault #NSLog(u"%s" % fvprefs['ServerURL']) ##escrow successful, if the file exists, remove it thePlist = '/private/var/root/recovery_key.plist' if os.path.exists(thePlist): os.remove(thePlist) if runtype=="initial": the_command = "/sbin/reboot" reboot = subprocess.Popen(the_command,shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE).communicate()[0]
def startUpdateCheck(suppress_apple_update_check=False): '''Does launchd magic to run managedsoftwareupdate as root.''' try: if not os.path.exists(UPDATECHECKLAUNCHFILE): plist = {} plist['SuppressAppleUpdateCheck'] = suppress_apple_update_check try: FoundationPlist.writePlist(plist, UPDATECHECKLAUNCHFILE) except FoundationPlist.FoundationPlistException, err: # problem creating the trigger file raise ProcessStartError(err) except (OSError, IOError), err: raise ProcessStartError(err)
def userSelfServiceChoicesChanged(): '''Is WRITEABLE_SELF_SERVICE_MANIFEST_PATH different from the 'system' version of this file?''' if not os.path.exists(WRITEABLE_SELF_SERVICE_MANIFEST_PATH): return False user_choices = FoundationPlist.readPlist(WRITEABLE_SELF_SERVICE_MANIFEST_PATH) managedinstallbase = pref('ManagedInstallDir') system_path = os.path.join(managedinstallbase, "manifests", "SelfServeManifest") if not os.path.exists(system_path): return True system_choices = FoundationPlist.readPlist(system_path) return (user_choices != system_choices)
def startUpdateCheck(suppress_apple_update_check=False): """Does launchd magic to run managedsoftwareupdate as root.""" try: if not os.path.exists(UPDATECHECKLAUNCHFILE): plist = {} plist["SuppressAppleUpdateCheck"] = suppress_apple_update_check try: FoundationPlist.writePlist(plist, UPDATECHECKLAUNCHFILE) except FoundationPlist.FoundationPlistException: # problem creating the trigger file return 1 return 0 except (OSError, IOError): return 1
def writeFilteredUpdateCatalog(updatelist): '''Write out a sucatalog containing only the updates listed in updatelist. updatelist is a list of ProductIDs.''' # our locally-cached catalog catalogpath = os.path.join(swupdCacheDir(), 'content/catalogs/apple_index.sucatalog') catalog = FoundationPlist.readPlist(catalogpath) if 'Products' in catalog: filtered_products = {} for key in updatelist: filtered_products[key] = catalog['Products'][key] catalog['Products'] = filtered_products filtered_catalogpath = os.path.join(swupdCacheDir(), 'content/catalogs/filtered_index.sucatalog') FoundationPlist.writePlist(catalog, filtered_catalogpath)
def writeAppleUpdatesFile(): '''Writes a file used by Managed Software Update.app to display available updates''' appleUpdates = getSoftwareUpdateInfo() if appleUpdates: plist = {} plist['AppleUpdates'] = appleUpdates FoundationPlist.writePlist(plist, appleUpdatesFile()) return True else: try: os.unlink(appleUpdatesFile()) except (OSError, IOError): pass return False
def writeFilteredUpdateCatalog(updatelist): '''Write out a sucatalog containing only the updates listed in updatelist. updatelist is a list of ProductIDs.''' # our locally-cached catalog catalogpath = os.path.join(swupdCacheDir(), 'content/catalogs/apple_index.sucatalog') catalog = FoundationPlist.readPlist(catalogpath) if 'Products' in catalog: filtered_products = {} for key in updatelist: filtered_products[key] = catalog['Products'][key] catalog['Products'] = filtered_products filtered_catalogpath = os.path.join( swupdCacheDir(), 'content/catalogs/filtered_index.sucatalog') FoundationPlist.writePlist(catalog, filtered_catalogpath)
def create_bundle_info(self, template): info = template info["CFBundleShortVersionString"] = self.env['version'] ver = self.env['version'].split(".") info["IFMajorVersion"] = ver[0] info["IFMinorVersion"] = ver[1] size, nfiles = self.get_pkgroot_size(self.env['pkgroot']) info["IFPkgFlagInstalledSize"] = size try: FoundationPlist.writePlist(info, self.env['infofile']) except BaseException as e: raise ProcessorError("Couldn't write %s: %s" % (self.env['infofile'], e))
def profile_receipt_data(): '''Reads profile install data''' try: profile_data = FoundationPlist.readPlist(profile_receipt_data_path()) return profile_data except BaseException: return {}
def read_signed_profile(profile_path): '''Attempts to read a (presumably) signed profile.''' # filed for future reference: # openssl smime -inform DER -verify -in Signed.mobileconfig # -noverify -out Unsigned.mobileconfig # will strip the signing from a signed profile # this might be a better approach # from: http://apple.stackexchange.com/questions/105981/ # how-do-i-view-or-verify-signed-mobileconfig-files-using-terminal # but... we're going to use an Apple-provided tool instead. cmd = ['/usr/bin/security', 'cms', '-D', '-i', profile_path] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = proc.communicate() if proc.returncode: # security cms -D couldn't decode the file munkicommon.display_error( 'Error reading profile %s: %s' % (profile_path, stderr)) return {} try: return FoundationPlist.readPlistFromString(stdout) except FoundationPlist.NSPropertyListSerializationException, err: # not a valid plist munkicommon.display_error( 'Error reading profile %s: %s' % (profile_path, err)) return {}
def getIdentifierFromProfile(profile_path): profile_dict = FoundationPlist.readPlist(profile_path) try: profile_id = profile_dict['PayloadIdentifier'] except: errorAndExit("Can't find a ProfileIdentifier in the profile at %s." % profile_path) return profile_id
def main(self): """Return a version for file at input_plist_path""" # Check if we're trying to read something inside a dmg. (dmg_path, dmg, dmg_source_path) = self.parsePathForDMG( self.env["input_plist_path"] ) try: if dmg: # Mount dmg and copy path inside. mount_point = self.mount(dmg_path) input_plist_path = os.path.join(mount_point, dmg_source_path) else: # just use the given path input_plist_path = self.env["input_plist_path"] if not os.path.exists(input_plist_path): raise ProcessorError( "File '%s' does not exist or could not be read." % input_plist_path ) try: plist = FoundationPlist.readPlist(input_plist_path) version_key = self.env.get("plist_version_key") self.env["version"] = plist.get(version_key, "UNKNOWN_VERSION") self.output( "Found version %s in file %s" % (self.env["version"], input_plist_path) ) except FoundationPlist.FoundationPlistException as err: raise ProcessorError(err) finally: if dmg: self.unmount(dmg_path)
def read_signed_profile(profile_path): '''Attempts to read a (presumably) signed profile.''' # filed for future reference: # openssl smime -inform DER -verify -in Signed.mobileconfig # -noverify -out Unsigned.mobileconfig # will strip the signing from a signed profile # this might be a better approach # from: https://apple.stackexchange.com/questions/105981/ # how-do-i-view-or-verify-signed-mobileconfig-files-using-terminal # but... we're going to use an Apple-provided tool instead. cmd = ['/usr/bin/security', 'cms', '-D', '-i', profile_path] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = proc.communicate() if proc.returncode: # security cms -D couldn't decode the file munkicommon.display_error('Error reading profile %s: %s' % (profile_path, stderr)) return {} try: return FoundationPlist.readPlistFromString(stdout) except FoundationPlist.NSPropertyListSerializationException, err: # not a valid plist munkicommon.display_error('Error reading profile %s: %s' % (profile_path, err)) return {}
def readPlist(self, pathname): if not pathname: return {} try: return FoundationPlist.readPlist(pathname) except Exception, err: raise ProcessorError('Could not read %s: %s' % (pathname, err))
def config_profile_info(ignore_cache=False): '''Returns a dictionary representing the output of `profiles -C -o`''' global CONFIG_PROFILE_INFO if not profiles_supported(): CONFIG_PROFILE_INFO = {} return CONFIG_PROFILE_INFO if not ignore_cache and CONFIG_PROFILE_INFO is not None: return CONFIG_PROFILE_INFO output_plist = os.path.join(tempfile.mkdtemp(dir=munkicommon.tmpdir()), 'profiles') cmd = ['/usr/bin/profiles', '-C', '-o', output_plist] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) proc.communicate() if proc.returncode != 0: munkicommon.display_error( 'Could not obtain configuration profile info: %s' % proc.stderr) CONFIG_PROFILE_INFO = {} else: try: CONFIG_PROFILE_INFO = FoundationPlist.readPlist(output_plist + '.plist') except BaseException, err: munkicommon.display_error( 'Could not read configuration profile info: %s' % err) CONFIG_PROFILE_INFO = {} finally:
def dmg_has_sla(self, dmgpath): '''Returns true if dmg has a Software License Agreement. These dmgs normally cannot be attached without user intervention''' has_sla = False proc = subprocess.Popen( ['/usr/bin/hdiutil', 'imageinfo', dmgpath, '-plist'], bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = proc.communicate() if stderr: # some error with hdiutil. # Output but return False so we can attempt to continue self.output('hdiutil imageinfo error %s with image %s.' % (stderr, dmgpath)) return False (pliststr, stdout) = self.get_first_plist(stdout) if pliststr: try: plist = FoundationPlist.readPlistFromString(pliststr) properties = plist.get('Properties') if properties: has_sla = properties.get( 'Software License Agreement', False) except FoundationPlist.NSPropertyListSerializationException: pass return has_sla
def loadData(self): pool = NSAutoreleasePool.alloc().init() self.volumes = macdisk.MountedVolumes() theURL = Utils.getServerURL() if theURL: plistData = Utils.downloadFile(theURL) if plistData: try: converted_plist = FoundationPlist.readPlistFromString(plistData) except: self.errorMessage = "Configuration plist couldn't be read." try: self.passwordHash = converted_plist['password'] except: self.errorMessage = "Password wasn't set." try: self.workflows = converted_plist['workflows'] except: self.errorMessage = "No workflows found in the configuration plist." else: self.errorMessage = "Couldn't get configuration plist from server." else: self.errorMessage = "Configuration URL wasn't set." self.performSelectorOnMainThread_withObject_waitUntilDone_( self.loadDataComplete, None, YES) del pool
def create_installs_items(self): """Calls makepkginfo to create an installs array.""" faux_root = "" if self.env.get("faux_root"): faux_root = self.env["faux_root"].rstrip("/") args = ["/usr/local/munki/makepkginfo"] for item in self.env["installs_item_paths"]: args.extend(["-f", faux_root + item]) # Call makepkginfo. try: proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (out, err) = proc.communicate() except OSError as err: raise ProcessorError( "makepkginfo execution failed with error code %d: %s" % (err.errno, err.strerror)) if proc.returncode != 0: raise ProcessorError("creating pkginfo failed: %s" % err) # Get pkginfo from output plist. pkginfo = FoundationPlist.readPlistFromString(out) installs_array = pkginfo.get("installs", []) if faux_root: for item in installs_array: if item["path"].startswith(faux_root): item["path"] = item["path"][len(faux_root):] self.output("Created installs item for %s" % item["path"]) if "version_comparison_key" in self.env: for item in installs_array: cmp_key = None # If it's a string, set it for all installs items if isinstance(self.env["version_comparison_key"], basestring): cmp_key = self.env["version_comparison_key"] # It it's a dict, find if there's a key that matches a path elif isinstance(self.env["version_comparison_key"], NSDictionary): for path, key in self.env["version_comparison_key"].items( ): if path == item["path"]: cmp_key = key if cmp_key: # Check that we really have this key available to compare if cmp_key in item: item["version_comparison_key"] = cmp_key else: raise ProcessorError( "version_comparison_key '%s' could not be found in " "the installs item for path '%s'" % (cmp_key, item["path"])) if "additional_pkginfo" not in self.env: self.env["additional_pkginfo"] = {} self.env["additional_pkginfo"]["installs"] = installs_array
def get_pkginfo_template(pkginfo_template_path): """Return the pkginfo top-level key from a plist file.""" pkginfo_template = FoundationPlist.readPlist( os.path.expanduser(pkginfo_template_path)).get("pkginfo") if not pkginfo_template: sys.exit("Pkginfo template format incorrect!. Quitting.") return pkginfo_template
def createInstallsItems(self): """Calls makepkginfo to create an installs array.""" faux_root = "" if self.env.get("faux_root"): faux_root = self.env["faux_root"].rstrip("/") args = ["/usr/local/munki/makepkginfo"] for item in self.env["installs_item_paths"]: args.extend(["-f", faux_root + item]) # Call makepkginfo. try: proc = subprocess.Popen( args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (out, err) = proc.communicate() except OSError as err: raise ProcessorError( "makepkginfo execution failed with error code %d: %s" % (err.errno, err.strerror)) if proc.returncode != 0: raise ProcessorError( "creating pkginfo failed: %s" % err) # Get pkginfo from output plist. pkginfo = FoundationPlist.readPlistFromString(out) installs_array = pkginfo.get("installs", []) if faux_root: for item in installs_array: if item["path"].startswith(faux_root): item["path"] = item["path"][len(faux_root):] self.output("Created installs item for %s" % item["path"]) if not "additional_pkginfo" in self.env: self.env["additional_pkginfo"] = {} self.env["additional_pkginfo"]["installs"] = installs_array
def main(self): # Check if we're trying to read something inside a dmg. (dmg_path, dmg, dmg_source_path) = self.env['input_plist_path'].partition(".dmg/") dmg_path += ".dmg" try: if dmg: # Mount dmg and copy path inside. mount_point = self.mount(dmg_path) input_plist_path = os.path.join(mount_point, dmg_source_path) else: # just use the given path input_plist_path = self.env['input_plist_path'] try: plist = FoundationPlist.readPlist(input_plist_path) version_key = self.env.get("plist_version_key", "CFBundleShortVersionString") self.env['version'] = plist.get(version_key, "UNKNOWN_VERSION") self.output("Found version %s in file %s" % (self.env['version'], input_plist_path)) except FoundationPlist.FoundationPlistException, err: raise ProcessorError(err) finally: if dmg: self.unmount(dmg_path)
def main(self): # Check if we're trying to read something inside a dmg. (dmg_path, dmg, dmg_source_path) = self.env[ 'input_plist_path'].partition(".dmg/") dmg_path += ".dmg" try: if dmg: # Mount dmg and copy path inside. mount_point = self.mount(dmg_path) input_plist_path = os.path.join(mount_point, dmg_source_path) else: # just use the given path input_plist_path = self.env['input_plist_path'] try: plist = FoundationPlist.readPlist(input_plist_path) version_key = self.env.get( "plist_version_key", "CFBundleShortVersionString") self.env['version'] = plist.get(version_key, "UNKNOWN_VERSION") self.output("Found version %s in file %s" % (self.env['version'], input_plist_path)) except FoundationPlist.FoundationPlistException, err: raise ProcessorError(err) finally: if dmg: self.unmount(dmg_path)
def load_template(self, template_path, template_type): """Load a package info template in Info.plist or PackageInfo format.""" if template_path.endswith(".plist"): # Try to load Info.plist in bundle format. try: info = FoundationPlist.readPlist(self.env['template_path']) except FoundationPlist.FoundationPlistException: raise ProcessorError("Malformed Info.plist template %s" % self.env['template_path']) if template_type == "bundle": return info else: return self.convert_bundle_info_to_flat(info) else: # Try to load PackageInfo in flat format. try: info = ElementTree.parse(template_path) except FoundationPlist.FoundationPlistException: raise ProcessorError("Malformed PackageInfo template %s" % self.env['template_path']) if template_type == "flat": return info else: return self.convert_flat_info_to_bundle(info)