├── .gitignore ├── LICENSE ├── README.md ├── allow_localonly_login.sh ├── chrome-enable-autoupdates.py ├── enrollment_config_helper ├── com.isd720.enrollment-config-helper.plist ├── enrollment_config_helper-2.0.pkg.zip └── enrollment_config_helper.sh ├── forget_SSIDs.py ├── nomad_disable_welcome.sh ├── postinstall_BitnamiMAMP.sh ├── set_finder_prefs.py ├── set_timezone.py └── uninstall_relay_agent.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # General 2 | .DS_Store 3 | .AppleDouble 4 | .LSOverride 5 | 6 | # Thumbnails 7 | ._* 8 | 9 | # Files that might appear in the root of a volume 10 | .DocumentRevisions-V100 11 | .fseventsd 12 | .Spotlight-V100 13 | .TemporaryItems 14 | .Trashes 15 | .VolumeIcon.icns 16 | .com.apple.timemachine.donotpresent 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Nathaniel Strauss 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # macos-management-scripts 2 | Collection of scripts to help manage macOS 3 | -------------------------------------------------------------------------------- /allow_localonly_login.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Only allow local account login 4 | dseditgroup -o create -q com.apple.access_loginwindow 5 | dseditgroup -o edit -n /Local/Default -a "localaccounts" -t group com.apple.access_loginwindow 6 | 7 | exit $? -------------------------------------------------------------------------------- /chrome-enable-autoupdates.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | """ 4 | chrome-enable-autoupdates.py 5 | 6 | This script enables system wide automatic updates for Google Chrome. 7 | It should work for Chrome versions 18 and later. No configuration needed 8 | as this is originally intended as a munki postinstall script. 9 | 10 | Created by Hannes Juutilainen, hjuutilainen@mac.com 11 | 12 | History: 13 | -------- 14 | 2019-08-05, Andy Duss 15 | - Fix keystone_registration_framework_path to point to correct directory 16 | 17 | 2017-09-01, Hannes Juutilainen 18 | - Ignore errors when installing keystone 19 | 20 | 2015-09-25, Niklas Blomdalen 21 | - Modifications to include old KeystoneRegistration installation (python version) 22 | 23 | 2014-11-20, Hannes Juutilainen 24 | - Modifications for Chrome 39 25 | 26 | 2012-08-31, Hannes Juutilainen 27 | - Added --force flag to keystone install as suggested by Riley Shott 28 | 29 | 2012-05-29, Hannes Juutilainen 30 | - Added more error checking 31 | 32 | 2012-05-25, Hannes Juutilainen 33 | - Added some error checking in main 34 | 35 | 2012-05-24, Hannes Juutilainen 36 | - First version 37 | 38 | """ 39 | 40 | import sys 41 | import os 42 | import subprocess 43 | import plistlib 44 | from distutils.version import LooseVersion 45 | 46 | chrome_path = "/Applications/Google Chrome.app" 47 | info_plist_path = os.path.realpath(os.path.join(chrome_path, 'Contents/Info.plist')) 48 | brand_path = "/Library/Google/Google Chrome Brand.plist" 49 | brand_key = "KSBrandID" 50 | tag_path = info_plist_path 51 | tag_key = "KSChannelID" 52 | version_path = info_plist_path 53 | version_key = "KSVersion" 54 | 55 | 56 | class Usage(Exception): 57 | def __init__(self, msg): 58 | self.msg = msg 59 | 60 | 61 | def chrome_installed(): 62 | """Check if Chrome is installed""" 63 | if os.path.exists(chrome_path): 64 | return True 65 | else: 66 | return False 67 | 68 | 69 | def chrome_version(): 70 | """Returns Chrome version""" 71 | info_plist = plistlib.readPlist(info_plist_path) 72 | bundle_short_version = info_plist["CFBundleShortVersionString"] 73 | return bundle_short_version 74 | 75 | 76 | def chrome_update_url(): 77 | """Returns KSUpdateURL from Chrome Info.plist""" 78 | info_plist = plistlib.readPlist(info_plist_path) 79 | update_url = info_plist["KSUpdateURL"] 80 | return update_url 81 | 82 | 83 | def chrome_product_id(): 84 | """Returns KSProductID from Chrome Info.plist""" 85 | info_plist = plistlib.readPlist(info_plist_path) 86 | product_id = info_plist["KSProductID"] 87 | return product_id 88 | 89 | 90 | def keystone_registration_framework_path(): 91 | """Returns KeystoneRegistration.framework path""" 92 | if LooseVersion(chrome_version()) >= LooseVersion("76"): 93 | keystone_registration = os.path.join(chrome_path, 'Contents', 'Frameworks') 94 | keystone_registration = os.path.join(keystone_registration, 'Google Chrome Framework.framework') 95 | keystone_registration = os.path.join(keystone_registration, 'Frameworks', 'KeystoneRegistration.framework') 96 | keystone_registration = os.path.join(keystone_registration, 'Versions', 'Current') 97 | elif LooseVersion(chrome_version()) >= LooseVersion("75") and LooseVersion(chrome_version()) < LooseVersion("76"): 98 | keystone_registration = os.path.join(chrome_path, 'Contents/Frameworks/') 99 | keystone_registration = os.path.join(keystone_registration, 'Google Chrome Framework.framework/Versions') 100 | keystone_registration = os.path.join(keystone_registration, chrome_version()) 101 | keystone_registration = os.path.join(keystone_registration, 'Frameworks/KeystoneRegistration.framework') 102 | else: 103 | keystone_registration = os.path.join(chrome_path, 'Contents/Versions') 104 | keystone_registration = os.path.join(keystone_registration, chrome_version()) 105 | keystone_registration = os.path.join(keystone_registration, 'Google Chrome Framework.framework') 106 | keystone_registration = os.path.join(keystone_registration, 'Frameworks/KeystoneRegistration.framework') 107 | return keystone_registration 108 | 109 | 110 | def keystone_install(): 111 | """Install the current Keystone""" 112 | install_script = os.path.join(keystone_registration_framework_path(), 'Resources/ksinstall') 113 | if not os.path.exists(install_script): 114 | install_script = os.path.join(keystone_registration_framework_path(), 'Resources/install.py') 115 | keystone_payload = os.path.join(keystone_registration_framework_path(), 'Resources/Keystone.tbz') 116 | if os.path.exists(install_script) and os.path.exists(keystone_payload): 117 | ksinstall_process = [ 118 | install_script, 119 | '--install', keystone_payload, 120 | '--force' 121 | ] 122 | p = subprocess.Popen(ksinstall_process, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 123 | (results, error) = p.communicate() 124 | if results: 125 | print results 126 | if p.returncode != 0: 127 | if error: 128 | print >> sys.stderr, "%s" % error 129 | print >> sys.stderr, "Keystone install exited with code %i" % p.returncode 130 | 131 | # Since we used --force argument, succeed no matter what the exit code was. 132 | return True 133 | else: 134 | print >> sys.stderr, "Error: KeystoneRegistration.framework not found" 135 | return False 136 | 137 | 138 | def register_chrome_with_keystone(): 139 | """Registers Chrome with Keystone""" 140 | ksadmin = "/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksadmin" 141 | if os.path.exists(ksadmin): 142 | ksadmin_process = [ 143 | ksadmin, 144 | '--register', 145 | '--productid', chrome_product_id(), 146 | '--version', chrome_version(), 147 | '--xcpath', chrome_path, 148 | '--url', chrome_update_url(), 149 | '--tag-path', tag_path, 150 | '--tag-key', tag_key, 151 | '--brand-path', brand_path, 152 | '--brand-key', brand_key, 153 | '--version-path', version_path, 154 | '--version-key', version_key 155 | ] 156 | p = subprocess.Popen(ksadmin_process, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 157 | (results, error) = p.communicate() 158 | if error: 159 | print >> sys.stderr, "%s" % error 160 | if results: 161 | print results 162 | if p.returncode == 0: 163 | return True 164 | else: 165 | return False 166 | else: 167 | print >> sys.stderr, "Error: %s doesn't exist" % ksadmin 168 | return False 169 | 170 | 171 | def main(argv=None): 172 | if argv is None: 173 | argv = sys.argv 174 | try: 175 | # Check for root 176 | if os.geteuid() != 0: 177 | print >> sys.stderr, "This script must be run as root" 178 | return 1 179 | 180 | if not chrome_installed(): 181 | print >> sys.stderr, "Error: Chrome is not installed on this computer" 182 | return 1 183 | if keystone_install(): 184 | print "Keystone installed" 185 | else: 186 | print >> sys.stderr, "Error: Keystone install failed" 187 | return 1 188 | if register_chrome_with_keystone(): 189 | print "Registered Chrome with Keystone" 190 | return 0 191 | else: 192 | print >> sys.stderr, "Error: Failed to register Chrome with Keystone" 193 | return 1 194 | 195 | except Usage, err: 196 | print >> sys.stderr, err.msg 197 | print >> sys.stderr, "for help use --help" 198 | return 2 199 | 200 | 201 | if __name__ == "__main__": 202 | sys.exit(main()) -------------------------------------------------------------------------------- /enrollment_config_helper/com.isd720.enrollment-config-helper.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Label 6 | com.isd720.enrollment-config-helper 7 | LaunchOnlyOnce 8 | 9 | Program 10 | /private/var/tmp/enrollment_config_helper.sh 11 | RunAtLoad 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /enrollment_config_helper/enrollment_config_helper-2.0.pkg.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nstrauss/macos-management-scripts/855d2538c43bc1a6c60a954cf27ca64d195bf2d8/enrollment_config_helper/enrollment_config_helper-2.0.pkg.zip -------------------------------------------------------------------------------- /enrollment_config_helper/enrollment_config_helper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | # Configurable retries. How many retries in a cycle, how many total cycles. 4 | retries="3" 5 | cycles="10" 6 | 7 | # Log paths 8 | log_file="/var/tmp/mds_dep_enroll.log" 9 | pm_data="/var/tmp/pm_data.plist" 10 | 11 | timestamp () { 12 | echo $(date "+%a %h %d %H:%M:%S") 13 | } 14 | 15 | # Check if script running as root 16 | if [[ $EUID != 0 ]] ; then 17 | echo $(timestamp) "Failed to run. Must run as root or with sudo." >> "$log_file" 18 | exit 1 19 | fi 20 | 21 | echo $(timestamp) "Starting enrollment configuration helper..." >> "$log_file" 22 | echo $(timestamp) "Waiting for setup assistant..." >> "$log_file" 23 | 24 | # Only start script once Setup Assistant has launched 25 | until [[ $(pgrep -x "Setup Assistant") ]]; do 26 | wait 27 | done 28 | 29 | echo $(timestamp) "Setup assistant is up." >> "$log_file" 30 | 31 | # Append OS info 32 | os_version=$(defaults read /System/Library/CoreServices/SystemVersion.plist ProductVersion) 33 | os_build=$(defaults read /System/Library/CoreServices/SystemVersion.plist ProductBuildVersion) 34 | echo $(timestamp) "OS version: ${os_version}" >> "$log_file" 35 | echo $(timestamp) "OS build: ${os_build}" >> "$log_file" 36 | 37 | # Run enrollment configuration check 38 | config_status="" 39 | for x in {1.."$cycles"}; do 40 | echo $(timestamp) "Starting cycle ${x}..." >> "$log_file" 41 | 42 | # Get power metrics data and append thermal data 43 | echo $(timestamp) "Checking power metrics..." >> "$log_file" 44 | powermetrics -i 1 -n 1 --samplers smc,thermal --format plist > "$pm_data" 45 | cpu_thermal_level=$(/usr/libexec/PlistBuddy -c "print 'smc':cpu_thermal_level" ${pm_data}) 46 | io_thermal_level=$(/usr/libexec/PlistBuddy -c "print 'smc':io_thermal_level" ${pm_data}) 47 | fan_rpm=$(/usr/libexec/PlistBuddy -c "print 'smc':fan" ${pm_data}) 48 | cpu_die_temp=$(/usr/libexec/PlistBuddy -c "print 'smc':cpu_die" ${pm_data}) 49 | thermal_pressure=$(defaults read ${pm_data} thermal_pressure) 50 | echo $(timestamp) "CPU thermal level: ${cpu_thermal_level}" >> "$log_file" 51 | echo $(timestamp) "IO thermal level: ${io_thermal_level}" >> "$log_file" 52 | echo $(timestamp) "Fan RPM: ${fan_rpm}" >> "$log_file" 53 | echo $(timestamp) "CPU die temp: ${cpu_die_temp} C" >> "$log_file" 54 | echo $(timestamp) "Thermal pressure: ${thermal_pressure}" >> "$log_file" 55 | 56 | # Attempt to get enrollment configuration 57 | echo $(timestamp) "Getting enrollment configuration..." >> "$log_file" 58 | for i in {1.."$retries"}; do 59 | sleep 5 60 | profiles renew -type enrollment &>> "$log_file" 61 | if [[ $? == "0" ]]; then 62 | echo $(timestamp) "Got enrollment configuration..." >> "$log_file" 63 | sleep 2 64 | profiles show -type enrollment &>> "$log_file" 65 | 66 | # Delete launch daemon 67 | rm -rf /Library/LaunchDaemons/com.isd720.enrollment-config-helper.plist 68 | 69 | # Mark config status as succeeded 70 | config_status="success" 71 | break 72 | else 73 | echo $(timestamp) "Failed to get enrollment configuration - attempt ${i}" >> "$log_file" 74 | fi 75 | done 76 | if [[ "$config_status" = "success" ]]; then 77 | break 78 | else 79 | if [[ "$x" = "$cycles" ]]; then 80 | echo $(timestamp) "*** Gone through ${x} failed cycles. Stop here. Shut down Mac, let it cool for 10 minutes, and try again." >> "$log_file" 81 | exit 1 82 | else 83 | echo $(timestamp) "Cycle ${x} - all attempts failed. Waiting 1 minute for Mac to cool down before trying again." >> "$log_file" 84 | sleep 60 85 | fi 86 | fi 87 | done 88 | -------------------------------------------------------------------------------- /forget_SSIDs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # encoding: utf-8 3 | 4 | # original author: Matthew Warren 5 | # @haircut on #macadmins slack 6 | # created: 2018-04-20 7 | # modified: 2018-04-21 8 | # edited: Nathaniel Strauss 9 | # modified: 2019-05-08 10 | # https://gist.github.com/haircut/b5d5bea915a58c9b61160c857e7a08a2 11 | 12 | """ 13 | Forget saved SSIDs with whitelisting. 14 | 15 | This script removes ALL saved SSIDs on a Mac except for those configured in a 16 | whitelist – see SSID_WHITELIST variable below. 17 | 18 | If you configure Wi-Fi via profile you must exclude those configured SSIDs. 19 | The networksetup binary does not care about your profiles! 20 | """ 21 | 22 | import subprocess 23 | import sys 24 | 25 | # pylint: disable=E0611 26 | from SystemConfiguration import ( 27 | SCNetworkInterfaceCopyAll, 28 | SCNetworkInterfaceGetBSDName, 29 | SCNetworkInterfaceGetHardwareAddressString, 30 | SCNetworkInterfaceGetLocalizedDisplayName, 31 | ) 32 | 33 | SSID_WHITELIST = ["WirelessSSID1", "WirelessSSID2"] 34 | 35 | 36 | def get_wifi_interface(): 37 | """Returns the name of the wifi interface.""" 38 | network_interfaces = SCNetworkInterfaceCopyAll() 39 | interfaces = {} 40 | for interface in network_interfaces: 41 | interfaces[SCNetworkInterfaceGetLocalizedDisplayName(interface)] = ( 42 | SCNetworkInterfaceGetBSDName(interface), 43 | SCNetworkInterfaceGetHardwareAddressString(interface), 44 | ) 45 | wifi_interface = None 46 | try: 47 | wifi_interface = interfaces["Wi-Fi"][0] 48 | except KeyError: 49 | pass 50 | return wifi_interface 51 | 52 | 53 | def get_ssids(interface): 54 | """Returns a list of saved SSIDs for the provided interface.""" 55 | cmd = ["networksetup", "-listpreferredwirelessnetworks", interface] 56 | proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 57 | output, _ = proc.communicate() 58 | return [item.strip() for item in output.splitlines()[1:]] 59 | 60 | 61 | def remove_ssid(ssid, interface): 62 | """Removes the passed SSID from the preferred SSID list on the passed 63 | interface.""" 64 | cmd = ["networksetup", "-removepreferredwirelessnetwork", interface, ssid] 65 | proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 66 | output, _ = proc.communicate() 67 | return True if proc.returncode == 0 else False 68 | 69 | 70 | def main(): 71 | """Main.""" 72 | interface = get_wifi_interface() 73 | # Exit cleanly on Macs with no wireless interface 74 | if interface is None: 75 | print("No Wi-Fi interface. Exiting.") 76 | sys.exit(0) 77 | 78 | # Remove SSIDs 79 | ssids = get_ssids(interface) 80 | for ssid in ssids: 81 | if ssid not in SSID_WHITELIST: 82 | if remove_ssid(ssid, interface): 83 | print("Removed SSID %s" % ssid) 84 | else: 85 | print("Unable to remove SSID %s" % ssid) 86 | 87 | 88 | if __name__ == "__main__": 89 | main() 90 | -------------------------------------------------------------------------------- /nomad_disable_welcome.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | defaults="/usr/bin/defaults" 4 | 5 | "$defaults" write /Library/Preferences/com.trusourcelabs.NoMAD DontShowWelcome -bool TRUE 6 | "$defaults" write /Library/Preferences/com.trusourcelabs.NoMAD DontShowWelcomeDefaultOn -bool TRUE 7 | -------------------------------------------------------------------------------- /postinstall_BitnamiMAMP.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | # User variables 4 | logged_in_user=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ && ! /loginwindow/ { print $3 }') 5 | 6 | # Installer variables 7 | base_pass="shakopeesabers" 8 | install_dir="/Users/${logged_in_user}/Applications/mampstack" 9 | 10 | # Run installer 11 | sudo -u "$logged_in_user" /private/tmp/MAMP.app/Contents/MacOS/osx-x86_64 \ 12 | --mode unattended \ 13 | --prefix "$install_dir" \ 14 | --base_password "$base_pass" \ 15 | --launch_cloud "0" 16 | 17 | # Create symlink to user desktop 18 | ln -s "$install_dir"/manager-osx.app "/Users/${logged_in_user}/Desktop/Application Manager.app" 19 | 20 | # Clean up 21 | rm -rf /private/tmp/MAMP.app -------------------------------------------------------------------------------- /set_finder_prefs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # encoding: utf-8 3 | 4 | """ 5 | set_finder_prefs.py 6 | Set user level finder preferences using defaults for values listed in the 7 | provided dictionary. User must be logged in. 8 | """ 9 | 10 | import subprocess 11 | 12 | # pylint: disable=E0611 13 | from SystemConfiguration import SCDynamicStoreCopyConsoleUser 14 | 15 | 16 | FINDER_PREFS = { 17 | "ShowStatusBar": {"type": "-bool", "value": "TRUE"}, 18 | "ShowPathBar": {"type": "-bool", "value": "TRUE"}, 19 | "FXPreferredViewStyle": {"type": "-string", "value": "Nlsv"}, 20 | } 21 | 22 | 23 | def get_currentuser(): 24 | """Uses Apple's SystemConfiguration framework to get the current 25 | console user. Stolen from munki code. 26 | https://github.com/munki/munki/blob/master/code/client/launchapp""" 27 | cfuser = SCDynamicStoreCopyConsoleUser(None, None, None) 28 | return cfuser[0] 29 | 30 | 31 | def set_pref(username, pref, data_type, value): 32 | cmd = [ 33 | "/usr/bin/sudo", 34 | "-u", 35 | username, 36 | "/usr/bin/defaults", 37 | "write", 38 | "com.apple.finder", 39 | pref, 40 | data_type, 41 | value, 42 | ] 43 | subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 44 | 45 | 46 | if __name__ == "__main__": 47 | user = get_currentuser() 48 | for pref in FINDER_PREFS: 49 | data_type = FINDER_PREFS[pref]["type"] 50 | value = FINDER_PREFS[pref]["value"] 51 | set_pref(user, pref, data_type, value) 52 | -------------------------------------------------------------------------------- /set_timezone.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # encoding: utf-8 3 | 4 | """ 5 | set_timezone.py 6 | Use built-in tools to sync NTP server and set time zone. Default is to sync to 7 | Apple's default time.apple.server. Zone can be changed with TIME_ZONE. 8 | 9 | OS version code stolen mostly from Munki. 10 | https://github.com/munki/munki/blob/master/code/client/munkilib/osutils.py 11 | """ 12 | 13 | import platform 14 | import subprocess 15 | 16 | TIME_ZONE = "America/Chicago" 17 | 18 | 19 | def get_os_version(only_major_minor=True, only_major=False, as_tuple=False): 20 | """Returns an OS version. 21 | Args: 22 | only_major_minor: Boolean. If True, only include major/minor versions. 23 | only_major: Boolean. If True, only include major version. 24 | as_tuple: Boolean. If True, return a tuple of ints, otherwise a string. 25 | """ 26 | os_version_tuple = platform.mac_ver()[0].split(".") 27 | if only_major_minor: 28 | os_version_tuple = os_version_tuple[0:2] 29 | if only_major: 30 | os_version_tuple = os_version_tuple[1:2] 31 | if as_tuple: 32 | return tuple(map(int, os_version_tuple)) 33 | else: 34 | return ".".join(os_version_tuple) 35 | 36 | 37 | def sync_ntp(server, major_version): 38 | """Get major version, sync NTP using that version's tool.""" 39 | if major_version <= 13: 40 | cmd = ["/usr/sbin/ntpdate", "-u", server] 41 | if major_version >= 14: 42 | cmd = ["/usr/bin/sntp", "-sS", server] 43 | 44 | try: 45 | subprocess.check_call(cmd, stdout=subprocess.PIPE) 46 | except subprocess.CalledProcessError as err: 47 | print(err) 48 | 49 | 50 | def set_timezone(timezone): 51 | """Set system time zone.""" 52 | cmd = ["/usr/sbin/systemsetup", "-settimezone", timezone] 53 | try: 54 | proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 55 | out = proc.communicate() 56 | return out 57 | except Exception as err: 58 | print(err) 59 | 60 | 61 | if __name__ == "__main__": 62 | major_version = int(get_os_version(only_major=True)) 63 | sync_ntp("time.apple.com", major_version) 64 | set_timezone(TIME_ZONE) 65 | -------------------------------------------------------------------------------- /uninstall_relay_agent.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | # Mac Mobile Filter removal script 4 | # Copyright Lightspeed Systems 2013 5 | # Modified by Nathaniel Strauss 2020 because yikes 6 | 7 | if [[ $EUID != 0 ]] ; then 8 | echo "Must be run as root or via sudo" 9 | exit 1 10 | fi 11 | 12 | # Unload launch daemons 13 | launchctl unload /Library/LaunchDaemons/com.lightspeedsystems.lsproxy.plist > /dev/null 2>&1 14 | launchctl unload /Library/LaunchDaemons/com.lightspeedsystems.mobilefilter.plist > /dev/null 2>&1 15 | launchctl unload /Library/LaunchDaemons/com.lightspeedsystems.proxyforce.plist > /dev/null 2>&1 16 | launchctl unload /Library/LaunchDaemons/com.lightspeedsystems.smartagentjs.plist > /dev/null 2>&1 17 | 18 | # Delete launch daemons 19 | rm -rf /Library/LaunchDaemons/com.lightspeedsystems.lsproxy.plist > /dev/null 2>&1 20 | rm -rf /Library/LaunchDaemons/com.lightspeedsystems.mobilefilter.plist > /dev/null 2>&1 21 | rm -rf /Library/LaunchDaemons/com.lightspeedsystems.proxyforce.plist > /dev/null 2>&1 22 | rm -rf /Library/LaunchDaemons/com.lightspeedsystems.smartagentjs.plist > /dev/null 2>&1 23 | 24 | # Unload agent associated processes and kernel extension 25 | /usr/local/bin/cagen unload > /dev/null 2>&1 26 | /usr/local/bin/mobilefilter -unload > /dev/null 2>&1 27 | /usr/local/bin/proxyforce unload > /dev/null 2>&1 28 | /sbin/kextunload -b com.lightspeedsystems.kext.MobileFilterKext 29 | 30 | # Remove smart agent files 31 | rm /usr/local/bin/cagen > /dev/null 2>&1 32 | rm /usr/local/etc/ca_key.pem > /dev/null 2>&1 33 | rm /usr/local/etc/ca.pem > /dev/null 2>&1 34 | rm /usr/local/bin/com.lightspeedsystems.restartservices.plist > /dev/null 2>&1 35 | rm /usr/local/bin/LightspeedSmartAgentCopyrights.rtf > /dev/null 2>&1 36 | rm /usr/local/bin/lsproxy > /dev/null 2>&1 37 | rm /usr/local/bin/makeca > /dev/null 2>&1 38 | rm /usr/local/bin/mobilefilter > /dev/null 2>&1 39 | rm /usr/local/bin/mobilefilterupdatekext > /dev/null 2>&1 40 | rm /usr/local/bin/mobilefilterupdate > /dev/null 2>&1 41 | rm /usr/local/bin/mobilefilterupdatecopy > /dev/null 2>&1 42 | rm /usr/local/bin/proxyforce > /dev/null 2>&1 43 | rm -rf /usr/local/bin/SmartAgentJS > /dev/null 2>&1 44 | rm /usr/local/etc/ca_key.pem > /dev/null 2>&1 45 | rm /usr/local/etc/ca.pem > /dev/null 2>&1 46 | rm /usr/local/etc/localhost_key.pem > /dev/null 2>&1 47 | rm /usr/local/etc/localhost.pem > /dev/null 2>&1 48 | rm /usr/local/etc/SmartAgentUpdate.dmg > /dev/null 2>&1 49 | 50 | # Remove kext 51 | rm -rf /Library/Extensions/MobileFilterKext.kext > /dev/null 2>&1 52 | --------------------------------------------------------------------------------