How to update Chrome automatically

LewisLebentz
New Contributor II

I have just written a blog post on how to automatically update Google Chrome using Jamf if anyone is interested. You can find my blog post here:

https://lew.im/2017/03/auto-update-chrome/

I have seen a few different methods posted here, but most require some admin intervention (uploading new packages, changing version numbers etc.) but this method is fully automated. Create the Extension Attribute, Smart Group and Policy and you're good to go! Every time Google release a new version of Chrome, this script will automatically grab it and install it on your Macs.

132 REPLIES 132

bpavlov
Honored Contributor

I haven't implemented this, but just reading through the script, it looks like you are literally overwriting the Google Chrome.app on the client already. In my experience having done this with a package in the past, this has the effect of causing issues when new tabs are opened and not being able to navigate to new websites. So in essence if you want to do this, you need to make sure Google Chrome is not opened otherwise the user may run into that issue. Again, I haven't tested your workflow so I'm going off what I'm reading in that script. Curious to hear how long you've been using this workflow and what your experience has been from the end-user side.

LewisLebentz
New Contributor II

We have been using this method (less the automated version part) for around a year now, and haven't had any issues. With a few hundred Macs reporting in, I'd probably have heard a complaint or two if it was causing issues with new tabs!

I tested it when we initially deployed it and all seemed fine, but Chrome has changed a lot since then, so I'll do some further testing when I'm back in the office and will update you.

LewisLebentz
New Contributor II

@bpavlov just did some further testing, ran the script a few times deleting Chrome whilst using it, open new tabs, browsing etc. and didn't notice anything whatsoever.

So can confirm there is still no noticeable effect for the end user if you run this.

RobertBasil
Contributor

Saw your post on Reddit about this script. Going to install it today and give it a run.

Thanks for sharing.

mm2270
Legendary Contributor III

@LewisLebentz Thanks for your post, and showing your work. If nothing else, you pointed me to a resource I was previously unaware of. I'm not sure who developed or maintains the omahaproxy pages, but I looked it up to see more on it. It doesn't appear to be something Google maintains, but I'm not completely sure on that.

In any event, I've been looking for a more reliable way to get the Google Chrome current release number, since it seems Google obscurs it to the point of being impossible to get. I also have an "update" script that can update several products on the fly, doing live version checking, and incorporating Google Chrome into it has been a bear, because it was such a moving target to locate the latest version.

I found the team at omahaproxy have a simple plain csv file they host as well and was able to come up with the following very simple bash code to pull the current Mac version release from that. Posting it here so others can benefit.

curl -s https://omahaproxy.appspot.com/history | awk -F',' '/mac,stable/{print $3; exit}'

The above prints

56.0.2924.87

which is the current version. I'll need to see if that still works when they release an update.
Hopefully those pages won't up and disappear someday, or go stale from lack of maintenance.

mm2270
Legendary Contributor III

LOL! No sooner did I post the above and Google released an update. Didn't need to wait long! The code above (and I assume your python EA as well) is working to show the new version, 57.0.2987.98, which means those pages get updated simultaneously along with new releases. Wow! Impressive!

ac8f0909203c450f9bbaed79ae177c14

LewisLebentz
New Contributor II

@mm2270 just noticed the update too! Most of my Macs have already picked up the update because of the script, which is great!

I believe the OmahaProxy site is officially Google, I've seen it referred to in a few different places by Google. So I think it's safe to rely on, it's been around for a while too.

Just found some code that references it on Google's site: https://chromium.googlesource.com/chromium/chromium/+/trunk/tools/omahaproxy.py

Script is pretty similar to mine!

Thanks for sharing your code too. Much shorter than mine! Need to learn how to use awk at some point.

I did notice that Jamf haven't yet updated their patch reporting, so our pie chart is all red saying that the version number is 'Other' and in the list it reports it as 'Unknown' which isn't great.

cbrewer
Valued Contributor II

Why use this work flow over Google's own system wide automatic updater? Especially when it can be enabled with a script.

LewisLebentz
New Contributor II

@cbrewer ours users are all admins, so can override settings we push out. Even if they don't they may not restart Chrome.

This script forces an update on check in, without the user even noticing. It runs in the background, and doesn't require a restart of Chrome.

rayabril
New Contributor

So with @mm2270 new script, what should final Extension Attribute code look like? Sorry i'm new to this and pretty green when it comes to coding.

bpavlov
Honored Contributor

@cbrewer what's the script you're referring to use the internal update tool from Google?

cdenoia
New Contributor

Hey @LewisLebentz

Excellent post!

May
Contributor III

Thanks ! @LewisLebentz @mm2270

What a time saver! i've seen no issues using it whilst Chrome is open,
it will also install the latest Chrome if it's not installed, here's the EA i'm using to report,

#!/bin/sh

if [ ! -f "/Applications/Google Chrome.app/Contents/Info.plist" ] ; then
echo "<result>Chrome isn't installed</result>"
exit 0
fi

INSTALLEDVERSION=$( defaults read "/Applications/Google Chrome.app/Contents/Info.plist" CFBundleShortVersionString )
CURRENTVERSION=$( curl -s https://omahaproxy.appspot.com/history | awk -F',' '/mac,stable/{print $3; exit}' )

if [[ "$INSTALLEDVERSION" == "$CURRENTVERSION" ]]; then

echo "<result>latest - $CURRENTVERSION</result>"

else

echo "<result>old</result>"

fi

Kyuubi
Contributor

@mm2270 @LewisLebentz pardon my ignorance but I would love to get this working at my site. I saw the curl command that @mm2270 put above and i saw it incorporated into the EA that @May wrote. What I don't understand is how that curl command pulls down the latest version and installs it. What am I missing.

Thanks,

mm2270
Legendary Contributor III

@Kyuubi The script above from @May is an Extension Attribute, not the script that updates Chrome. The EA is part of the whole workflow put together by @LewisLebentz in his original post up top. You would use an EA similar, or identical to the one May posted above to gather Macs that are out of date according to what is noted on the omahaproxy pages for the latest Chrome version. This can then be used to gather out of date Macs in a Smart Group, which can in turn be scoped to the policy that would update them. Refer to Lewis' OP at top for his script that updates Chrome. There are others posted on the forums here as well. Essentially any script that would pull Google Chrome down, mount the DMG, copy over the app (overwriting the old one) and so on and so forth.

Hope that helps.

Kyuubi
Contributor

@mm2270 Thanks for the response. I understand all you wrote above, I'm just having trouble finding the actual script that does the pulling and installing. I've checked @LewisLebentz blog and github pages but can't find the script. Making me feel stupid.

Kyuubi
Contributor

.......found it

mm2270
Legendary Contributor III

@Kyuubi OK, good! Was just about to post a more direct link to the script if I could for you. :)

ryan_ball
Valued Contributor

I actually incorporate the chrome_enable_autoupdates.py as a postinstall in my AutoPKG Chrome recipe now and this seems to be working well.

tld75000
New Contributor II

@LewisLebentz Not working for me, maybe missing a step or something. When Lewis says " I made a Smart Group targeting all Macs where Chrome Version = Old" how does that translate into the Smart Group, how do you create it.
Thanks

JeffA
New Contributor II

@LewisLebentz Any update on creating the Smart Group? This would be great to implement but I am in the position as @tld75000. How do you create a Smart Group with the Criteria of "Chrome = Old"? Any help would be appreciated. Thanks.

tep
Contributor II

@JeffA you can do a smart group with the criteria "Chrome like old"

Not applicable

The windows pop up message when the new version of chrome launch. I don't think so you need to go for automatic chrome update.

WellsJtech
New Contributor III

@JeffA You've probably figured this out already. For anyone who creates the Extension Attribute, you would create a Smart Group and there will be a "New Criteria" with whatever you named the EA. For example, I named mine Chrome Version, so I have a new criteria option called Chrome Version, then I just use the value is "old". 3933f989940140a1ac40a2642acdab14

rhooper
Contributor III

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.

merps
Contributor III

@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.

rhooper
Contributor III

@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!

vvujcic
New Contributor

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!

josh_perlman
New Contributor

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

brunerd
Contributor

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!

G_M_
New Contributor III

@brunerd Your script worked well for me!! Greatly appreciated!!

thomH
New Contributor III

@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.

chris_kemp
Contributor III

@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"...

larry_barrett
Valued Contributor

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.

msw
Contributor

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"
c1bcace62b0740f59c97384180acddc7
70e9f873831c47c4b57b346130aa77cc

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?

psliequ
Contributor III

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.

msw
Contributor

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.

ekrizon
New Contributor II

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.