Safari
With the release of Safari 10, it looks like Apple no longer allows for MCX-style management of Safari's preferences. In previous versions, you could easily set a homepage using the following command (ran as the current user):
defaults write com.apple.Safari HomePage "http://HOMEPAGE_URL"
MCX preference settings are still supported through configuration profiles. We can create a custom profile with the following attributes:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>PayloadIdentifier</key> <string>com.laurenceschool.profile.safari.20161111</string> <key>PayloadRemovalDisallowed</key> <true/> <key>PayloadScope</key> <string>System</string> <key>PayloadType</key> <string>Configuration</string> <key>PayloadUUID</key> <string>69F2AD5C-A85E-11E6-80F5-76304DEC7EB7</string> <key>PayloadOrganization</key> <string>Laurence School</string> <key>PayloadVersion</key> <integer>1</integer> <key>PayloadDisplayName</key> <string>Safari Home Page</string> <key>PayloadContent</key> <array> <dict> <key>PayloadType</key> <string>com.apple.ManagedClient.preferences</string> <key>PayloadVersion</key> <integer>1</integer> <key>PayloadIdentifier</key> <string>com.laurenceschool.profile.safari.20161113</string> <key>PayloadUUID</key> <string>E276A24C-A85E-11E6-80F5-76304DEC7EB7</string> <key>PayloadEnabled</key> <true/> <key>PayloadDisplayName</key> <string>Sets the Safari HomePage attribute and locks it in place.</string> <key>PayloadContent</key> <dict> <key>com.apple.Safari</key> <dict> <key>Forced</key> <array> <dict> <key>mcx_preference_settings</key> <dict> <key>AlwaysRestoreSessionAtLaunch</key> <false/> <key>NewWindowBehavior</key> <integer>0</integer> <key>NewTabBehavior</key> <integer>0</integer> <key>HomePage</key> <string>http://HOMEPAGE_URL</string> </dict> </dict> </array> </dict> </dict> </dict> </array> </dict> </plist>
The profile can then be installed for a specific user through a script:
/usr/bin/profiles -I -F /path/to/profile.mobileconfig -U $USER
Google Chrome
The same concept applies for Google Chrome:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>PayloadIdentifier</key> <string>com.laurenceschool.profile.chrome.20161113</string> <key>PayloadRemovalDisallowed</key> <true/> <key>PayloadScope</key> <string>System</string> <key>PayloadType</key> <string>Configuration</string> <key>PayloadUUID</key> <string>6A53E33E-A9E8-11E6-80F5-76304DEC7EB7</string> <key>PayloadOrganization</key> <string>Laurence School</string> <key>PayloadVersion</key> <integer>1</integer> <key>PayloadDisplayName</key> <string>Google Chrome Homepage</string> <key>PayloadContent</key> <array> <dict> <key>PayloadType</key> <string>com.apple.ManagedClient.preferences</string> <key>PayloadVersion</key> <integer>1</integer> <key>PayloadIdentifier</key> <string>com.laurenceschool.profile.chrome.20161113</string> <key>PayloadUUID</key> <string>BC8C5630-A9E9-11E6-80F5-76304DEC7EB7</string> <key>PayloadEnabled</key> <true/> <key>PayloadDisplayName</key> <string>Sets the Chrome HomePage attribute and locks it in place.</string> <key>PayloadContent</key> <dict> <key>com.google.Chrome</key> <dict> <key>Forced</key> <array> <dict> <key>mcx_preference_settings</key> <dict> <key>AutoFillEnabled</key> <false/> <key>DefaultBrowserSettingEnabled</key> <false/> <key>BookmarkBarEnabled</key> <true/> <key>HideWebStorePromo</key> <true/> <key>HomepageIsNewTabPage</key> <false/> <key>HomepageLocation</key> <string>http://HOMEPAGE_URL</string> <key>PasswordManagerEnabled</key> <false/> <key>RestoreOnStartup</key> <integer>4</integer> <key>RestoreOnStartupURLs</key> <array> <string>http://HOMEPAGE_URL</string> </array> <key>ShowHomeButton</key> <true/> <key>SyncDisabled</key> <false/> <key>DefaultNotificationsSetting</key> <integer>2</integer> <key>ImportAutofillFormData</key> <false/> <key>ImportBookmarks</key> <false/> <key>ImportHistory</key> <false/> <key>ImportHomepage</key> <false/> <key>ImportSearchEngine</key> <false/> <key>ImportSavedPasswords</key> <false/> </dict> </dict> </array> </dict> </dict> </dict> </array> </dict> </plist>
Firefox
Firefox, however, does not support MCX or Configuration Profile management. There is a third party extension that allows customizing preferences and then exporting them as an add-on package. For our purposes, we will create an override autoconfig.js file inside the app directory itself. The JS file will initially point to a CFG file. This allows us to lock the settings using javascript:
// This file is saved to // Firefox.app/Contents/Resources/defaults/pref/autoconfig.js pref("general.config.filename", "firefox.cfg"); pref("general.config.obscure_value", 0);
// This file is saved to // Firefox.app/Contents/Resources/firefox.cfg // Disable updater lockPref("app.update.enabled", false); // make absolutely sure it is really off lockPref("app.update.auto", false); lockPref("app.update.mode", 0); lockPref("app.update.service.enabled", false); // Disable Add-ons compatibility checking clearPref("extensions.lastAppVersion"); // Don't show 'know your rights' on first run pref("browser.rights.3.shown", true); // Don't show WhatsNew on first run after every update pref("browser.startup.homepage_override.mstone", "ignore"); // Set default homepage lockPref("browser.startup.homepage","http://HOMEPAGE_URL"); // Disable the internal PDF viewer pref("pdfjs.disabled", true); // Disable the flash to javascript converter pref("shumway.disabled", true); // Don't ask to install the Flash plugin pref("plugins.notifyMissingFlash", false); // Plugin checking lockPref("plugins.hide_infobar_for_outdated_plugin", true); clearPref("plugins.update.url"); // Health reporter lockPref("datareporting.healthreport.service.enabled", false); // Telemetry and FHR lockPref("datareporting.policy.dataSubmissionEnabled", false); // Crash reporter lockPref("toolkit.crashreporter.enabled", false); Components.classes["@mozilla.org/toolkit/crash-reporter;1"].getService(Components.interfaces.nsICrashReporter).submitReports = false; // Popup blocker lockPref("dom.disable_open_during_load", true); // Popup whitelist Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/NetUtil.jsm"); Services.perms.add(NetUtil.newURI("http://ALLOWED_URL"), "popup", Services.perms.ALLOW_ACTION); // Set default search engine Components.utils.import("resource://gre/modules/Services.jsm"); var searchService = Services.search; var engine = searchService.getEngineByName("Google"); searchService.currentEngine = engine;
Note: This configuration will reset with each update to the app since Munki will override the actual executable. This deployment should be included as an 'update-to' package to ensure that it is continuously applied after each app update.
Signing Configuration Profiles
Custom profiles, or profiles created outside of Profile Manager/Apple Configurator, are not signed. We can sign them manually with a trusted certificate from the Apple Developer program.
Sign in to the Developer portal and download a Mac Developer Application cert. After it's installed to the keychain, verify that it's available as a code signing identity:
/usr/bin/security find-identity -p codesigning -v
Then use it to sign a profile:
/usr/bin/security cms -S -N "3rd Party Mac Developer Application: Laurence School Apps (4MESE8N7WN)" -i /path/to/profile.mobileconfig -o /path/to/signedprofile.mobileconfig
The resulting profile will now appear verified to the user.