Skip to main content
Solved

Install latest version of Google Chrome without re-packaging

  • August 17, 2016
  • 94 replies
  • 752 views

Show first post

94 replies

Forum|alt.badge.img+12
  • Contributor
  • February 10, 2019

I use something @daz_wallace made that uses an EA to scope the update policy, but I can't find the blog.

#!/bin/bash readData() { installedApplicationVersion=$(defaults read /Applications/Google Chrome.app/Contents/Info.plist CFBundleShortVersionString) latestVersion=$(curl -s https://omahaproxy.appspot.com/history | awk -F',' '/mac,stable/{print $3; exit}') } readData if [ "$installedApplicationVersion" != "$latestVersion" ]; then state="Old" else state="Latest" fi echo "<result>$state</result>"

Forum|alt.badge.img+8
  • Contributor
  • February 15, 2019

Any using this python script to enable auto updates for Chrome? Once you run it, no need to keep packaging/updating Chrome, since it does it automatically on the client:

https://github.com/hjuutilainen/adminscripts/blob/master/chrome-enable-autoupdates.py

#!/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:

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 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""" 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())

Forum|alt.badge.img+11
  • Valued Contributor
  • March 1, 2019

i want to do something similar for Google Chat. The one I modified from a chrome download pulled down the chat dmg from google but when I launch the app, it says to check with the developer to make sure it matches the OS. Delete that version then manually download from Google, then drag into the applications folder, then launch and it is happy. After it is happy, I deleted the app and ran my script again. This time it says it cannot verify the developer.

#!/bin/sh

# original script from https://lew.im/2017/03/auto-update-chrome/
# below are my modifications and edits
#this will download the app and move into applications, but when launching the app, gets an error

dmgfile="InstallHangoutsChat.dmg"
volname="Install Hangouts Chat"
logfile="/Library/Logs/GoogleChatInstallScript.log"

# url='https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg'
url='https://dl.google.com/chat/latest/InstallHangoutsChat.dmg'


/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}/Chat.app" "/Applications/Chat.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}"

exit 0

Forum|alt.badge.img+13

.


Forum|alt.badge.img+3
  • New Contributor
  • March 21, 2019

@gldc on your set up what Package and other scripts are you running?


Forum|alt.badge.img+6
  • Contributor
  • May 14, 2019

Thanks, @ellavader . I used your script (with the DownloadURL="$4" modification).

When I first tried it, I got an error about curl not supporting https. I tried it with the Chrome URL you included as parameter 4. Tried it both with and without quotes (in the parameter field), and neither worked.

What did work was using single quotes, like so: 'https://dl.google.com/chrome/mac/stable/googlechrome.dmg'

I mention this in case anyone else runs into that problem.


Forum|alt.badge.img+4
  • Contributor
  • May 21, 2019

As a small addition, I had to modify a line in ellie's script for OS X 10.14 (not sure if it affects other versions as well):

cp -pPR /tmp/jamf/mount/*.app /Applications || :

needs to be

cp -a /tmp/jamf/mount/*.app /Applications || :

Otherwise it messes up the permissions of existing Chrome installations.
Thanks for the awesome contribution!


Forum|alt.badge.img
  • New Contributor
  • May 29, 2019

@swhps I was running into similar issues as you, but finally determined the issue was how the Chat app was being copied to the Applications folder. I wasn't having any luck with ditto, but was finally able to open Chat when using cp. Additionally, I modified the curl request to handle the URL redirect.

#!/bin/sh

# original script from https://lew.im/2017/03/auto-update-chrome/
# below are my modifications and edits
#this will download the app and move into applications, but when launching the app, gets an error

dmgfile="InstallHangoutsChat.dmg"
volname="Install Hangouts Chat"
logfile="/Library/Logs/GoogleChatInstallScript.log"

# url='https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg'
url='https://dl.google.com/chat/latest/InstallHangoutsChat.dmg'


/bin/echo "--" >> ${logfile}
/bin/echo "`date`: Downloading latest version." >> ${logfile}
/usr/bin/curl -L ${url} > /tmp/${dmgfile}
/bin/echo "`date`: Mounting installer disk image." >> ${logfile}
/usr/bin/hdiutil attach /tmp/${dmgfile} -nobrowse -quiet
/bin/echo "`date`: Installing..." >> ${logfile}
cp -r "/Volumes/${volname}/Chat.app" "/Applications"
/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}"

exit 0

Forum|alt.badge.img+2
  • New Contributor
  • May 30, 2019

Thanks for sharing this script! Has anyone run into an issue where Chrome can't update when deployed this way? What is a proposed workaround? I assume it might have something to do with user permissions / rights from when it was installed. Thanks!


Forum|alt.badge.img+6
  • Contributor
  • May 30, 2019

@cornwella : Do the permissions problem you fixed prevent Chrome from updating itself?

If so, then @pds.jamfadmin needs to make the change you recommended.


Forum|alt.badge.img+31
  • Honored Contributor
  • June 2, 2019

you can deploy Chrome once and use a configuration profile to force auto updates. Also, curl scripts as root on all your endpoints is a security risk, FYI


Forum|alt.badge.img+18
  • Author
  • Valued Contributor
  • September 9, 2019

@tlarkin As long as curl is using https, then a MITM attack becomes less of a concern. However, if Google were hacked and a bad copy of Chrome were sneaked in, then there would be a problem - a BIGGER problem. Anyway, just a point to consider. YMMV... ¯_(ツ)_/¯


Forum|alt.badge.img+31
  • Honored Contributor
  • September 10, 2019

@caine.horr only if the cert is pinned, which isn't every CDN or host is. That is the only the time MITM is not gonna work. Your results will vary.


Forum|alt.badge.img+2
  • New Contributor
  • September 19, 2019

first off, there is some great info in this post, thanks to everyone who has contributed. has anyone tried using this script to deploy chrome update on a machine where an older version of chrome is currently open/running? when i try to do so, the update goes through successfully, but then when i exit out of the running instance of chrome, i can't seem to reopen chrome at all until a reboot. if i try to run the app before rebooting, the chrome icon just bounces up and down on the dock but nothing launches. once i reboot, i am able to open chrome and it gives message that it closed unexpectedly last time, but it is on the new version and works fine. wondering if this is possible at all to deploy while chrome is running or if we will need to ensure users close out of the app first before deploying.


Forum|alt.badge.img+31
  • Honored Contributor
  • September 19, 2019

@dancunn typically you can install apps over running apps and it will mostly work, but there is always a risk of failure. So, to be safe, you should attempt to quit the app first. I have a script that will quit and run a policy to patch an app using NSRunningApplication and bundle IDs, found here.

Hopefully this helps


Forum|alt.badge.img+6
  • Contributor
  • September 20, 2019

Today I'm revisiting @ellavader 's excellent script. I'm still a huge fan, but…

Today I was troubleshooting some Jamf stuff, and so I was manually invoking a policy that included this script. (using a custom trigger)

And in so doing, was able to "watch" it execute, and noticed this:

installer: Error - the package path specified was invalid: '/tmp/jamf/mount/*.pkg'.

Okay, so the attempt to install as a pkg failed because it wasn't a pkg. Should we care?

We could edit the script to check if the DownloadURL ends with .pkg, or .dmg, or .zip, and only attempt to execute the relevant code.

I'm not a pedant, and I don't want to waste time hiding error messages that no one will see, if it doesn't affect the results.

So, does it matter? Or is worrying about it a waste of time?


Forum|alt.badge.img+5

Hello all. I have been happily using the script by @cainehorr It has been working great. However it seems the link for the download no longer works. Does anyone have an updated link to continue using this scipt?


Forum|alt.badge.img+15
  • Esteemed Contributor
  • October 25, 2019

You're using https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg? It works fine for me. What happens if you access it in a browser? Are you getting a valid cert?


Forum|alt.badge.img+5

I had an older link which no longer exists. I updated the link and all is well... Thank you! @cbrewer


Forum|alt.badge.img+10
  • Valued Contributor
  • October 26, 2019

We have this script that goes out once a month and checks the current version to the latest google version. It just went out and started the update to version 78.xxxx. Worked great for us.

!/bin/sh

dmgfile="googlechrome.dmg"
volname="Google Chrome"
logfile="/Library/Logs/GoogleChromeInstallScript.log"

url='https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg'

/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}"

exit 0


Forum|alt.badge.img+7
  • Contributor
  • January 17, 2020

Hello. My organization is using this script too (v1.1 at the top of the thread.) But I'm having to reevaluate this because it installs on our MacBooks with auto updates broken. Is anyone having this issue too?

My preference is finding a solution where Chrome is installed with auto updates turned on. Can anyone assist with this?


MrRoboto
Forum|alt.badge.img+9
  • Valued Contributor
  • January 17, 2020

We are using a single policy with the following 2 scripts to install the latest version of Chrome, and configure automatic updates...

Install:

#!/bin/sh

dmgfile="googlechrome.dmg"
volname="Google Chrome"
logfile="/Library/Logs/GoogleChromeInstallScript.log"

url='https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg'


/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}"

exit 0

Updates:
https://github.com/ryangball/chrome-enable-autoupdates/blob/master/chrome-enable-autoupdates.sh


Forum|alt.badge.img+7
  • Contributor
  • January 17, 2020

MrRoboto, your script on Github totally worked for me. Automatic updates in Chrome are working. Thanks a million.


Forum|alt.badge.img+12
  • Valued Contributor
  • January 17, 2020

When i run the Github script i get the following, am i doing something wrong?
Keystone installed
AutoUpdateChrome.sh: line 51: /Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksadmin: No such file or directory
Error: Failed to register Chrome with Keystone - code 0


MrRoboto
Forum|alt.badge.img+9
  • Valued Contributor
  • January 17, 2020

@ralvarezOES That's good to hear. It's not my script, created by @ryan.ball

@Dylan_YYC What version of Chrome are you testing? The script only works for 75+