I still cannot get the Chrome Version Smart group to post any devices.
Added the EA script. and then created the smart group with Version = Old. Still nothing there after 1 hr.
Any help or direction is appreciated.
The actual Chrome updater script works awesome! Thank you.
@rhooper EAs update when device inventory updates - during a jamf recon. From what I understand, most environments will run recon daily or once a week.
I'd take a system, do a manual recon, and then check the computer record in the category you used for the EA. This will help you verify whether the EA is working for you. You also may need to use a lowercase "o" in Version = old.
@merps OH yeay, the ol' Recon weekly thing.
Thanks for the reminder.
I wonder, can I use a recon policy to push and receive more devices? so far only 2 show.....
Problems logging into JAMF Pro right now... errors galore!
This great @LewisLebentz . Thanks for sharing! I added an extra if/else in the original EA script to also detect/output if Chrome is not installed all together similar to @May
#!/usr/bin/python
import json
import urllib2
import os.path
import plistlib
url = 'http://omahaproxy.appspot.com/all.json'
resp = urllib2.urlopen(url)
data = json.loads(resp.read())
for each in data:
if each.get("os") == "mac":
versions = each.get("versions")
for version in versions:
if version.get("channel") == "stable":
latest = (version.get("current_version"))
print latest
chromeExists = os.path.exists("/Applications/Google Chrome.app")
print chromeExists
if chromeExists:
plistloc = "/Applications/Google Chrome.app/Contents/Info.plist"
pl = plistlib.readPlist(plistloc)
pver = pl["CFBundleShortVersionString"]
print pver
if latest == pver:
print "<result>Latest</result>"
else:
print "<result>Old</result>"
else:
print "<result>NotInstalled</result>"
Fairly new to python and JAMF so any criticisms are more than welcome. Thanks!
Thanks for this info @LewisLebentz! One thing I minor edge case that could be a security problem is your script installs /Volumes/Google Chrome/Google Chrome.app regardless of if that path already exists or not.
I added the following prior to the rest of your install script:
if [ -d "/Volumes/Google Chrome" ]; then
/bin/echo "`date`: Chrome image already mounted" >> ${logfile}
exit 1
fi
Since updating Chrome is in the news these days, making sure AutoUpdates are on brought me here...
Google's Manage Chrome updates (Mac) page totally underplays what's needed saying you just need to set a key:
We recommend that you keep auto-updates turned on so your users receive critical security fixes and new features as they become available.
Open the com.google.Keystone.plist file in your preferred XML editor.
Under the updatePolicies key, add the Chrome Browser UpdateDefault key entry, and set the key value to 0. The following example shows settings for Chrome Browser (com.google.Chrome) that turns on auto-updates:
<key>updatePolicies</key>
<dict>
<key>global</key>
<dict>
<key>UpdateDefault</key>
<integer>0</integer>
</dict>
</dict>
Save your changes.
Which is annoying for two reasons: 1) It's assuming you have the Keystone daemon running and 2) Their snippet leads to authoring errors, in some other thread it's in a plist but not properly formatted, you have to have the whole thing enclosed in a dictionary like so...
<?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>updatePolicies</key>
<dict>
<key>global</key>
<dict>
<key>UpdateDefault</key>
<integer>0</integer>
</dict>
</dict>
</dict>
</plist>
Which is still useless from my testing, even if this plist is deployed to the domain com.google.Keystone as a Config Profile, and you make sure Google Software Updates is installed it will STILL ask the end user to enable updates... and auth as an admin.
I took the Python script found in this thread: Auto update Google Chrome script? and BASH-ified it, streamlined it taking out keyname variables and such and added in a couple script that get run when the button is manually clicked in Chrome and I have this:
#!/bin/sh
#Joel Bruner
#specify a custom path in parameter $4 or just take the default
appPath="${4:-/Applications/Google Chrome.app}"
#no exist? exit.
[ ! -e "${appPath}/Contents/Info.plist" ] && exit
appVersion=$(defaults read "${appPath}/Contents/Info.plist" CFBundleShortVersionString)
updateURL=$(defaults read "${appPath}/Contents/Info.plist" KSUpdateURL)
productID=$(defaults read "${appPath}/Contents/Info.plist" KSProductID)
"${appPath}/Contents/Versions/${appVersion}/Google Chrome Framework.framework/Versions/A/Resources/keystone_promote_preflight.sh" 2>/dev/null 1>&2
"${appPath}/Contents/Versions/${appVersion}/Google Chrome Framework.framework/Frameworks/KeystoneRegistration.framework/Resources/ksinstall" --install "${appPath}/Contents/Versions/${appVersion}/Google Chrome Framework.framework/Frameworks/KeystoneRegistration.framework/Resources/Keystone.tbz" --force
/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksadmin --register --productid "${productID}" --version "${appVersion}" --xcpath "${appPath}" --url "${updateURL}" --tag-path "${appPath}/Contents/Info.plist" --tag-key "KSChannelID" --brand-path "/Library/Google/Google Chrome Brand.plist" --brand-key "KSBrandID" --version-path "${appPath}/Contents/Info.plist" --version-key "KSVersion"
"${appPath}/Contents/Versions/${appVersion}/Google Chrome Framework.framework/Versions/A/Resources/keystone_promote_postflight.sh" "${appPath}" 2>/dev/null 1>&2
Use it in good health!
@brunerd Your script worked well for me!! Greatly appreciated!!
@LewisLebentz Instead of creating the EA, couldn't you have your smart groups (one for up to date and another for out of date) use Criteria: patch reporting, Google Chrome.
@piagetblix I was just looking at this today, but unfortunately the "Latest Version" seems unreliable - Patch Reporting says that 80% of our fleet is on the current version, but Smart Groups flagged more than this as "Is not" "Latest Version"...
Keep in mind there needs to be a recon before everything is accurate. Once all the devices check in you'll have a clearer picture. If you do not have todays inventory you don't have the full picture.
I've been using the python script @brunerd linked for years to enable auto-updates after installing the latest version of Chrome during imaging. It's been working flawlessly for ages. I was just testing something unrelated this morning and saw that when I launched Chrome on a freshly-imaged device, I got the 'Google Chrome may not be able to keep itself updated' banner. Likewise if I go to Settings > About, I get a warning "Google Chrome may not be able to keep itself updated"


I found this thread on the topic. The relevant portion from @gzilla13 is here:
The problem has to do with GoogleSoftrwareUpdate. In newer versions of Google Chrome, GoogleSoftwareUpdate is not downloaded until Chrome has been launched once. On first launch, Chrome will install GoogleSoftwareUpdate in the current user's Library. This causes the prompt if the app is not owned by that user. Changing ownership of Google Chrome to the user will only fix the problem for that user. If anyone else logs in, the prompt will appear again.
When you click "Set up automatic updates" from that prompt. The system will move GoogleSoftwareUpdate to the /Library/Google folder and remove it from the current user's Library, it will also update and create all relevant LaunchAgents and Daemons to point to GoogleSoftwareUpdate in /Library/Google.
He later says in the same thread that the Auto Update python script solved the problem for him but I'm still having it. Just in case, I tried brunerd's script since I'm more familiar with bash, and still have the same issue. There appear to be two problems:
- there's no /Applications/Google Chrome.app/Contents/Versions folder (Chrome version 75.0.3770.80)
- Because the Version folder isn't there, the keystone scripts aren't present, and (maybe as a result) there isn't a /Library/Google folder, just a ~/Library/Google folder
Can't quite figure out what's broken here. Anyone else running into similar issues?
I've always had very good success packaging Chrome and its auto update components.
Packaging;
/Applications/Google Chrome.app
/Library/Google/
/Library/LaunchDaemons/com.google.keystone.daemon.plist
/Library/LaunchAgents/com.google.keystone.agent.plist
/Library/LaunchAgents/com.google.keystone.xpcservice.plist
does the trick.
You could add a post install script to load the daemons and agents in the current session or just wait for the next reboot for them to be loaded.
I'm installing Chrome with a script like this:
#!/bin/sh
echo "Installing the current stable version of Google Chrome..."
echo "Downloading..."
curl -k --silent --retry 3 --retry-max-time 6 --fail https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg --output /googlechrome.dmg
echo "Mounting DMG..."
hdiutil attach -quiet -nobrowse /googlechrome.dmg -mountpoint /Volumes/GC/
echo "Installing..."
cp -r /Volumes/GC/Google Chrome.app/ /Applications/Google Chrome.app/
echo "Cleaning up..."
hdiutil detach /Volumes/GC/
rm -rf /googlechrome.dmg
chrome_version=`defaults read /Applications/Google Chrome.app/Contents/Info CFBundleShortVersionString`
echo "Chrome $chrome_version installed..."
A computer I imaged about a week ago with Chrome 74.0.3729.169 installed with auto-updates enabled, and no user gets the 'enable automatic updates?' prompt on first launch. In /Applications/Google Chrome.app/Contents/, the expected Versions folder is there.
Today, I am getting Chrome 75.0.3770.80, and there isn't a Versions folder in the app bundle, so none of keystone/auto-update scripts are present. Did Google change something about the app architecture? Just to confirm I wasn't losing my mind, I re-downloaded the dmg from https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg and from https://www.google.com/chrome/ — in both cases, the .app bundle in the dmg doesn't contain /Contents/Versions.
So...I guess I've identified the problem but I have no idea what to do about it.
I'm in the same boat, we use the install latest version script and the enable auto-updates.py and am seeing the same issue.
@msw-sa and @ekrizon I have a PR in with hjuutilainen that will fix it.
See my fork here:
https://github.com/ryangball/adminscripts/blob/master/chrome-enable-autoupdates.py
I would only use mine temporarily, as he might merge my changes into his.
Okay my changes are merged into the original and I've deleted my fork, so the updated script that will work for versions above and below Chrome 75 is here:
https://github.com/hjuutilainen/adminscripts/blob/master/chrome-enable-autoupdates.py
huge thanks @ryan.ball — much appreciated! i've confirmed this script works in my environment.
Hello Jamf Nation,
I am getting the following Error when Google try's to update:
Script result: /Library/Application Support/JAMF/tmp/Update Google Chrome: line 15: /Applications/Google Chrome.app/Contents/Versions/75.0.3770.80/Google Chrome Framework.framework/Frameworks/KeystoneRegistration.framework/Resources/ksinstall: No such file or directory
Does anyone know if Google has changed anything on there end?
#!/bin/sh
#specify a custom path in parameter $4 or just take the default
appPath="${4:-/Applications/Google Chrome.app}"
#no exist? exit.
[ ! -e "${appPath}/Contents/Info.plist" ] && exit
appVersion=$(defaults read "${appPath}/Contents/Info.plist" CFBundleShortVersionString)
updateURL=$(defaults read "${appPath}/Contents/Info.plist" KSUpdateURL)
productID=$(defaults read "${appPath}/Contents/Info.plist" KSProductID)
"${appPath}/Contents/Versions/${appVersion}/Google Chrome Framework.framework/Versions/A/Resources/keystone_promote_preflight.sh" 2>/dev/null 1>&2
"${appPath}/Contents/Versions/${appVersion}/Google Chrome Framework.framework/Frameworks/KeystoneRegistration.framework/Resources/ksinstall" --install "${appPath}/Contents/Versions/${appVersion}/Google Chrome Framework.framework/Frameworks/KeystoneRegistration.framework/Resources/Keystone.tbz" --force
/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksadmin --register --productid "${productID}" --version "${appVersion}" --xcpath "${appPath}" --url "${updateURL}" --tag-path "${appPath}/Contents/Info.plist" --tag-key "KSChannelID" --brand-path "/Library/Google/Google Chrome Brand.plist" --brand-key "KSBrandID" --version-path "${appPath}/Contents/Info.plist" --version-key "KSVersion"
"${appPath}/Contents/Versions/${appVersion}/Google Chrome Framework.framework/Versions/A/Resources/keystone_promote_postflight.sh" "${appPath}" 2>/dev/null 1>&2
This was working and updating Google flawlessly till today.
@CorpIT_eB It does appear Google has borked something with version 75.0.3770.80. The script is using the version number in the path to call ksinstall, but on my Mac if I look in /Applications/Google Chrome/Contents/Versions/
there is no directory named 75.0.3770.80, just one named 74.0.3729.169.
@sdagley Lovely!
Let't see how else I can fix this now, with Catalina around the corner I don't want to start adding Python scripts in the mix.
Keep in mind I install using another policy with this:
dmgfile="googlechrome.dmg"
volname="Google Chrome"
logfile="/Library/Logs/GoogleChromeInstallScript.log"
url='https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg'
# Are we running on Intel?
if [ '`/usr/bin/uname -p`'="i386" -o '`/usr/bin/uname -p`'="x86_64" ]; then
/bin/echo "--" >> ${logfile}
/bin/echo "`date`: Downloading latest version." >> ${logfile}
/usr/bin/curl -s -o /tmp/${dmgfile} ${url}
/bin/echo "`date`: Mounting installer disk image." >> ${logfile}
/usr/bin/hdiutil attach /tmp/${dmgfile} -nobrowse -quiet
/bin/echo "`date`: Installing..." >> ${logfile}
ditto -rsrc "/Volumes/${volname}/Google Chrome.app" "/Applications/Google Chrome.app"
/bin/sleep 10
/bin/echo "`date`: Unmounting installer disk image." >> ${logfile}
/usr/bin/hdiutil detach $(/bin/df | /usr/bin/grep "${volname}" | awk '{print $1}') -quiet
/bin/sleep 10
/bin/echo "`date`: Deleting disk image." >> ${logfile}
/bin/rm /tmp/"${dmgfile}"
else
/bin/echo "`date`: ERROR: This script is for Intel Macs only." >> ${logfile}
fi
exit 0
@CorpIT_eB all of the items that were in Google Chrome.app/Contents/Versions have been moved and the Versions folder is gone starting with version 75.
Let this section of the python script be your guide
def keystone_registration_framework_path():
"""Returns KeystoneRegistration.framework path"""
if LooseVersion(chrome_version()) >= LooseVersion("75"):
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
The python version is nice, because it has loose version comparison, but you can easily compare versions with bash too. Do a defaults read to get the chrome major version from info.plist, and if 75+, use the path with the /Versions folder, if 74 or below, use the /Frameworks path.
It's Friday afternoon so don't feel like bashing this out myself, but I might do next week. Also, if you don't care about the script to enable auto-updates working on older versions of Chrome than the current one, you don't even need to add version logic, you can just use the Frameworks path instead of the Versions path.
@msw-sa Just read your post, from yesterday. I might bother you again next week then. I want it to auto update for sure the first time so I don't have to relive updating it again, and trying to really move away from Python in light of Catalina. (Trying to future proof)
So if you wouldn't mind next week I can totally use the Assist. And I appreciate you in advance!
Thanks
@CorpIT_eB I took @msw-sa's explanation of the changes and updated @brunerd's script to accommodate Chrome 75 (here's hoping they don't change back):
#!/bin/bash
#Joel Bruner
#Updated by @sdagley for Chrome 75 changes based on comments by @msw-sa
appPath="${4:-/Applications/Google Chrome.app}"
#no exist? exit.
[ ! -e "${appPath}/Contents/Info.plist" ] && exit
appVersion=$(defaults read "${appPath}/Contents/Info.plist" CFBundleShortVersionString)
majorVersion=$(echo "$appVersion" | awk -F. '{ print $1; }')
if [[ $majorVersion -ge 75 ]] ; then
# Framework will be in ../Content/Frameworks
frameWorkPath="${appPath}/Contents/Frameworks/Google Chrome Framework.framework/Versions/${appVersion}/Frameworks/KeystoneRegistration.framework"
else
# Framework will be in ../Contents/Versions
frameWorkPath="${appPath}/Contents/Versions/${appVersion}/Google Chrome Framework.framework/Frameworks/KeystoneRegistration.framework"
fi
updateURL=$(defaults read "${appPath}/Contents/Info.plist" KSUpdateURL)
productID=$(defaults read "${appPath}/Contents/Info.plist" KSProductID)
"${frameWorkPath}/Versions/A/Resources/keystone_promote_preflight.sh" 2>/dev/null 1>&2
"${frameWorkPath}/Resources/ksinstall" --install "${frameWorkPath}/Resources/Keystone.tbz" --force
/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksadmin --register --productid "${productID}" --version "${appVersion}" --xcpath "${appPath}" --url "${updateURL}" --tag-path "${appPath}/Contents/Info.plist" --tag-key "KSChannelID" --brand-path "/Library/Google/Google Chrome Brand.plist" --brand-key "KSBrandID" --version-path "${appPath}/Contents/Info.plist" --version-key "KSVersion"
"${frameWorkPath}/Versions/A/Resources/keystone_promote_postflight.sh" "${appPath}" 2>/dev/null 1>&2
@sdagley You're awesome!
I will give this a try and see how it works.
Thanks Again.
@sdagley I got a 127.
Script exit code: 127
Script result: 2019-06-10 08:58:49.469 ksinstall[39014/0x11c7685c0] [lvl=3] -[KeystoneInstallBackend runImpersonatedLaunchControlWithCommand:asUser:inProcess:] Error impersonating 327506609/96 and running command stop com.google.keystone.user.agent: return code 3 (3: No such process).
Standard output:
Standard error:
2019-06-10 08:58:49.477 ksinstall[39014/0x11c7685c0] [lvl=3] -[KeystoneInstallBackend runImpersonatedLaunchControlWithCommand:asUser:inProcess:] Error impersonating 327506609/96 and running command stop com.google.keystone.user.xpcservice: return code 3 (3: No such process).
Standard output:
Standard error:
Error running script: return code was 127.