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.