Posted on 11-05-2019 02:51 AM
We're trying to manage Chrome with a Config Profile, because it's way easier than with the master preferences file. So far the config profile works as intended, but Google Chrome won't update. It keeps saying "Google Chrome may not be able to keep itself updated", even though it also says "Automatic Updates are enabled". The keystone Agent and Daemon are both included in the Package, as is "Google Software Update" in /Library/Google/.
The only time I get Google to update is with 777 permissions, which we would rather avoid.
I noticed some people on here using a script to auto update Chrome, which we would also rather avoid due to the sheer amount of clients we manage.
Does anyone know how to make Chrome update itself with the setup we're trying to use?
Thanks!
Posted on 11-05-2019 05:16 AM
Following this thread as I am quite interested in this as well.
Posted on 11-05-2019 06:58 AM
@msoti The following has worked well in our environment. We basically have a base installer of Google Chrome (it hasn't been updated since July 2019) and then we enable auto-updated with the following script (I have scoped once per computer, triggered during check-in and enrollment).
#!/usr/bin/env python
# encoding: utf-8
"""
chrome-enable-autoupdates.py
This script enables system wide automatic updates for Google Chrome.
It should work for Chrome versions 18 and later. No configuration needed
as this is originally intended as a munki postinstall script.
Created by Hannes Juutilainen, hjuutilainen@mac.com
History:
2019-08-05, Andy Duss
- Fix keystone_registration_framework_path to point to correct directory
2017-09-01, Hannes Juutilainen
- Ignore errors when installing keystone
2015-09-25, Niklas Blomdalen
- Modifications to include old KeystoneRegistration installation (python version)
2014-11-20, Hannes Juutilainen
- Modifications for Chrome 39
2012-08-31, Hannes Juutilainen
- Added --force flag to keystone install as suggested by Riley Shott
2012-05-29, Hannes Juutilainen
- Added more error checking
2012-05-25, Hannes Juutilainen
- Added some error checking in main
2012-05-24, Hannes Juutilainen
- First version
"""
import sys
import os
import subprocess
import plistlib
from distutils.version import LooseVersion
chrome_path = "/Applications/Google Chrome.app"
info_plist_path = os.path.realpath(os.path.join(chrome_path, 'Contents/Info.plist'))
brand_path = "/Library/Google/Google Chrome Brand.plist"
brand_key = "KSBrandID"
tag_path = info_plist_path
tag_key = "KSChannelID"
version_path = info_plist_path
version_key = "KSVersion"
class Usage(Exception):
def __init__(self, msg):
self.msg = msg
def chrome_installed():
"""Check if Chrome is installed"""
if os.path.exists(chrome_path):
return True
else:
return False
def chrome_version():
"""Returns Chrome version"""
info_plist = plistlib.readPlist(info_plist_path)
bundle_short_version = info_plist["CFBundleShortVersionString"]
return bundle_short_version
def chrome_update_url():
"""Returns KSUpdateURL from Chrome Info.plist"""
info_plist = plistlib.readPlist(info_plist_path)
update_url = info_plist["KSUpdateURL"]
return update_url
def chrome_product_id():
"""Returns KSProductID from Chrome Info.plist"""
info_plist = plistlib.readPlist(info_plist_path)
product_id = info_plist["KSProductID"]
return product_id
def keystone_registration_framework_path():
"""Returns KeystoneRegistration.framework path"""
if LooseVersion(chrome_version()) >= LooseVersion("76"):
keystone_registration = os.path.join(chrome_path, 'Contents', 'Frameworks')
keystone_registration = os.path.join(keystone_registration, 'Google Chrome Framework.framework')
keystone_registration = os.path.join(keystone_registration, 'Frameworks', 'KeystoneRegistration.framework')
keystone_registration = os.path.join(keystone_registration, 'Versions', 'Current')
elif LooseVersion(chrome_version()) >= LooseVersion("75") and LooseVersion(chrome_version()) < LooseVersion("76"):
keystone_registration = os.path.join(chrome_path, 'Contents/Frameworks/')
keystone_registration = os.path.join(keystone_registration, 'Google Chrome Framework.framework/Versions')
keystone_registration = os.path.join(keystone_registration, chrome_version())
keystone_registration = os.path.join(keystone_registration, 'Frameworks/KeystoneRegistration.framework')
else:
keystone_registration = os.path.join(chrome_path, 'Contents/Versions')
keystone_registration = os.path.join(keystone_registration, chrome_version())
keystone_registration = os.path.join(keystone_registration, 'Google Chrome Framework.framework')
keystone_registration = os.path.join(keystone_registration, 'Frameworks/KeystoneRegistration.framework')
return keystone_registration
def keystone_install():
"""Install the current Keystone"""
install_script = os.path.join(keystone_registration_framework_path(), 'Resources/ksinstall')
if not os.path.exists(install_script):
install_script = os.path.join(keystone_registration_framework_path(), 'Resources/install.py')
keystone_payload = os.path.join(keystone_registration_framework_path(), 'Resources/Keystone.tbz')
if os.path.exists(install_script) and os.path.exists(keystone_payload):
ksinstall_process = [
install_script,
'--install', keystone_payload,
'--force'
]
p = subprocess.Popen(ksinstall_process, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(results, error) = p.communicate()
if results:
print results
if p.returncode != 0:
if error:
print >> sys.stderr, "%s" % error
print >> sys.stderr, "Keystone install exited with code %i" % p.returncode
# Since we used --force argument, succeed no matter what the exit code was.
return True
else:
print >> sys.stderr, "Error: KeystoneRegistration.framework not found"
return False
def register_chrome_with_keystone():
"""Registers Chrome with Keystone"""
ksadmin = "/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksadmin"
if os.path.exists(ksadmin):
ksadmin_process = [
ksadmin,
'--register',
'--productid', chrome_product_id(),
'--version', chrome_version(),
'--xcpath', chrome_path,
'--url', chrome_update_url(),
'--tag-path', tag_path,
'--tag-key', tag_key,
'--brand-path', brand_path,
'--brand-key', brand_key,
'--version-path', version_path,
'--version-key', version_key
]
p = subprocess.Popen(ksadmin_process, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(results, error) = p.communicate()
if error:
print >> sys.stderr, "%s" % error
if results:
print results
if p.returncode == 0:
return True
else:
return False
else:
print >> sys.stderr, "Error: %s doesn't exist" % ksadmin
return False
def main(argv=None):
if argv is None:
argv = sys.argv
try:
# Check for root
if os.geteuid() != 0:
print >> sys.stderr, "This script must be run as root"
return 1
if not chrome_installed():
print >> sys.stderr, "Error: Chrome is not installed on this computer"
return 1
if keystone_install():
print "Keystone installed"
else:
print >> sys.stderr, "Error: Keystone install failed"
return 1
if register_chrome_with_keystone():
print "Registered Chrome with Keystone"
return 0
else:
print >> sys.stderr, "Error: Failed to register Chrome with Keystone"
return 1
except Usage, err:
print >> sys.stderr, err.msg
print >> sys.stderr, "for help use --help"
return 2
if __name__ == "__main__":
sys.exit(main())
I also have the following script run at ongoing & login to run any Chrome updates if they are there and auto-updated hasn't taken care of it.
#!/bin/sh
## Script name: run_chrome_updater.sh
## Author: Andy McPherson
## Last modified: 1/31/18
## Logged in user
loggedInUser=$( ls -l /dev/console | awk '{print $3}' )
echo "$loggedInUser"
sudo -u "$loggedInUser" /Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/Resources/GoogleSoftwareUpdateAgent.app/Contents/MacOS/GoogleSoftwareUpdateAgent -runMode oneshot -userInitiated YES 2> /dev/null
exit 0
This has worked super well with 0 failure. We are patched within a few hours of new Chrome releases. Now if we could do the same thing for Firefox I will be super happy!
Posted on 11-05-2019 07:20 AM
@jared_f Thank you very much. It's really weird that it isn't possible to do that natively without a script. I'm also planning on using a script for any new installation of chrome to make sure the user always gets the latest stable release when (re)installing.
I'm still gonna try to figure out a way to keep Chrome updated automatically/user-initiated. I might actually go for the 777 permissions instead of the script if everything else fails.
Posted on 11-05-2019 08:47 AM
There is also a bash version of the python script mentioned above.
https://github.com/ryangball/chrome-enable-autoupdates/blob/master/chrome-enable-autoupdates.sh
Posted on 06-11-2020 02:43 PM
The Chrome for Enterprise Team has published a new kBase on Managing Chrome Browser Updates with Jamf Pro (macOS). This takes advantage of Jamf's Application and Custom Settings Payload and does not rely on a script.
Posted on 06-16-2020 02:15 PM
@jamf_sam What if we do NOT have gsuite running? Step 10 calls out generating a token from gsuite
Posted on 05-19-2021 10:16 AM
@jamf_sam This works great with Chrome Browser. I have tried to do the same with Brave browser. But can not get it to work.
What setting goes here in brave?
Posted on 05-20-2021 09:35 AM
@thch_jamf how do you know which one is a stable version? There are 4 choices 1.0, 1.1, 1.2, and 1.3.
Posted on 01-12-2022 07:55 AM
@akhan_admin I am also curious about the 4 choices. Did you figure out what they were?
Posted on 02-11-2022 07:45 AM
From my understanding the 4 are: Stable, Beta, Dev, and Canary (unstable). The frustrating part is I'm still unable to fine which one is which. It seems crazy to me that in the Google Chrome support doc https://support.google.com/chrome/a/answer/9923111?hl=en they just refer to them by number and not what they actually are. I can't deploy something company wide on a hunch...
Posted on 02-11-2022 01:17 PM
I've continued venturing down this road and I believe the options you eluded to above are in the correct order.
1.0 = Stable
1.1 = Beta
1.2 = Dev
1.3 = Canary
Not 100% on this though.
Posted on 02-11-2022 01:19 PM
Thank you! That's what I assumed it would be but couldn't take the leap without being sure. Where did you find the info? Or was it just by testing? So strange Google would omit that from their support doc.
Posted on 02-11-2022 03:21 PM
Well, like I said, I'm 100% on that. I remember reading or hearing something on it and it eluded to that being the case. I've looked and cannot find the article. If I do, I'll link it here. Sorry if I misled you!
Posted on 02-11-2022 07:38 AM
I would also like to know this...
Posted on 07-25-2022 08:01 AM
Are there any updates regarding the use of a configuration profile to manage Google Chrome behavior regarding updates ? i would like to stay away from scripts if possible and make use of native plist or configuration profiles..
Posted on 07-25-2022 08:44 AM
I found this documentation very useful in our Chrome endeavors. It may or may not have the answer you're looking for, but I believe it covers how to manage Chrome (including updates) via config profiles vs scripts.