From 9e2fa6567076931c46c05bf06842a5c0d2899c79 Mon Sep 17 00:00:00 2001 From: Raptor399 Date: Tue, 12 Oct 2021 12:14:29 +0200 Subject: [PATCH 01/76] Added option to not interrupt Do Not Disturb full screen apps like KeyNote or Zoom --- CHANGELOG.md | 1 + fragments/functions.sh | 26 ++++++++++++++++++++++++++ fragments/header.sh | 10 ++++++++++ fragments/main.sh | 7 +++++++ 4 files changed, 44 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74d7b8f..f50b40c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Added bunch of new labels, and improved others. - Renamed `buildCaseStatement.sh` to `buildLabel.sh` and improved it a lot. It is a great start when figuring out how to create a new label for an app, or a piece of software. Look at the tutorials in our wiki. - Mosyle changed their app name from Business to Self-Service +- Added option to not interrupt Do Not Disturb full screen apps like KeyNote or Zoom with `INTERRUPT_DND="no"`. ## v0.6 - 2021-07-14 diff --git a/fragments/functions.sh b/fragments/functions.sh index ebf6e58..7725e80 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -616,4 +616,30 @@ finishing() { fi } +# Detect if there is an app actively making a display sleep assertion, e.g. +# KeyNote, PowerPoint, Zoom, or Webex. +# See: https://developer.apple.com/documentation/iokit/iopmlib_h/iopmassertiontypes +hasDisplaySleepAssertion() { + # Get the names of all apps with active display sleep assertions + local apps="$(/usr/bin/pmset -g assertions | /usr/bin/awk '/NoDisplaySleepAssertion | PreventUserIdleDisplaySleep/ && match($0,/\(.+\)/) && ! /coreaudiod/ {gsub(/^.*\(/,"",$0); gsub(/\).*$/,"",$0); print};')" + + if [[ ! "${apps}" ]]; then + # No display sleep assertions detected + return 1 + fi + + # Create an array of apps that need to be ignored + local ignore_array=("${(@s/,/)IGNORE_DND_APPS}") + + for app in ${(f)apps}; do + if (( ! ${ignore_array[(Ie)${app}]} )); then + # Relevant app with display sleep assertion detected + printlog "Display sleep assertion detected by ${app}." + return 0 + fi + done + + # No relevant display sleep assertion detected + return 1 +} diff --git a/fragments/header.sh b/fragments/header.sh index a845b98..0ede4db 100644 --- a/fragments/header.sh +++ b/fragments/header.sh @@ -102,6 +102,16 @@ REOPEN="yes" # - no App not reopened +# Interrupt Do Not Disturb (DND) full screen apps +INTERRUPT_DND="yes" +# options: +# - yes Script will run without checking for DND full screen apps. +# - no Script will exit when an active DND full screen app is detected. + +# Comma separated list of app names to ignore when evaluating DND +IGNORE_DND_APPS="firefox,Google Chrome,Safari,Microsoft Edge,Opera,Amphetamine,caffeinate" + + # NOTE: How labels work # Each workflow label needs to be listed in the case statement below. diff --git a/fragments/main.sh b/fragments/main.sh index dfba2c9..2127145 100644 --- a/fragments/main.sh +++ b/fragments/main.sh @@ -8,6 +8,13 @@ esac # MARK: application download and installation starts here +if [[ ${INTERRUPT_DND} = "no" ]]; then + # Check if a fullscreen app is active + if hasDisplaySleepAssertion; then + cleanupAndExit 1 "active display sleep assertion detected, aborting" + fi +fi + printlog "BLOCKING_PROCESS_ACTION=${BLOCKING_PROCESS_ACTION}" printlog "NOTIFY=${NOTIFY}" From cfdb884818134d7003f32dfdc8005d78b37b5d63 Mon Sep 17 00:00:00 2001 From: Raptor399 Date: Mon, 18 Oct 2021 16:12:44 +0200 Subject: [PATCH 02/76] Setting no default IGNORE_DND_APPS with example in comments. As per the discussion in the pull request. --- fragments/header.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fragments/header.sh b/fragments/header.sh index 0ede4db..43ebb7a 100644 --- a/fragments/header.sh +++ b/fragments/header.sh @@ -109,7 +109,9 @@ INTERRUPT_DND="yes" # - no Script will exit when an active DND full screen app is detected. # Comma separated list of app names to ignore when evaluating DND -IGNORE_DND_APPS="firefox,Google Chrome,Safari,Microsoft Edge,Opera,Amphetamine,caffeinate" +IGNORE_DND_APPS="" +# example that will ignore browsers when evaluating DND: +# IGNORE_DND_APPS="firefox,Google Chrome,Safari,Microsoft Edge,Opera,Amphetamine,caffeinate" # NOTE: How labels work From cf42f1f8b7d5263deabcc0e4810b83ae2867967b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Thu, 25 Nov 2021 12:50:36 +0100 Subject: [PATCH 03/76] Moved change to top of the list --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f50b40c..8db070c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +- Added option to not interrupt Do Not Disturb full screen apps like Keynote or Zoom with `INTERRUPT_DND="no"`. + ## v0.7 - pre-release - default for `BLOCKING_PROCESS_ACTION`is now `BLOCKING_PROCESS_ACTION=tell_user` and not `prompt_user`. It will demand the user to quit the app to get it updated, and not present any option to skip it. In considering various use cases in different MDM solutions this is the best option going forward. Users usually choose to update, and is most often not bothered much with this information. If it's absoultely a bad time, then they can move the dialog box to the side, and click it when ready. @@ -7,7 +9,6 @@ - Added bunch of new labels, and improved others. - Renamed `buildCaseStatement.sh` to `buildLabel.sh` and improved it a lot. It is a great start when figuring out how to create a new label for an app, or a piece of software. Look at the tutorials in our wiki. - Mosyle changed their app name from Business to Self-Service -- Added option to not interrupt Do Not Disturb full screen apps like KeyNote or Zoom with `INTERRUPT_DND="no"`. ## v0.6 - 2021-07-14 From e622c6d43404711f9926ab4393731f73138c5823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Fri, 26 Nov 2021 09:56:50 +0100 Subject: [PATCH 04/76] Update README.md --- README.md | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index aef13c3..320bb30 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,19 @@ This script is in the “we find it useful, it is working for us” stage. Your production and deployment environment will be different, please test thoroughly before rolling it out to your production. -I have put a lot of work into making it stable and safe, but I cannot - of course - make _any_ promises that it won't break in some not yet encountered edge case. +We have put a lot of work into making it stable and safe, but we cannot - of course - make _any_ promises that it won't break in some not yet encountered edge case. + +## Authors + +Intallomator was original inspired by the download scripts from William Smith and Sander Schram, and created by: + Armin Briegel - @scriptingosx + +Later on a few more contributers came on the project: + Isaac Ordonez - @issacatmann + Søren Theilgaard - @Theile + Adam Codega - @acodega + + And with numerous contributions from many others. ## Support and Contributing @@ -22,7 +34,7 @@ Please see [CONTRIBUTING.md](https://github.com/Installomator/Installomator/blob ## More reading -There are a few interesting post on Installomator on my weblog: +There are a few interesting post on Installomator on Armin’s weblog: - [Introducing Installomator](https://scriptingosx.com/2020/05/introducing-installomator/) - [Using Installomator with Jamf Pro](https://scriptingosx.com/2020/06/using-installomator-with-jamf-pro/) by Mischa van der Bent @@ -66,12 +78,12 @@ At some point, earlier this year, I got frustrated at the number of scripts we w ## Goals -My goals for Installomator are: +The goals for Installomator are: - work with various common archive types - verify the downloaded archive or application -- have a simple 'interface' to the admin -- single script file so it can 'easily' be copied into a management system +- have a simple ‘interface’ to the admin +- single script file so it can ‘easily’ be copied into a management system - extensible without deep scripting knowledge - work independently of a specific management system - no dependencies that may be removed from macOS in the future or are not pre-installed @@ -90,7 +102,7 @@ When the download yields a pkg file, Installomator will run `installer` to insta Applications in dmgs or zips will be copied to `/Applications` and their owner will be set to the current user, so the install works like a standard drag'n drop installation. -(I consider it a disgrace, that Jamf, after nearly 20 years, _still_ cannot deal with 'drag'n drop installation dmgs' natively. It's not _that_ hard.) +(I consider it a disgrace, that Jamf, after nearly 20 years, _still_ cannot deal with ‘drag’n drop installation dmgs’ natively. It's not _that_ hard.) ### Verify the download From dd8b9b2b160f265e16b97e018d79790a13c04f60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Fri, 26 Nov 2021 10:06:37 +0100 Subject: [PATCH 05/76] Update README.md --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 320bb30..e7ed94d 100644 --- a/README.md +++ b/README.md @@ -189,11 +189,13 @@ Other than the version arguments, the argument can be any of the labels listed i ### Debug mode -There is a variable named `DEBUG` which is set in line 21 of the script. When `DEBUG` is set to `1` (default) no actions that would actually modify the current system are taken. This is useful for testing most of the actions in the script, but obviously not all of them. +There is a variable named `DEBUG` which is set in line 21 of the script. When `DEBUG` is set to `1` (default) or `2` for a variation of debug, no actions that would actually modify the current system are taken. This is useful for testing most of the actions in the script, but obviously not all of them. -Also when the `DEBUG` variable is `1`, downloaded archives and extracted files will be written to the script's directory, rather than a temporary directory, which can make debugging easier. +When the `DEBUG` variable is `1`, downloaded archives and extracted files will be written to the script's directory, rather than a temporary directory, which can make debugging easier. -_Always remember_ to change the `DEBUG` variable to `0` when deploying. +When `DEBUG` variable is `2`, the temporary folder is created and downloaded and extracted files goes to that folder, as if not in DEBUG mode, but installation is still not done. On the other hand blocking processes are checked, the app is reopened if closed, and the user is notified. + +_Always remember_ to change the `DEBUG` variable to `0` when deploying. The installer PKG we provide has `DEBUG=0`. ### Use Installomator with Jamf Pro @@ -203,6 +205,8 @@ Remember to set `DEBUG` to `0`. Then you can use the Installomator script in a policy and choose the application to install by setting the label for argument 4. + + ## What it does When it runs with a known label, the script will perform the following: From fd2ed3aa49e8c4f4503ba659b3d361f587cad15b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Fri, 26 Nov 2021 10:39:29 +0100 Subject: [PATCH 06/76] Update README.md --- README.md | 149 ++++-------------------------------------------------- 1 file changed, 10 insertions(+), 139 deletions(-) diff --git a/README.md b/README.md index e7ed94d..c9f3ad6 100644 --- a/README.md +++ b/README.md @@ -195,17 +195,13 @@ When the `DEBUG` variable is `1`, downloaded archives and extracted files will b When `DEBUG` variable is `2`, the temporary folder is created and downloaded and extracted files goes to that folder, as if not in DEBUG mode, but installation is still not done. On the other hand blocking processes are checked, the app is reopened if closed, and the user is notified. +Debug mode 1 is useful to test the download and verification process without having to re-download and re-install an application or package on your system. Debug mode 2 is great for checking running processe and notifications. + _Always remember_ to change the `DEBUG` variable to `0` when deploying. The installer PKG we provide has `DEBUG=0`. -### Use Installomator with Jamf Pro - -In Jamf Pro, create a new 'Script' and paste the contents of `Installomator.sh` into the 'Script Contents' area. Under 'Options' you can change the parameter label for argument 4 to 'Application Label.' - -Remember to set `DEBUG` to `0`. - -Then you can use the Installomator script in a policy and choose the application to install by setting the label for argument 4. - +### Use Installomator with various MDM solutions +In the wiki we have provided documentation on how Installomator is used in various MDM solution, like Jamf Pro, Mosyle, and Addigy. ## What it does @@ -225,15 +221,7 @@ When it runs with a known label, the script will perform the following: ## Configuring the script -As of now there are two settings that are meant to configured when deploying the script. - -### Debug mode - -The first is the `DEBUG` variable. When this is set to `1` the script will _not_ perform any changes to the current system. In other words, no application will be copied to the target directory and no `installer` command be performed. - -In addition, files will be downloaded and extracted to the Installomator project folder instead of a temporary directory and _not_ deleted when the script exits. Also archives will _not_ be re-downloaded when they already exist in the project folder. The repository's `.gitignore` file is set up to ignore the archive file extensions. - -Debug mode is useful to test the download and verification process without having to re-download and re-install an application or package on your system. +We have several default settings for certain behavior and notifications inside the script, but these can be customized when calling the script. ### Blocking Process actions @@ -292,119 +280,6 @@ The `REOPEN` can be used to prevent the reopening of a closed app - `yes`: (default) app will be reopened if it was closed - `no`: app not reopened -### Adding applications/label blocks - -#### Required Variables - -The script requires four pieces of information to download and install an application: - -``` -spotify) - name="Spotify" - type="dmg" - downloadURL="https://download.scdn.co/Spotify.dmg" - expectedTeamID="2FNC3A47ZF" - ;; -``` - -The four required variables are - -- `name`: -The display name of the installed application without the `.app` extensions. - -- `type`: -The type of installation. Possible values: - - `dmg`: application in disk image file (drag'n drop installation) - - `pkg`: flat pkg download - - `zip`: application in zip archive (`zip` extension) - - `tbz`: application in tbz archive (`tbz` extension) - - `pkgInDmg`: a pkg file inside a disk image - - `pkgInZip`: a pkg file inside a zip - - `appInDmgInZip`: an app in a dmg file that has been zip'ed - -- `downloadURL`: -The URL from which to download the archive. -The URL can be generated by a series of commands, for example when you need to parse an xml file for the latest URL. (See `bbedit`, `desktoppr`, or `omnigraffle` for examples.) -Sometimes version differs between Intel and Apple Silicon versions. (See `brave`, `obsidian`, `omnidisksweeper`, or `notion`). - -- `appNewVersion` (optional, but recommended): -Version of the downloaded software. -If given, it will be compared to installed version, to see if download is different. -It does not check for newer or not, only different. -Not always easy to figure out how to make this. Sometimes this is listed on the downloads page, sometimes in other places. And how can we isolate it in a genral manner? (See `abstract`, `bbedit`, `brave`, `desktoppr`, `googlechrome`, or `omnidisksweeper`). - -- `packageID` (optional, but recommended for pkgs without an app) -This variable is for pkg bundle IDs. Very usefull if a pkg only install command line tools, or the like that does not install an app. (See label `desktoppr`, `golang`, `installomator_st`, `odrive`, or `teamviewerhost`). - -- `expectedTeamID`: -The 10-character Developer Team ID with which the application or pkg is signed and notarized. - - Obtain the team ID by running: - - - Applications (in dmgs or zips) - `spctl -a -vv /Applications/BBEdit.app` - - - Installation Packages (pkg) - `spctl -a -vv -t install ~/Downloads/desktoppr-0.2.pkg` - - -#### Optional Variables - -Depending on the application or pkg there are a few more variables you can or need to set. Many of these are derived from the required variables, but may need to be set manually if those derived values do not work. - -- `archiveName`: (optional) - The name of the downloaded file. - When not given the `archiveName` is set to `$name.$type` - -- `appName`: (optional) - File name of the app bundle in the dmg to verify and copy (include the `.app`). - When not given, the `appName` is set to `$name.app`. - This is also the name of the app that will get reopned, if we closed any `blockingProcesses` (see further down) - -- `targetDir`: (optional) - dmg or zip: - Applications will be copied to this directory. - Default value is '`/Applications`' for dmg and zip installations. - pkg: - `targetDir` is used as the install-location. Default is '`/`'. - -- `blockingProcesses`: (optional) - Array of process names that will block the installation or update. - If no `blockingProcesses` array is given the default will be: - `blockingProcesses=( $name )` - When a package contains multiple applications, _all_ should be listed, e.g: - `blockingProcesses=( "Keynote" "Pages" "Numbers" )` - When a workflow has no blocking processes, use - `blockingProcesses=( NONE )` - -- `pkgName`: (optional, only used for `dmgInPkg` and `dmgInZip`) - File name of the pkg file _inside_ the dmg or zip. - When not given the pkgName is set to `$name.pkg`. - -- `updateTool`, `updateToolArguments`: - When Installomator detects an existing installation of the application, - and the `updateTool` variable is set then - `$updateTool $updateArguments` - Will be run instead of of downloading and installing a complete new version. - Use this when the `updateTool` does differential and optimized downloads. - e.g. `msupdate` (see various Microsoft installations). - -- `updateToolRunAsCurrentUser`: - When this variable is set (any value), `$updateTool` will be run as the current user. Default is unset and - -- `CLIInstaller`: -- `CLIArguments`: - If the downloaded dmg is actually an installer that we can call using CLI, we can use these two variables for what to call. - We need to define `name` for the installed app (to be version checked), as well as `installerTool` for the installer app (if named differently that `name`. Installomator will add the path to the folder/disk image with the binary, and it will be called like this: - `$CLIInstaller $CLIArguments` - For most installations `CLIInstaller` should contain the `installerTool` for the CLI call (if it’s the same). - We can support a whole range of other software titles by implementing this. - See label adobecreativeclouddesktop. - -- `installerTool`: - Introduced as part of `CLIInstaller`. If the installer in the DMG or ZIP is named differently than the installed app, then this variable can be used to name the installer that should be located after mounting/expanding the downloaded archive. - See label adobecreativeclouddesktop - ### Configuration from Arguments You can provide a configuration variable, such as `DEBUG` or `NOTIFY` as an argument in the form `VAR=value`. For example: @@ -430,17 +305,13 @@ Providing all the variables this way might be useful for certain downloads that ### What if the latest version of the app is already installed? -Short answer: Installomator will re-download and re-install the latest over the existing installation. +Short answer: That depends on if labels will know what the latest version will be. Longer answer: -Installomator will try to find a currently installed app to log the version. When Installomator finds an existing app (any version) and the `updateTool` variable is set, then Installomator will _not_ download and install, but run the `updateTool` instead. - -However, there is no simple generic method to actually determine the latest version of an application or installer. - -We deploy Installomator usually for user initiated installations from Self Service, so re-installs don't really 'hurt' and may be a useful troubleshooting step. - -When you want to have automated installations, you can use smart groups based on the app version to limit excessive re-installations. +- Labels without this will re-download and re-install the latest over the existing installation. +- Labels with this info will only install the app if the version is different than the one installed. +- Labels that can use update tool will use that for the update (if the version is different) ### Why don't you just use `autopkg install`? @@ -470,7 +341,7 @@ Please don't misunderstand this as me saying that AutoPkg is a bad or poorly des But it is not suited as a client install automation tool. -### Why don't you just use brew? +### Why don't you just use brew or MacPorts? Read the explanation for `autopkg`, pretty much the same applies for `brew`, i.e. while it is useful on a single Mac, it is a un-manageable mess when you think about deploying and managing on a fleet of computers. From fe4c8a96da569b02aa2d657c6bd7f8b77c9839bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 10 Jan 2022 13:04:04 +0100 Subject: [PATCH 07/76] brave fix --- fragments/labels/brave.sh | 4 ++-- fragments/main.sh | 24 ++++++++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/fragments/labels/brave.sh b/fragments/labels/brave.sh index 6e16d6d..ef9df31 100644 --- a/fragments/labels/brave.sh +++ b/fragments/labels/brave.sh @@ -3,12 +3,12 @@ brave) type="dmg" if [[ $(arch) != "i386" ]]; then printlog "Architecture: arm64 (not i386)" - downloadURL=$(curl -fsIL https://laptop-updates.brave.com/latest/osxarm64/release | grep -i "^location" | awk '{print $2}') + downloadURL=$(curl -fsIL https://laptop-updates.brave.com/latest/osxarm64/release | grep -i "^location" | sed -E 's/.*(https.*\.dmg).*/\1/g') appNewVersion="$(curl -fsL "https://updates.bravesoftware.com/sparkle/Brave-Browser/stable-arm64/appcast.xml" | xpath '//rss/channel/item[last()]/enclosure/@sparkle:version' 2>/dev/null | cut -d '"' -f 2)" #appNewVersion="96.$(curl -fsL "https://updates.bravesoftware.com/sparkle/Brave-Browser/stable-arm64/appcast.xml" | xpath '//rss/channel/item[last()]/enclosure/@sparkle:shortVersionString' 2>/dev/null | cut -d '"' -f 2 | cut -d "." -f1-3)" else printlog "Architecture: i386" - downloadURL=$(curl -fsIL https://laptop-updates.brave.com/latest/osx/release | grep -i "^location" | awk '{print $2}') + downloadURL=$(curl -fsIL https://laptop-updates.brave.com/latest/osx/release | grep -i "^location" | sed -E 's/.*(https.*\.dmg).*/\1/g') appNewVersion="$(curl -fsL "https://updates.bravesoftware.com/sparkle/Brave-Browser/stable/appcast.xml" | xpath '//rss/channel/item[last()]/enclosure/@sparkle:version' 2>/dev/null | cut -d '"' -f 2)" #appNewVersion="96.$(curl -fsL "https://updates.bravesoftware.com/sparkle/Brave-Browser/stable/appcast.xml" | xpath '//rss/channel/item[last()]/enclosure/@sparkle:shortVersionString' 2>/dev/null | cut -d '"' -f 2 | cut -d "." -f1-3)" fi diff --git a/fragments/main.sh b/fragments/main.sh index cef364c..2eb8781 100644 --- a/fragments/main.sh +++ b/fragments/main.sh @@ -179,17 +179,25 @@ else fi fi if ! curl --location --fail --silent "$downloadURL" -o "$archiveName"; then - printlog "error downloading $downloadURL" - message="$name update/installation failed. This will be logged, so IT can follow up." - if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then - printlog "notifying" - if [[ $updateDetected == "YES" ]]; then - displaynotification "$message" "Error updating $name" + if ! curl -fsL -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" -H "accept-encoding: gzip, deflate, br" -H "upgrade-insecure-requests: 1" -H "sec-fetch-dest: document" -H "sec-gpc: 1" -H "sec-fetch-user: ?1" -H "accept-language: en-US,en;q=0.9" -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" -H "sec-fetch-mode: navigate" "$downloadURL" -o "$archiveName"; then + if ! curl -fsL -H "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36" -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" -H "accept-encoding: gzip, deflate, br" -H "accept-language: en-US,en;q=0.9" -H "sec-fetch-dest: document" -H "sec-fetch-mode: navigate" -H "sec-fetch-site: same-site" -H "sec-fetch-user: ?1" -H "sec-gpc: 1" -H "upgrade-insecure-requests: 1" "$downloadURL" -o "$archiveName"; then + printlog "error downloading $downloadURL" + message="$name update/installation failed. This will be logged, so IT can follow up." + if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then + printlog "notifying" + if [[ $updateDetected == "YES" ]]; then + displaynotification "$message" "Error updating $name" + else + displaynotification "$message" "Error installing $name" + fi + fi + cleanupAndExit 2 else - displaynotification "$message" "Error installing $name" + printlog "Downloaded with all headers." fi + else + printlog "Downloaded with exta headers." fi - cleanupAndExit 2 fi fi From a8c9fdbab7a58171ec80104dda3e272c94f39b50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 10 Jan 2022 20:26:53 +0100 Subject: [PATCH 08/76] Download with extra sets of headers --- CHANGELOG.md | 1 + .../{disabled => labels}/mochakeyboard.sh | 0 fragments/{disabled => labels}/mochatelnet.sh | 0 fragments/{disabled => labels}/mochatn3270.sh | 0 fragments/{disabled => labels}/mochatn3812.sh | 0 fragments/{disabled => labels}/mochatn5250.sh | 0 fragments/main.sh | 73 +++++++++--- utils/buildLabel.sh | 111 +++++++++++++++--- 8 files changed, 149 insertions(+), 36 deletions(-) rename fragments/{disabled => labels}/mochakeyboard.sh (100%) rename fragments/{disabled => labels}/mochatelnet.sh (100%) rename fragments/{disabled => labels}/mochatn3270.sh (100%) rename fragments/{disabled => labels}/mochatn3812.sh (100%) rename fragments/{disabled => labels}/mochatn5250.sh (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dd2a79..11f3056 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - New variable `RETURN_LABEL_NAME`. If given the value `1`, like `RETURN_LABEL_NAME=1` then Installomator only returns the name of the label. It makes for a better user friendly message for displaying in DEPNotify if that is integrated. - Changed logic if `IGNORE_APP_STORE_APPS=yes`. Before this version a label like `microsoftonedrive` that was installed from App Store, and that we want to replace with the “ordinary” version, Installomator would still use `updateTool`, even though `IGNORE_APP_STORE_APPS=yes`. So we would have to have `INSTALL=force` in order to have the app replaced, as `updateTool` would be used. But now if `IGNORE_APP_STORE_APPS=yes` then `updateTool` will be not set, and the App Store app will be replaced. BUT if the installed software was not from App Store, then `updateTool` will not be used, and it would be a kind of a forced install (in the example of `microsoftonedrive`), except if the version is the same (where installation is skipped). - Added variable `SYSTEMOWNER` that is used when copying files when installing. Default `0` is to change owner of the app to the current user on the Mac, like this user was installing this app themselves. When using `1` we will put “root:wheel” on the app, which can be useful for shared machines. +- Installomator will normally use `curl`without any headers to download files. But in the `buildLabel.sh` script it was necessary to add extra headers to get the correct download URLs from some servers, and as we get more experienced, various servers require different headers. In this version 3 set of extra headers has been added, so a download will be tried 4 times, but with different headers. Same sets of headers are also in `buildLabel.sh` in the same order. That has made it possible for the "mocha"-software-labels to work. ## v8.0 diff --git a/fragments/disabled/mochakeyboard.sh b/fragments/labels/mochakeyboard.sh similarity index 100% rename from fragments/disabled/mochakeyboard.sh rename to fragments/labels/mochakeyboard.sh diff --git a/fragments/disabled/mochatelnet.sh b/fragments/labels/mochatelnet.sh similarity index 100% rename from fragments/disabled/mochatelnet.sh rename to fragments/labels/mochatelnet.sh diff --git a/fragments/disabled/mochatn3270.sh b/fragments/labels/mochatn3270.sh similarity index 100% rename from fragments/disabled/mochatn3270.sh rename to fragments/labels/mochatn3270.sh diff --git a/fragments/disabled/mochatn3812.sh b/fragments/labels/mochatn3812.sh similarity index 100% rename from fragments/disabled/mochatn3812.sh rename to fragments/labels/mochatn3812.sh diff --git a/fragments/disabled/mochatn5250.sh b/fragments/labels/mochatn5250.sh similarity index 100% rename from fragments/disabled/mochatn5250.sh rename to fragments/labels/mochatn5250.sh diff --git a/fragments/main.sh b/fragments/main.sh index 2eb8781..ac036ad 100644 --- a/fragments/main.sh +++ b/fragments/main.sh @@ -168,7 +168,7 @@ fi if [ -f "$archiveName" ] && [ "$DEBUG" -eq 1 ]; then printlog "$archiveName exists and DEBUG mode 1 enabled, skipping download" else - # download the dmg + # download printlog "Downloading $downloadURL to $archiveName" if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then printlog "notifying" @@ -178,25 +178,64 @@ else displaynotification "Downloading new $name" "Download in progress …" fi fi - if ! curl --location --fail --silent "$downloadURL" -o "$archiveName"; then - if ! curl -fsL -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" -H "accept-encoding: gzip, deflate, br" -H "upgrade-insecure-requests: 1" -H "sec-fetch-dest: document" -H "sec-gpc: 1" -H "sec-fetch-user: ?1" -H "accept-language: en-US,en;q=0.9" -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" -H "sec-fetch-mode: navigate" "$downloadURL" -o "$archiveName"; then - if ! curl -fsL -H "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36" -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" -H "accept-encoding: gzip, deflate, br" -H "accept-language: en-US,en;q=0.9" -H "sec-fetch-dest: document" -H "sec-fetch-mode: navigate" -H "sec-fetch-site: same-site" -H "sec-fetch-user: ?1" -H "sec-gpc: 1" -H "upgrade-insecure-requests: 1" "$downloadURL" -o "$archiveName"; then - printlog "error downloading $downloadURL" - message="$name update/installation failed. This will be logged, so IT can follow up." - if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then - printlog "notifying" - if [[ $updateDetected == "YES" ]]; then - displaynotification "$message" "Error updating $name" - else - displaynotification "$message" "Error installing $name" + if ! curl -fsL "$downloadURL" -o "$archiveName"; then + printlog "Trying 1st set of extra headers to download." + if ! \ + curl -fsL \ + -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" \ + -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" \ + -H "accept-encoding: gzip, deflate, br" \ + -H "accept-language: en-US,en;q=0.9" \ + -H "sec-fetch-dest: document" \ + -H "sec-fetch-mode: navigate" \ + -H "sec-fetch-user: ?1" \ + -H "sec-gpc: 1" \ + -H "upgrade-insecure-requests: 1" \ + "$downloadURL" -o "$archiveName" + then + printlog "Trying 2nd set of extra headers to download." + if ! \ + curl -fsL \ + -H "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36" \ + -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" \ + -H "accept-encoding: gzip, deflate, br" \ + -H "accept-language: en-US,en;q=0.9" \ + -H "sec-fetch-dest: document" \ + -H "sec-fetch-mode: navigate" \ + -H "sec-fetch-site: same-site" \ + -H "sec-fetch-user: ?1" \ + -H "sec-gpc: 1" \ + -H "upgrade-insecure-requests: 1" \ + "$downloadURL" -o "$archiveName" + then + printlog "Trying 3rd set of extra headers to download." + if ! \ + curl -fsL \ + -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" \ + -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" \ + -H "accept-encoding: gzip, deflate, br" \ + -H "accept-language: en-US,en;q=0.9" \ + -H "sec-fetch-dest: document" \ + -H "sec-fetch-mode: navigate" \ + -H "sec-fetch-user: ?1" \ + -H "sec-gpc: 1" \ + -H "upgrade-insecure-requests: 1" \ + -H "Referrer Policy: strict-origin-when-cross-origin" \ + "$downloadURL" -o "$archiveName" + then + printlog "error downloading $downloadURL" + message="$name update/installation failed. This will be logged, so IT can follow up." + if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then + printlog "notifying" + if [[ $updateDetected == "YES" ]]; then + displaynotification "$message" "Error updating $name" + else + displaynotification "$message" "Error installing $name" + fi fi + cleanupAndExit 2 fi - cleanupAndExit 2 - else - printlog "Downloaded with all headers." fi - else - printlog "Downloaded with exta headers." fi fi fi diff --git a/utils/buildLabel.sh b/utils/buildLabel.sh index 8f96e3c..3dd8a5d 100755 --- a/utils/buildLabel.sh +++ b/utils/buildLabel.sh @@ -153,32 +153,105 @@ echo "Downloading $downloadURL" echo $(basename $downloadURL) # First trying to find redirection headers on the download, as those can contain version numbers echo "Redirecting to (maybe this can help us with version):\n$(curl -fsIL -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" -H "accept-encoding: gzip, deflate, br" -H "Referrer Policy: strict-origin-when-cross-origin" -H "upgrade-insecure-requests: 1" -H "sec-fetch-dest: document" -H "sec-gpc: 1" -H "sec-fetch-user: ?1" -H "accept-language: en-US,en;q=0.9" -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" -H "sec-fetch-mode: navigate" "$downloadURL" | grep -i "^[location|x\-amz\-meta\-version]*")" -# Now downloading without extra headers -if ! downloadOut="$(curl -fL "$downloadURL" --remote-header-name --remote-name -w "%{filename_effective}\n%{url_effective}\n")"; then - echo "error downloading $downloadURL using standard headers." - echo "result: $downloadOut" - echo "Trying all headers…" # that I know of - if ! downloadOut="$(curl -fL -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" -H "accept-encoding: gzip, deflate, br" -H "Referrer Policy: strict-origin-when-cross-origin" -H "upgrade-insecure-requests: 1" -H "sec-fetch-dest: document" -H "sec-gpc: 1" -H "sec-fetch-user: ?1" -H "accept-language: en-US,en;q=0.9" -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" -H "sec-fetch-mode: navigate" "$downloadURL" --remote-header-name --remote-name -w "%{filename_effective}\n%{url_effective}\n")"; then - echo "Trying almost all headers…" # that I know of - if ! downloadOut="$(curl -fL -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" -H "accept-encoding: gzip, deflate, br" -H "upgrade-insecure-requests: 1" -H "sec-fetch-dest: document" -H "sec-gpc: 1" -H "sec-fetch-user: ?1" -H "accept-language: en-US,en;q=0.9" -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" -H "sec-fetch-mode: navigate" "$downloadURL" --remote-header-name --remote-name -w "%{filename_effective}\n%{url_effective}\n")"; then - # we are only here if the download failed - echo "error downloading $downloadURL using two different sets of headers." - echo "result: $downloadOut" - # Sometimes a server will give some results to the downloaded output - if [[ -n $downloadOut ]]; then - echo "Trying output of this…" - downloadURL="$(echo $downloadOut | tail -1)" - # Last chance for succes on this download - if ! downloadOut="$(curl -fL "$downloadURL" --remote-header-name --remote-name -w "%{filename_effective}\n%{url_effective}\n")"; then - echo "error downloading $downloadURL using previous output." - echo "result: $downloadOut" +# Now downloading without various sets of extra headers +if ! downloadOut1="$( \ +curl -fL "$downloadURL" --remote-header-name --remote-name \ +-w "%{filename_effective}\n%{url_effective}\n")" +then + echo "error downloading $downloadURL with no headers." + echo "result: $downloadOut1" + echo "Trying 1st set of extra headers to download." + if ! downloadOut2="$( \ + curl -fL \ + -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" \ + -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" \ + -H "accept-encoding: gzip, deflate, br" \ + -H "accept-language: en-US,en;q=0.9" \ + -H "sec-fetch-dest: document" \ + -H "sec-fetch-mode: navigate" \ + -H "sec-fetch-user: ?1" \ + -H "sec-gpc: 1" \ + -H "upgrade-insecure-requests: 1" \ + "$downloadURL" --remote-header-name --remote-name \ + -w "%{filename_effective}\n%{url_effective}\n")" + then + echo "error downloading $downloadURL with 1st set of headers." + echo "result: $downloadOut2" + echo "Trying 2nd set of extra headers to download." + if ! downloadOut3="$( \ + curl -fL \ + -H "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36" \ + -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" \ + -H "accept-encoding: gzip, deflate, br" \ + -H "accept-language: en-US,en;q=0.9" \ + -H "sec-fetch-dest: document" \ + -H "sec-fetch-mode: navigate" \ + -H "sec-fetch-site: same-site" \ + -H "sec-fetch-user: ?1" \ + -H "sec-gpc: 1" \ + -H "upgrade-insecure-requests: 1" \ + "$downloadURL" --remote-header-name --remote-name \ + -w "%{filename_effective}\n%{url_effective}\n")" + then + echo "error downloading $downloadURL with 2nd set of headers." + echo "result: $downloadOut3" + echo "Trying 3rd set of extra headers to download." + if ! downloadOut4="$( \ + curl -fL \ + -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" \ + -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" \ + -H "accept-encoding: gzip, deflate, br" \ + -H "accept-language: en-US,en;q=0.9" \ + -H "sec-fetch-dest: document" \ + -H "sec-fetch-mode: navigate" \ + -H "sec-fetch-user: ?1" \ + -H "sec-gpc: 1" \ + -H "upgrade-insecure-requests: 1" \ + -H "Referrer Policy: strict-origin-when-cross-origin" \ + "$downloadURL" --remote-header-name --remote-name \ + -w "%{filename_effective}\n%{url_effective}\n")" + then + # we are only here if the download failed + echo "error downloading $downloadURL with 3rd set of headers." + echo "result: $downloadOut4" + echo "no more header sets to try" + # Sometimes a server will give some results to the downloaded output + echo "If any information came out of the previous download attempts, we can try those…" + downloadOuts=( "$downloadOut1" "$downloadOut3" "$downloadOut3" "$downloadOut4" ) + downloadOutCount=${#downloadOuts} + for downloadOut in $downloadOuts ; do + if [[ -n $downloadOut ]]; then + echo "Trying output of this…" + downloadURL="$(echo $downloadOut | tail -1)" + # Last chance for succes on this download + if ! downloadOut="$(curl -fL "$downloadURL" --remote-header-name --remote-name -w "%{filename_effective}\n%{url_effective}\n")"; then + echo "error downloading $downloadURL using previous output." + echo "result: $downloadOut" + ((downloadOutCount--)) + else + echo "Success on this download." + succesDownloadOut=$downloadOut + return + fi + fi + done + if [[ $downloadOutCount -eq 0 ]]; then echo "No more tries. Cannot continue." exit 1 fi + else + succesDownloadOut=$downloadOut4 fi + else + succesDownloadOut=$downloadOut3 fi + else + succesDownloadOut=$downloadOut2 fi +else + succesDownloadOut=$downloadOut1 fi +downloadOut=$succesDownloadOut # Now we have downloaded the archive, and we need to analyze this # The download have returned both {filename_effective} and {url_effective} From 732181c3a6807a21e2e90694031e86d32cc6798c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Tue, 11 Jan 2022 11:42:29 +0100 Subject: [PATCH 09/76] Delete main.sh --- fragments/main.sh | 305 ---------------------------------------------- 1 file changed, 305 deletions(-) delete mode 100644 fragments/main.sh diff --git a/fragments/main.sh b/fragments/main.sh deleted file mode 100644 index ac036ad..0000000 --- a/fragments/main.sh +++ /dev/null @@ -1,305 +0,0 @@ -*) - # unknown label - #printlog "unknown label $label" - cleanupAndExit 1 "unknown label $label" - ;; -esac - -# Are we only asked to return label name -if [[ $RETURN_LABEL_NAME -eq 1 ]]; then - printlog "Only returning label name." - printlog "$name" - echo "$name" - exit -fi - -# MARK: application download and installation starts here - -printlog "BLOCKING_PROCESS_ACTION=${BLOCKING_PROCESS_ACTION}" -printlog "NOTIFY=${NOTIFY}" - -# Finding LOGO to use in dialogs -case $LOGO in - appstore) - # Apple App Store on Mac - if [[ $(sw_vers -buildVersion) > "19" ]]; then - LOGO="/System/Applications/App Store.app/Contents/Resources/AppIcon.icns" - else - LOGO="/Applications/App Store.app/Contents/Resources/AppIcon.icns" - fi - ;; - jamf) - # Jamf Pro - LOGO="/Library/Application Support/JAMF/Jamf.app/Contents/Resources/AppIcon.icns" - ;; - mosyleb) - # Mosyle Business - LOGO="/Applications/Self-Service.app/Contents/Resources/AppIcon.icns" - ;; - mosylem) - # Mosyle Manager (education) - LOGO="/Applications/Manager.app/Contents/Resources/AppIcon.icns" - ;; - addigy) - # Addigy - LOGO="/Library/Addigy/macmanage/MacManage.app/Contents/Resources/atom.icns" - ;; -esac -if [[ ! -a "${LOGO}" ]]; then - if [[ $(sw_vers -buildVersion) > "19" ]]; then - LOGO="/System/Applications/App Store.app/Contents/Resources/AppIcon.icns" - else - LOGO="/Applications/App Store.app/Contents/Resources/AppIcon.icns" - fi -fi -printlog "LOGO=${LOGO}" - -# MARK: extract info from data -if [ -z "$archiveName" ]; then - case $type in - dmg|pkg|zip|tbz) - archiveName="${name}.$type" - ;; - pkgInDmg) - archiveName="${name}.dmg" - ;; - *InZip) - archiveName="${name}.zip" - ;; - updateronly) - ;; - *) - printlog "Cannot handle type $type" - cleanupAndExit 99 - ;; - esac -fi - -if [ -z "$appName" ]; then - # when not given derive from name - appName="$name.app" -fi - -if [ -z "$targetDir" ]; then - case $type in - dmg|zip|tbz|app*) - targetDir="/Applications" - ;; - pkg*) - targetDir="/" - ;; - updateronly) - ;; - *) - printlog "Cannot handle type $type" - cleanupAndExit 99 - ;; - esac -fi - -if [[ -z $blockingProcesses ]]; then - printlog "no blocking processes defined, using $name as default" - blockingProcesses=( $name ) -fi - -# MARK: determine tmp dir -if [ "$DEBUG" -eq 1 ]; then - # for debugging use script dir as working directory - tmpDir=$(dirname "$0") -else - # create temporary working directory - tmpDir=$(mktemp -d ) -fi - -# MARK: change directory to temporary working directory -printlog "Changing directory to $tmpDir" -if ! cd "$tmpDir"; then - printlog "error changing directory $tmpDir" - cleanupAndExit 1 -fi - -# MARK: get installed version -getAppVersion -printlog "appversion: $appversion" - -# MARK: Exit if new version is the same as installed version (appNewVersion specified) -if [[ "$type" != "updateronly" && ($INSTALL == "force" || $IGNORE_APP_STORE_APPS == "yes") ]]; then - printlog "Label is not of type “updateronly”, and it’s set to use force to install or ignoring app store apps, so not using updateTool." - updateTool="" -fi -if [[ -n $appNewVersion ]]; then - printlog "Latest version of $name is $appNewVersion" - if [[ $appversion == $appNewVersion ]]; then - if [[ $DEBUG -ne 1 ]]; then - printlog "There is no newer version available." - if [[ $INSTALL != "force" ]]; then - message="$name, version $appNewVersion, is the latest version." - if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then - printlog "notifying" - displaynotification "$message" "No update for $name!" - fi - cleanupAndExit 0 "No newer version." - fi - else - printlog "DEBUG mode 1 enabled, not exiting, but there is no new version of app." - fi - fi -else - printlog "Latest version not specified." -fi - -# MARK: check if this is an Update and we can use updateTool -if [[ (-n $appversion && -n "$updateTool") || "$type" == "updateronly" ]]; then - printlog "appversion & updateTool" - if [[ $DEBUG -ne 1 ]]; then - if runUpdateTool; then - finishing - cleanupAndExit 0 - elif [[ $type == "updateronly" ]];then - printlog "type is $type so we end here." - cleanupAndExit 0 - fi # otherwise continue - else - printlog "DEBUG mode 1 enabled, not running update tool" - fi -fi - -# MARK: download the archive -if [ -f "$archiveName" ] && [ "$DEBUG" -eq 1 ]; then - printlog "$archiveName exists and DEBUG mode 1 enabled, skipping download" -else - # download - printlog "Downloading $downloadURL to $archiveName" - if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then - printlog "notifying" - if [[ $updateDetected == "YES" ]]; then - displaynotification "Downloading $name update" "Download in progress …" - else - displaynotification "Downloading new $name" "Download in progress …" - fi - fi - if ! curl -fsL "$downloadURL" -o "$archiveName"; then - printlog "Trying 1st set of extra headers to download." - if ! \ - curl -fsL \ - -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" \ - -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" \ - -H "accept-encoding: gzip, deflate, br" \ - -H "accept-language: en-US,en;q=0.9" \ - -H "sec-fetch-dest: document" \ - -H "sec-fetch-mode: navigate" \ - -H "sec-fetch-user: ?1" \ - -H "sec-gpc: 1" \ - -H "upgrade-insecure-requests: 1" \ - "$downloadURL" -o "$archiveName" - then - printlog "Trying 2nd set of extra headers to download." - if ! \ - curl -fsL \ - -H "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36" \ - -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" \ - -H "accept-encoding: gzip, deflate, br" \ - -H "accept-language: en-US,en;q=0.9" \ - -H "sec-fetch-dest: document" \ - -H "sec-fetch-mode: navigate" \ - -H "sec-fetch-site: same-site" \ - -H "sec-fetch-user: ?1" \ - -H "sec-gpc: 1" \ - -H "upgrade-insecure-requests: 1" \ - "$downloadURL" -o "$archiveName" - then - printlog "Trying 3rd set of extra headers to download." - if ! \ - curl -fsL \ - -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" \ - -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" \ - -H "accept-encoding: gzip, deflate, br" \ - -H "accept-language: en-US,en;q=0.9" \ - -H "sec-fetch-dest: document" \ - -H "sec-fetch-mode: navigate" \ - -H "sec-fetch-user: ?1" \ - -H "sec-gpc: 1" \ - -H "upgrade-insecure-requests: 1" \ - -H "Referrer Policy: strict-origin-when-cross-origin" \ - "$downloadURL" -o "$archiveName" - then - printlog "error downloading $downloadURL" - message="$name update/installation failed. This will be logged, so IT can follow up." - if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then - printlog "notifying" - if [[ $updateDetected == "YES" ]]; then - displaynotification "$message" "Error updating $name" - else - displaynotification "$message" "Error installing $name" - fi - fi - cleanupAndExit 2 - fi - fi - fi - fi -fi - -# MARK: when user is logged in, and app is running, prompt user to quit app -if [[ $BLOCKING_PROCESS_ACTION == "ignore" ]]; then - printlog "ignoring blocking processes" -else - if [[ $currentUser != "loginwindow" ]]; then - if [[ ${#blockingProcesses} -gt 0 ]]; then - if [[ ${blockingProcesses[1]} != "NONE" ]]; then - checkRunningProcesses - fi - fi - fi -fi - -# MARK: install the download -printlog "Installing $name" -if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then - printlog "notifying" - if [[ $updateDetected == "YES" ]]; then - displaynotification "Updating $name" "Installation in progress …" - else - displaynotification "Installing $name" "Installation in progress …" - fi -fi - -if [ -n "$installerTool" ]; then - # installerTool defined, and we use that for installation - printlog "installerTool used: $installerTool" - appName="$installerTool" -fi - -case $type in - dmg) - installFromDMG - ;; - pkg) - installFromPKG - ;; - zip) - installFromZIP - ;; - tbz) - installFromTBZ - ;; - pkgInDmg) - installPkgInDmg - ;; - pkgInZip) - installPkgInZip - ;; - appInDmgInZip) - installAppInDmgInZip - ;; - *) - printlog "Cannot handle type $type" - cleanupAndExit 99 - ;; -esac - -# MARK: Finishing — print installed application location and version -finishing - -# all done! -cleanupAndExit 0 From 01eabca204c2c82ef05622e31f68e116163829ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Tue, 11 Jan 2022 11:54:54 +0100 Subject: [PATCH 10/76] Introducing `curlOptions` to labels. --- CHANGELOG.md | 2 +- fragments/labels/mochatn3270.sh | 9 ++ fragments/main.sh | 258 ++++++++++++++++++++++++++++++++ 3 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 fragments/main.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 11f3056..ff2cfcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ - New variable `RETURN_LABEL_NAME`. If given the value `1`, like `RETURN_LABEL_NAME=1` then Installomator only returns the name of the label. It makes for a better user friendly message for displaying in DEPNotify if that is integrated. - Changed logic if `IGNORE_APP_STORE_APPS=yes`. Before this version a label like `microsoftonedrive` that was installed from App Store, and that we want to replace with the “ordinary” version, Installomator would still use `updateTool`, even though `IGNORE_APP_STORE_APPS=yes`. So we would have to have `INSTALL=force` in order to have the app replaced, as `updateTool` would be used. But now if `IGNORE_APP_STORE_APPS=yes` then `updateTool` will be not set, and the App Store app will be replaced. BUT if the installed software was not from App Store, then `updateTool` will not be used, and it would be a kind of a forced install (in the example of `microsoftonedrive`), except if the version is the same (where installation is skipped). - Added variable `SYSTEMOWNER` that is used when copying files when installing. Default `0` is to change owner of the app to the current user on the Mac, like this user was installing this app themselves. When using `1` we will put “root:wheel” on the app, which can be useful for shared machines. -- Installomator will normally use `curl`without any headers to download files. But in the `buildLabel.sh` script it was necessary to add extra headers to get the correct download URLs from some servers, and as we get more experienced, various servers require different headers. In this version 3 set of extra headers has been added, so a download will be tried 4 times, but with different headers. Same sets of headers are also in `buildLabel.sh` in the same order. That has made it possible for the "mocha"-software-labels to work. +- Added option `curlOptions` to the labels. It can be filled with extra headers need for downloading the specific software. See “mocha”-software-labels. By default Installomator use `curl` without any headers to download files, but in the `buildLabel.sh` script it was necessary to add extra headers to get the correct download URLs from some servers, and as we get more experienced, various servers require different headers. So 3 different sets of headers have been added to `buildLabel.sh` so a download will be tried 4 times. Browsers like Safari and Brave can be used to inspect which headers are needed for software to donwload. ## v8.0 diff --git a/fragments/labels/mochatn3270.sh b/fragments/labels/mochatn3270.sh index 74ce410..b375fc6 100644 --- a/fragments/labels/mochatn3270.sh +++ b/fragments/labels/mochatn3270.sh @@ -3,5 +3,14 @@ mochatn3270) type="appInDmgInZip" downloadURL="https://mochasoft.dk/tn3270.dmg.zip" appNewVersion="" + curlOptions="-H \"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15\" \ +-H \"accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\" \ +-H \"accept-encoding: gzip, deflate, br\" \ +-H \"accept-language: en-US,en;q=0.9\" \ +-H \"sec-fetch-dest: document\" \ +-H \"sec-fetch-mode: navigate\" \ +-H \"sec-fetch-user: ?1\" \ +-H \"sec-gpc: 1\" \ +-H \"upgrade-insecure-requests: 1\" " expectedTeamID="RR9F5EPNVW" ;; diff --git a/fragments/main.sh b/fragments/main.sh new file mode 100644 index 0000000..71994af --- /dev/null +++ b/fragments/main.sh @@ -0,0 +1,258 @@ +*) + # unknown label + #printlog "unknown label $label" + cleanupAndExit 1 "unknown label $label" + ;; +esac + +# Are we only asked to return label name +if [[ $RETURN_LABEL_NAME -eq 1 ]]; then + printlog "Only returning label name." + printlog "$name" + echo "$name" + exit +fi + +# MARK: application download and installation starts here + +printlog "BLOCKING_PROCESS_ACTION=${BLOCKING_PROCESS_ACTION}" +printlog "NOTIFY=${NOTIFY}" + +# Finding LOGO to use in dialogs +case $LOGO in + appstore) + # Apple App Store on Mac + if [[ $(sw_vers -buildVersion) > "19" ]]; then + LOGO="/System/Applications/App Store.app/Contents/Resources/AppIcon.icns" + else + LOGO="/Applications/App Store.app/Contents/Resources/AppIcon.icns" + fi + ;; + jamf) + # Jamf Pro + LOGO="/Library/Application Support/JAMF/Jamf.app/Contents/Resources/AppIcon.icns" + ;; + mosyleb) + # Mosyle Business + LOGO="/Applications/Self-Service.app/Contents/Resources/AppIcon.icns" + ;; + mosylem) + # Mosyle Manager (education) + LOGO="/Applications/Manager.app/Contents/Resources/AppIcon.icns" + ;; + addigy) + # Addigy + LOGO="/Library/Addigy/macmanage/MacManage.app/Contents/Resources/atom.icns" + ;; +esac +if [[ ! -a "${LOGO}" ]]; then + if [[ $(sw_vers -buildVersion) > "19" ]]; then + LOGO="/System/Applications/App Store.app/Contents/Resources/AppIcon.icns" + else + LOGO="/Applications/App Store.app/Contents/Resources/AppIcon.icns" + fi +fi +printlog "LOGO=${LOGO}" + +# MARK: extract info from data +if [ -z "$archiveName" ]; then + case $type in + dmg|pkg|zip|tbz) + archiveName="${name}.$type" + ;; + pkgInDmg) + archiveName="${name}.dmg" + ;; + *InZip) + archiveName="${name}.zip" + ;; + updateronly) + ;; + *) + printlog "Cannot handle type $type" + cleanupAndExit 99 + ;; + esac +fi + +if [ -z "$appName" ]; then + # when not given derive from name + appName="$name.app" +fi + +if [ -z "$targetDir" ]; then + case $type in + dmg|zip|tbz|app*) + targetDir="/Applications" + ;; + pkg*) + targetDir="/" + ;; + updateronly) + ;; + *) + printlog "Cannot handle type $type" + cleanupAndExit 99 + ;; + esac +fi + +if [[ -z $blockingProcesses ]]; then + printlog "no blocking processes defined, using $name as default" + blockingProcesses=( $name ) +fi + +# MARK: determine tmp dir +if [ "$DEBUG" -eq 1 ]; then + # for debugging use script dir as working directory + tmpDir=$(dirname "$0") +else + # create temporary working directory + tmpDir=$(mktemp -d ) +fi + +# MARK: change directory to temporary working directory +printlog "Changing directory to $tmpDir" +if ! cd "$tmpDir"; then + printlog "error changing directory $tmpDir" + cleanupAndExit 1 +fi + +# MARK: get installed version +getAppVersion +printlog "appversion: $appversion" + +# MARK: Exit if new version is the same as installed version (appNewVersion specified) +if [[ "$type" != "updateronly" && ($INSTALL == "force" || $IGNORE_APP_STORE_APPS == "yes") ]]; then + printlog "Label is not of type “updateronly”, and it’s set to use force to install or ignoring app store apps, so not using updateTool." + updateTool="" +fi +if [[ -n $appNewVersion ]]; then + printlog "Latest version of $name is $appNewVersion" + if [[ $appversion == $appNewVersion ]]; then + if [[ $DEBUG -ne 1 ]]; then + printlog "There is no newer version available." + if [[ $INSTALL != "force" ]]; then + message="$name, version $appNewVersion, is the latest version." + if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then + printlog "notifying" + displaynotification "$message" "No update for $name!" + fi + cleanupAndExit 0 "No newer version." + fi + else + printlog "DEBUG mode 1 enabled, not exiting, but there is no new version of app." + fi + fi +else + printlog "Latest version not specified." +fi + +# MARK: check if this is an Update and we can use updateTool +if [[ (-n $appversion && -n "$updateTool") || "$type" == "updateronly" ]]; then + printlog "appversion & updateTool" + if [[ $DEBUG -ne 1 ]]; then + if runUpdateTool; then + finishing + cleanupAndExit 0 + elif [[ $type == "updateronly" ]];then + printlog "type is $type so we end here." + cleanupAndExit 0 + fi # otherwise continue + else + printlog "DEBUG mode 1 enabled, not running update tool" + fi +fi + +# MARK: download the archive +if [ -f "$archiveName" ] && [ "$DEBUG" -eq 1 ]; then + printlog "$archiveName exists and DEBUG mode 1 enabled, skipping download" +else + # download + printlog "Downloading $downloadURL to $archiveName" + if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then + printlog "notifying" + if [[ $updateDetected == "YES" ]]; then + displaynotification "Downloading $name update" "Download in progress …" + else + displaynotification "Downloading new $name" "Download in progress …" + fi + fi + if ! curl -fsL ${=curlOptions} "$downloadURL" -o "$archiveName"; then + printlog "error downloading $downloadURL" + message="$name update/installation failed. This will be logged, so IT can follow up." + if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then + printlog "notifying" + if [[ $updateDetected == "YES" ]]; then + displaynotification "$message" "Error updating $name" + else + displaynotification "$message" "Error installing $name" + fi + fi + cleanupAndExit 2 + fi +fi + +# MARK: when user is logged in, and app is running, prompt user to quit app +if [[ $BLOCKING_PROCESS_ACTION == "ignore" ]]; then + printlog "ignoring blocking processes" +else + if [[ $currentUser != "loginwindow" ]]; then + if [[ ${#blockingProcesses} -gt 0 ]]; then + if [[ ${blockingProcesses[1]} != "NONE" ]]; then + checkRunningProcesses + fi + fi + fi +fi + +# MARK: install the download +printlog "Installing $name" +if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then + printlog "notifying" + if [[ $updateDetected == "YES" ]]; then + displaynotification "Updating $name" "Installation in progress …" + else + displaynotification "Installing $name" "Installation in progress …" + fi +fi + +if [ -n "$installerTool" ]; then + # installerTool defined, and we use that for installation + printlog "installerTool used: $installerTool" + appName="$installerTool" +fi + +case $type in + dmg) + installFromDMG + ;; + pkg) + installFromPKG + ;; + zip) + installFromZIP + ;; + tbz) + installFromTBZ + ;; + pkgInDmg) + installPkgInDmg + ;; + pkgInZip) + installPkgInZip + ;; + appInDmgInZip) + installAppInDmgInZip + ;; + *) + printlog "Cannot handle type $type" + cleanupAndExit 99 + ;; +esac + +# MARK: Finishing — print installed application location and version +finishing + +# all done! +cleanupAndExit 0 From bd07ee6c76c34b2e8edc2eaaf89c64bba34a7933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Tue, 11 Jan 2022 12:53:06 +0100 Subject: [PATCH 11/76] More to `curlOptions` --- README.md | 5 +++++ fragments/header.sh | 5 +++++ fragments/main.sh | 6 ++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 51e22c2..aaac96b 100644 --- a/README.md +++ b/README.md @@ -317,6 +317,11 @@ The URL from which to download the archive. The URL can be generated by a series of commands, for example when you need to parse an xml file for the latest URL. (See `bbedit`, `desktoppr`, or `omnigraffle` for examples.) Sometimes version differs between Intel and Apple Silicon versions. (See `brave`, `obsidian`, `omnidisksweeper`, or `notion`). +- `curlOptions`: (optional) +Options to the `curl` command, needed for `curl` to be able to download the software. +Usually used for adding extra headers that some servers need in order to serve the file. +(see “mocha”-labels, for examples). + - `appNewVersion` (optional, but recommended): Version of the downloaded software. If given, it will be compared to installed version, to see if download is different. diff --git a/fragments/header.sh b/fragments/header.sh index 36f8500..baea5b9 100644 --- a/fragments/header.sh +++ b/fragments/header.sh @@ -149,6 +149,11 @@ REOPEN="yes" # URL to download the dmg. # Can be generated with a series of commands (see BBEdit for an example). # +# - curlOptions: (optional) +# Options to the curl command, needed for curl to be able to download the software. +# Usually used for adding extra headers that some servers need in order to serve the file. +# (see “mocha”-labels, for examples). +# # - appNewVersion: (optional) # Version of the downloaded software. # If given, it will be compared to the installed version, to see if the download is different. diff --git a/fragments/main.sh b/fragments/main.sh index 71994af..96fdb0e 100644 --- a/fragments/main.sh +++ b/fragments/main.sh @@ -178,7 +178,9 @@ else displaynotification "Downloading new $name" "Download in progress …" fi fi - if ! curl -fsL ${=curlOptions} "$downloadURL" -o "$archiveName"; then + set -x + if ! curl -fsL ${curlOptions} "$downloadURL" -o "$archiveName"; then + set +x printlog "error downloading $downloadURL" message="$name update/installation failed. This will be logged, so IT can follow up." if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then @@ -192,7 +194,7 @@ else cleanupAndExit 2 fi fi - +set +x # MARK: when user is logged in, and app is running, prompt user to quit app if [[ $BLOCKING_PROCESS_ACTION == "ignore" ]]; then printlog "ignoring blocking processes" From 193d51d49fa4a6684b6564277f07b790c0e86187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Tue, 11 Jan 2022 16:32:18 +0100 Subject: [PATCH 12/76] `curlOptions` as array. --- README.md | 5 +++-- fragments/header.sh | 5 +++-- fragments/labels/mochakeyboard.sh | 9 +++++++++ fragments/labels/mochatelnet.sh | 9 +++++++++ fragments/labels/mochatn3270.sh | 18 +++++++++--------- fragments/labels/mochatn3812.sh | 9 +++++++++ fragments/labels/mochatn5250.sh | 9 +++++++++ 7 files changed, 51 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index aaac96b..f325f34 100644 --- a/README.md +++ b/README.md @@ -317,10 +317,11 @@ The URL from which to download the archive. The URL can be generated by a series of commands, for example when you need to parse an xml file for the latest URL. (See `bbedit`, `desktoppr`, or `omnigraffle` for examples.) Sometimes version differs between Intel and Apple Silicon versions. (See `brave`, `obsidian`, `omnidisksweeper`, or `notion`). -- `curlOptions`: (optional) +- `curlOptions`: (array, optional) Options to the `curl` command, needed for `curl` to be able to download the software. Usually used for adding extra headers that some servers need in order to serve the file. -(see “mocha”-labels, for examples). +`curlOptions=( -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" )` +(See “mocha”-labels, for examples on labels, and `buildLabel.sh` for header-examples.) - `appNewVersion` (optional, but recommended): Version of the downloaded software. diff --git a/fragments/header.sh b/fragments/header.sh index baea5b9..a514960 100644 --- a/fragments/header.sh +++ b/fragments/header.sh @@ -149,10 +149,11 @@ REOPEN="yes" # URL to download the dmg. # Can be generated with a series of commands (see BBEdit for an example). # -# - curlOptions: (optional) +# - curlOptions: (array, optional) # Options to the curl command, needed for curl to be able to download the software. # Usually used for adding extra headers that some servers need in order to serve the file. -# (see “mocha”-labels, for examples). +# curlOptions=( -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" ) +# (See “mocha”-labels, for examples on labels, and buildLabel.sh for header-examples.) # # - appNewVersion: (optional) # Version of the downloaded software. diff --git a/fragments/labels/mochakeyboard.sh b/fragments/labels/mochakeyboard.sh index 5f742a5..17445e0 100644 --- a/fragments/labels/mochakeyboard.sh +++ b/fragments/labels/mochakeyboard.sh @@ -2,6 +2,15 @@ mochakeyboard) name="Mocha Keyboard" type="appInDmgInZip" downloadURL="https://mochasoft.dk/mochakeyboard.dmg.zip" + curlOptions=( -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" +-H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" +-H "accept-encoding: gzip, deflate, br" +-H "accept-language: en-US,en;q=0.9" +-H "sec-fetch-dest: document" +-H "sec-fetch-mode: navigate" +-H "sec-fetch-user: ?1" +-H "sec-gpc: 1" +-H "upgrade-insecure-requests: 1" ) appNewVersion="" expectedTeamID="RR9F5EPNVW" ;; diff --git a/fragments/labels/mochatelnet.sh b/fragments/labels/mochatelnet.sh index 5eba112..b34d58f 100644 --- a/fragments/labels/mochatelnet.sh +++ b/fragments/labels/mochatelnet.sh @@ -2,6 +2,15 @@ mochatelnet) name="Telnet" type="appInDmgInZip" downloadURL="https://mochasoft.dk/telnet.dmg.zip" + curlOptions=( -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" +-H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" +-H "accept-encoding: gzip, deflate, br" +-H "accept-language: en-US,en;q=0.9" +-H "sec-fetch-dest: document" +-H "sec-fetch-mode: navigate" +-H "sec-fetch-user: ?1" +-H "sec-gpc: 1" +-H "upgrade-insecure-requests: 1" ) appNewVersion="" expectedTeamID="RR9F5EPNVW" ;; diff --git a/fragments/labels/mochatn3270.sh b/fragments/labels/mochatn3270.sh index b375fc6..4be205d 100644 --- a/fragments/labels/mochatn3270.sh +++ b/fragments/labels/mochatn3270.sh @@ -2,15 +2,15 @@ mochatn3270) name="TN3270" type="appInDmgInZip" downloadURL="https://mochasoft.dk/tn3270.dmg.zip" + curlOptions=( -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" +-H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" +-H "accept-encoding: gzip, deflate, br" +-H "accept-language: en-US,en;q=0.9" +-H "sec-fetch-dest: document" +-H "sec-fetch-mode: navigate" +-H "sec-fetch-user: ?1" +-H "sec-gpc: 1" +-H "upgrade-insecure-requests: 1" ) appNewVersion="" - curlOptions="-H \"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15\" \ --H \"accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\" \ --H \"accept-encoding: gzip, deflate, br\" \ --H \"accept-language: en-US,en;q=0.9\" \ --H \"sec-fetch-dest: document\" \ --H \"sec-fetch-mode: navigate\" \ --H \"sec-fetch-user: ?1\" \ --H \"sec-gpc: 1\" \ --H \"upgrade-insecure-requests: 1\" " expectedTeamID="RR9F5EPNVW" ;; diff --git a/fragments/labels/mochatn3812.sh b/fragments/labels/mochatn3812.sh index 54f3884..e27a33e 100644 --- a/fragments/labels/mochatn3812.sh +++ b/fragments/labels/mochatn3812.sh @@ -2,6 +2,15 @@ mochatn3812) name="TN3812" type="appInDmgInZip" downloadURL="https://mochasoft.dk/tn3812.dmg.zip" + curlOptions=( -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" +-H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" +-H "accept-encoding: gzip, deflate, br" +-H "accept-language: en-US,en;q=0.9" +-H "sec-fetch-dest: document" +-H "sec-fetch-mode: navigate" +-H "sec-fetch-user: ?1" +-H "sec-gpc: 1" +-H "upgrade-insecure-requests: 1" ) appNewVersion="" expectedTeamID="Frydendal" ;; diff --git a/fragments/labels/mochatn5250.sh b/fragments/labels/mochatn5250.sh index ae8ccf2..2707120 100644 --- a/fragments/labels/mochatn5250.sh +++ b/fragments/labels/mochatn5250.sh @@ -2,6 +2,15 @@ mochatn5250) name="TN5250" type="appInDmgInZip" downloadURL="https://mochasoft.dk/tn5250.dmg.zip" + curlOptions=( -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" +-H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" +-H "accept-encoding: gzip, deflate, br" +-H "accept-language: en-US,en;q=0.9" +-H "sec-fetch-dest: document" +-H "sec-fetch-mode: navigate" +-H "sec-fetch-user: ?1" +-H "sec-gpc: 1" +-H "upgrade-insecure-requests: 1" ) appNewVersion="" expectedTeamID="RR9F5EPNVW" ;; From 1360b51eaeacc15db512e1a6ea03458b91b61cdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Tue, 11 Jan 2022 16:35:09 +0100 Subject: [PATCH 13/76] removed the debug `set -x` --- fragments/main.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fragments/main.sh b/fragments/main.sh index 96fdb0e..640c244 100644 --- a/fragments/main.sh +++ b/fragments/main.sh @@ -178,9 +178,7 @@ else displaynotification "Downloading new $name" "Download in progress …" fi fi - set -x if ! curl -fsL ${curlOptions} "$downloadURL" -o "$archiveName"; then - set +x printlog "error downloading $downloadURL" message="$name update/installation failed. This will be logged, so IT can follow up." if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then @@ -194,7 +192,7 @@ else cleanupAndExit 2 fi fi -set +x + # MARK: when user is logged in, and app is running, prompt user to quit app if [[ $BLOCKING_PROCESS_ACTION == "ignore" ]]; then printlog "ignoring blocking processes" From ca1759abd90a026ed0e46cdd807103925429d1d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Tue, 11 Jan 2022 18:37:34 +0100 Subject: [PATCH 14/76] Update checkLabels.sh --- utils/checkLabels.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/checkLabels.sh b/utils/checkLabels.sh index f9fdef1..33025ed 100755 --- a/utils/checkLabels.sh +++ b/utils/checkLabels.sh @@ -119,7 +119,7 @@ echo for label in $allLabels; do echo "########## $label" labelWarning=0; labelError=0; expectedExtension=""; URLextension="" - name=""; type=""; downloadURL=""; appNewVersion=""; expectedTeamID=""; blockingProcesses=""; updateTool=""; updateToolArguments=""; archiveName="" + name=""; type=""; downloadURL=""; curlOptions=""; appNewVersion=""; expectedTeamID=""; blockingProcesses=""; updateTool=""; updateToolArguments=""; archiveName="" #caseLabel if cat "${labels_dir}/${label}.sh" | grep -v -E '^[a-z0-9\_-]*(\)|\|\\)$' | grep -v ";;" > checkLabelCurrent.sh; then @@ -156,7 +156,7 @@ for label in $allLabels; do echo "Version: $appNewVersion" ; fi fi - if curl -sfL --output /dev/null -r 0-0 "$downloadURL" ; then + if curl -sfL ${curlOptions} --output /dev/null -r 0-0 "$downloadURL" ; then echo "${GREEN}OK: downloadURL works OK${NC}" if [[ $(echo "$downloadURL" | sed -E 's/.*\.([a-zA-Z]*)\s*/\1/g' ) == "${expectedExtension}" ]]; then echo "${GREEN}OK: download extension MATCH on ${expectedExtension}${NC}" From 59eaff7d26ae5149defbdb4fbf6c1a4d1c696baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Tue, 11 Jan 2022 18:58:39 +0100 Subject: [PATCH 15/76] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff2cfcc..31e2ce7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ - New variable `RETURN_LABEL_NAME`. If given the value `1`, like `RETURN_LABEL_NAME=1` then Installomator only returns the name of the label. It makes for a better user friendly message for displaying in DEPNotify if that is integrated. - Changed logic if `IGNORE_APP_STORE_APPS=yes`. Before this version a label like `microsoftonedrive` that was installed from App Store, and that we want to replace with the “ordinary” version, Installomator would still use `updateTool`, even though `IGNORE_APP_STORE_APPS=yes`. So we would have to have `INSTALL=force` in order to have the app replaced, as `updateTool` would be used. But now if `IGNORE_APP_STORE_APPS=yes` then `updateTool` will be not set, and the App Store app will be replaced. BUT if the installed software was not from App Store, then `updateTool` will not be used, and it would be a kind of a forced install (in the example of `microsoftonedrive`), except if the version is the same (where installation is skipped). - Added variable `SYSTEMOWNER` that is used when copying files when installing. Default `0` is to change owner of the app to the current user on the Mac, like this user was installing this app themselves. When using `1` we will put “root:wheel” on the app, which can be useful for shared machines. -- Added option `curlOptions` to the labels. It can be filled with extra headers need for downloading the specific software. See “mocha”-software-labels. By default Installomator use `curl` without any headers to download files, but in the `buildLabel.sh` script it was necessary to add extra headers to get the correct download URLs from some servers, and as we get more experienced, various servers require different headers. So 3 different sets of headers have been added to `buildLabel.sh` so a download will be tried 4 times. Browsers like Safari and Brave can be used to inspect which headers are needed for software to donwload. +- Added option `curlOptions` to the labels. It can be filled with extra headers need for downloading the specific software. It needs to be an array, like `curlOptions=( )`. See “mocha”-software-labels. ## v8.0 From 0cdc780a5f19b689aace7556a66273e92c4b98cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Tue, 11 Jan 2022 19:06:50 +0100 Subject: [PATCH 16/76] Update checkLabels.sh --- utils/checkLabels.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/utils/checkLabels.sh b/utils/checkLabels.sh index 33025ed..b1a55f6 100755 --- a/utils/checkLabels.sh +++ b/utils/checkLabels.sh @@ -97,16 +97,19 @@ YELLOW='\033[1;33m' BLUE='\033[1;34m' NC='\033[0m' # No Color -# Labels with the $(arch) call for different versions for Intel and Apple Silicon should be listed here: -archLabels=( $(grep "\$(arch)" ${labels_dir}/* | awk '{print $1}' | sed -E 's/.*\/([a-z0-9\_-]*)\..*/\1/g'| uniq ) ) -echo "${BLUE}Labels with \"\$(arch)\" call:${NC}\n${archLabels}\n" - +# Has label(s) been given as arguments or not, and list those +# Figure out which ones of these include "${arch}" so those will be testet for both architectures if [[ $# -eq 0 ]]; then allLabels=( $(grep -h -E '^([a-z0-9\_-]*)(\)|\|\\)$' ${labels_dir}/*.sh | tr -d ')|\\' | sort) ) + archLabels=( $(grep "\$(arch)" ${labels_dir}/* | awk '{print $1}' | sed -E 's/.*\/([a-z0-9\_-]*)\..*/\1/g'| uniq ) ) else allLabels=( ${=@} ) + # Next line needs to be improved to only look through the labels given as arguments + archLabels=( $(grep "\$(arch)" ${labels_dir}/* | awk '{print $1}' | sed -E 's/.*\/([a-z0-9\_-]*)\..*/\1/g'| uniq ) ) fi echo "${BLUE}Total labels:${NC}\n${allLabels}\n" +echo "${BLUE}Labels with \"\$(arch)\" call:${NC}\n${archLabels}\n" + secondRoundLabels="" # variable for labels with $(arch) call in them countWarning=0 From 36b7148e308b806f9cb10cd6fc8f8c76eded7ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Tue, 11 Jan 2022 20:39:53 +0100 Subject: [PATCH 17/76] Update checkLabels.sh --- utils/checkLabels.sh | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/utils/checkLabels.sh b/utils/checkLabels.sh index b1a55f6..5c080da 100755 --- a/utils/checkLabels.sh +++ b/utils/checkLabels.sh @@ -98,19 +98,32 @@ BLUE='\033[1;34m' NC='\033[0m' # No Color # Has label(s) been given as arguments or not, and list those -# Figure out which ones of these include "${arch}" so those will be testet for both architectures +# Figure out which ones of these include "$(arch)" so those will be testet for both i386 and arm64 architectures if [[ $# -eq 0 ]]; then allLabels=( $(grep -h -E '^([a-z0-9\_-]*)(\)|\|\\)$' ${labels_dir}/*.sh | tr -d ')|\\' | sort) ) archLabels=( $(grep "\$(arch)" ${labels_dir}/* | awk '{print $1}' | sed -E 's/.*\/([a-z0-9\_-]*)\..*/\1/g'| uniq ) ) else allLabels=( ${=@} ) - # Next line needs to be improved to only look through the labels given as arguments - archLabels=( $(grep "\$(arch)" ${labels_dir}/* | awk '{print $1}' | sed -E 's/.*\/([a-z0-9\_-]*)\..*/\1/g'| uniq ) ) + # Check if labels exist + for checkLabel in $allLabels; do + if [ ! $(ls ${labels_dir}/${checkLabel}.sh 2>/dev/null) ] ; then + # Remove label from array + allLabels=("${(@)allLabels:#$checkLabel}") + fi + done + # Figure out if labels has "$(arch)" in them + archLabels=( $allLabels ) + for checkLabel in $archLabels; do + if [ ! -n "$(grep "\$(arch)" ${labels_dir}/${checkLabel}.sh 2>/dev/null)" ] ; then + # Remove label from array + archLabels=("${(@)archLabels:#$checkLabel}") + fi + done fi + echo "${BLUE}Total labels:${NC}\n${allLabels}\n" echo "${BLUE}Labels with \"\$(arch)\" call:${NC}\n${archLabels}\n" - secondRoundLabels="" # variable for labels with $(arch) call in them countWarning=0 countError=0 From 6f229b0b8cf74a1d813c025e98e882daf7e87d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Tue, 11 Jan 2022 21:38:49 +0100 Subject: [PATCH 18/76] Update buildLabel.sh --- utils/buildLabel.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/buildLabel.sh b/utils/buildLabel.sh index 3dd8a5d..b5ca79f 100755 --- a/utils/buildLabel.sh +++ b/utils/buildLabel.sh @@ -231,7 +231,7 @@ then else echo "Success on this download." succesDownloadOut=$downloadOut - return + break 2 fi fi done From 504e8528cef75cd64fdcec5f75b060fc29b75a35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Tue, 11 Jan 2022 22:56:38 +0100 Subject: [PATCH 19/76] Update checkLabels.sh --- utils/checkLabels.sh | 61 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/utils/checkLabels.sh b/utils/checkLabels.sh index 5c080da..a06c155 100755 --- a/utils/checkLabels.sh +++ b/utils/checkLabels.sh @@ -125,13 +125,17 @@ echo "${BLUE}Total labels:${NC}\n${allLabels}\n" echo "${BLUE}Labels with \"\$(arch)\" call:${NC}\n${archLabels}\n" secondRoundLabels="" # variable for labels with $(arch) call in them +warningLabels="" # variable for labels with warnings +errorLabels="" # variable for labels with errors countWarning=0 countError=0 + +# Loop through the 2 architectures for fixedArch in i386 arm64; do echo "${BLUE}Architecture: $fixedArch${NC}" echo -# Go through all labels +# Loop through all labels for label in $allLabels; do echo "########## $label" labelWarning=0; labelError=0; expectedExtension=""; URLextension="" @@ -211,8 +215,21 @@ for label in $allLabels; do echo "${RED}-> !! ERROR in downloadURL${NC}" labelError=1 fi - if [[ $labelWarning != 0 ]]; then; echo "${YELLOW}########## Warning in label: $label${NC}"; ((countWarning++)); fi - if [[ $labelError != 0 ]]; then; echo "${RED}########## ERROR in label: $label${NC}"; ((countError++)); fi + if [[ $labelWarning != 0 ]]; then; echo "${YELLOW}########## Warning in label: $label${NC}"; ((countWarning++)); warningLabels+=( "$label" ); fi + if [[ $labelError != 0 ]]; then + echo "${RED}########## ERROR in label: $label${NC}" + echo "Testing using Installomator" + exit_status=$( . $repo_dir/assemble.sh $label DEBUG=2 INSTALL=force | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) + if [[ ${exit_status} -eq 0 ]] ; then + echo "${GREEN}$label works fine!${NC}" + #errorLabels=("${(@)errorLabels:#$errorLabel}") + else + echo "${RED}$label NOT WORKING!${NC}" + ((countError++)) + errorLabels+=( "$label" ) + fi + + fi if (($archLabels[(Ie)$label])); then secondRoundLabels+=( "$label" ) @@ -222,10 +239,45 @@ for label in $allLabels; do fi echo done +# check errorLabels using Installomator +#echo "Testing – $errorLabels – using Installomator" +#if [[ countError > 0 ]]; then +# allLabels=( ${=errorLabels} ) +# for errorLabel in $errorLabels; do +# exit_status=$( . $repo_dir/assemble.sh $errorLabel DEBUG=2 INSTALL=force | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) +# if [[ ${exit_status} -eq 0 ]] ; then +# echo "$errorLabel works fine" +# errorLabels=("${(@)errorLabels:#$errorLabel}") +# ((countError--)) +# fi +# done +#fi +if [[ $fixedArch == i386 ]] ; then + errorLabelsi386=( ${=errorLabels} ) +else + errorLabelsarm64=( ${=errorLabels} ) +fi +#eval errorLabels${fixedArch}="${errorLabels}" +errorLabels="" allLabels=( ${=secondRoundLabels} ) archLabels=() echo done +#errorLabels${fixedArch}=(${=errorLabels}) +# check errorLabels using Installomator +#echo "Testing – $errorLabels – using Installomator" +#if [[ countError > 0 ]]; then +# allLabels=( ${=errorLabels} ) +# for errorLabel in $errorLabels; do +# exit_status=$( . $repo_dir/assemble.sh $errorLabel DEBUG=2 INSTALL=force | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) +# if [[ ${exit_status} -eq 0 ]] ; then +# echo "$errorLabel works fine" +# errorLabels=("${(@)errorLabels:#$errorLabel}") +# ((countError--)) +# fi +# done +#fi +#errorLabels2=( ${=errorLabels} ) rm checkLabelCurrent.sh @@ -234,11 +286,14 @@ rm checkLabelCurrent.sh if [[ countWarning > 0 ]]; then echo "${YELLOW}Warnings counted: $countWarning${NC}" + echo "${YELLOW}${warningLabels}${NC}" else echo "${GREEN}No warnings detected!${NC}" fi if [[ countError > 0 ]]; then echo "${RED}ERRORS counted: $countError${NC}" + echo "${RED}i386 : ${errorLabelsi386}${NC}" + echo "${RED}arm64: ${errorLabelsarm64}${NC}" else echo "${GREEN}No errors detected!${NC}" fi From 901ea4babd302bcebded8d11362112ef90c6017d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Tue, 11 Jan 2022 23:03:51 +0100 Subject: [PATCH 20/76] Update checkLabels.sh --- utils/checkLabels.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/checkLabels.sh b/utils/checkLabels.sh index a06c155..cb56173 100755 --- a/utils/checkLabels.sh +++ b/utils/checkLabels.sh @@ -219,7 +219,7 @@ for label in $allLabels; do if [[ $labelError != 0 ]]; then echo "${RED}########## ERROR in label: $label${NC}" echo "Testing using Installomator" - exit_status=$( . $repo_dir/assemble.sh $label DEBUG=2 INSTALL=force | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) + exit_status=$( . $repo_dir/assemble.sh $label DEBUG=2 INSTALL=force BLOCKING_PROCESS_ACTION=ignore | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) if [[ ${exit_status} -eq 0 ]] ; then echo "${GREEN}$label works fine!${NC}" #errorLabels=("${(@)errorLabels:#$errorLabel}") From cd0204bb044cc50dbce6794d8f7b21a641628f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Tue, 11 Jan 2022 23:05:53 +0100 Subject: [PATCH 21/76] Update checkLabels.sh --- utils/checkLabels.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/checkLabels.sh b/utils/checkLabels.sh index cb56173..cf776f8 100755 --- a/utils/checkLabels.sh +++ b/utils/checkLabels.sh @@ -284,13 +284,13 @@ rm checkLabelCurrent.sh #${SELFLOCATION}/Installomator.sh version #echo -if [[ countWarning > 0 ]]; then +if [[ countWarning -gt 0 ]]; then echo "${YELLOW}Warnings counted: $countWarning${NC}" echo "${YELLOW}${warningLabels}${NC}" else echo "${GREEN}No warnings detected!${NC}" fi -if [[ countError > 0 ]]; then +if [[ countError -gt 0 ]]; then echo "${RED}ERRORS counted: $countError${NC}" echo "${RED}i386 : ${errorLabelsi386}${NC}" echo "${RED}arm64: ${errorLabelsarm64}${NC}" From 4df1a6dbaa6298909ead63d96492235d5a2febe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Tue, 11 Jan 2022 23:39:55 +0100 Subject: [PATCH 22/76] canva and logitechoptions labels fixed --- fragments/labels/canva.sh | 8 +++++--- fragments/labels/logitechoptions.sh | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/fragments/labels/canva.sh b/fragments/labels/canva.sh index f399d77..9e89ac9 100644 --- a/fragments/labels/canva.sh +++ b/fragments/labels/canva.sh @@ -2,10 +2,12 @@ canva) name="Canva" type="dmg" if [[ $(arch) == "arm64" ]]; then - downloadURL=$(curl -fsLI -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" -H "accept-encoding: gzip, deflate, br" -H "accept-language: en-US,en;q=0.9" -H "Referrer Policy: strict-origin-when-cross-origin" -H "upgrade-insecure-requests: 1" -H "sec-fetch-dest: document" -H "sec-gpc: 1" -H "sec-fetch-user: ?1" -H "sec-fetch-mode: navigate" -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" "https://www.canva.com/download/mac/arm/canva-desktop/" | grep -i "^location" | cut -d " " -f2 | tr -d '\r') + downloadURL=https://desktop-release.canva.com/$(curl -fs https://desktop-release.canva.com/latest-mac.yml | grep -e "url.*dmg" | grep -oe "Canva-[0-9.]*-arm64.dmg") + # https://www.canva.com/download/mac/arm/canva-desktop/ elif [[ $(arch) == "i386" ]]; then - downloadURL=$(curl -fsLI -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" -H "accept-encoding: gzip, deflate, br" -H "Referrer Policy: strict-origin-when-cross-origin" -H "upgrade-insecure-requests: 1" -H "sec-fetch-dest: document" -H "sec-gpc: 1" -H "sec-fetch-user: ?1" -H "accept-language: en-US,en;q=0.9" -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" -H "sec-fetch-mode: navigate" "https://www.canva.com/download/mac/intel/canva-desktop/" | grep -i "^location" | cut -d " " -f2 | tr -d '\r') + downloadURL=https://desktop-release.canva.com/$(curl -fs https://desktop-release.canva.com/latest-mac.yml | grep -e "url.*dmg" | grep -oe "Canva-[0-9.]*.dmg") + # https://www.canva.com/download/mac/intel/canva-desktop/ fi - appNewVersion=$( echo "${downloadURL}" | sed -E 's/.*\/[a-zA-Z]*-([0-9.]*)\..*/\1/g' ) + appNewVersion=$( curl -fs https://desktop-release.canva.com/latest-mac.yml | grep version | cut -d " " -f2 ) expectedTeamID="5HD2ARTBFS" ;; diff --git a/fragments/labels/logitechoptions.sh b/fragments/labels/logitechoptions.sh index 98bdf6b..c3cf225 100644 --- a/fragments/labels/logitechoptions.sh +++ b/fragments/labels/logitechoptions.sh @@ -1,8 +1,8 @@ logitechoptions) name="Logitech Options" type="pkgInZip" - downloadURL=$(curl -fs https://support.logi.com/api/v2/help_center/en-us/articles.json | tr "," "\n" | grep -A 10 "macOS" | grep -oie "https.*/.*/options.*\.zip") - appNewVersion=$(curl -fs https://support.logi.com/api/v2/help_center/en-us/articles.json | tr "," "\n" | grep -A 10 "macOS" | grep -B 5 -ie "https.*/.*/options.*\.zip" | grep "Software Version" | sed 's/\\u[0-9a-z][0-9a-z][0-9a-z][0-9a-z]//g' | grep -ioe "Software Version.*[0-9.]*" | tr "/" "\n" | grep -oe "[0-9.]*" | head -1) + downloadURL=$(curl -fs https://support.logi.com/api/v2/help_center/en-us/articles.json | tr "," "\n" | grep -A 10 "macOS" | grep -oie "https.*/.*/options/.*\.zip") + appNewVersion=$(curl -fs https://support.logi.com/api/v2/help_center/en-us/articles.json | tr "," "\n" | grep -A 10 "macOS" | grep -B 5 -ie "https.*/.*/options/.*\.zip" | grep "Software Version" | sed 's/\\u[0-9a-z][0-9a-z][0-9a-z][0-9a-z]//g' | grep -ioe "Software Version.*[0-9.]*" | tr "/" "\n" | grep -oe "[0-9.]*" | head -1) #pkgName="LogiMgr Installer "*".app/Contents/Resources/LogiMgr.pkg" pkgName=LogiMgr.pkg expectedTeamID="QED4VVPZWA" From 0fc7761fb9a21000b5ba9e3403561ac2c5d2389c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 12 Jan 2022 09:26:46 +0100 Subject: [PATCH 23/76] Label fixed --- fragments/labels/evernote.sh | 2 +- fragments/labels/golang.sh | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/fragments/labels/evernote.sh b/fragments/labels/evernote.sh index 85253e6..e65fe95 100644 --- a/fragments/labels/evernote.sh +++ b/fragments/labels/evernote.sh @@ -1,7 +1,7 @@ evernote) name="Evernote" type="dmg" - downloadURL=$(curl -fs -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15)" "https://evernote.com/download" | grep -i ".dmg" | cut -d '"' -f2) + downloadURL=$(curl -fs -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15)" "https://evernote.com/download" | grep -i ".dmg" | grep -ioe "href.*" | cut -d '"' -f2) appNewVersion=$( echo "${downloadURL}" | sed -E 's/.*\/[a-zA-Z]*-([0-9.]*)-.*/\1/g' ) expectedTeamID="Q79WDW8YH9" appName="Evernote.app" diff --git a/fragments/labels/golang.sh b/fragments/labels/golang.sh index 81b81f9..007c423 100644 --- a/fragments/labels/golang.sh +++ b/fragments/labels/golang.sh @@ -1,10 +1,9 @@ golang) - # credit: Søren Theilgaard (@theilgaard) name="GoLang" type="pkg" packageID="org.golang.go" - downloadURL="$(curl -fsIL "https://golang.org$(curl -fs "https://golang.org/dl/" | grep -i "downloadBox" | grep "pkg" | tr '"' '\n' | grep "pkg")" | grep -i "^location" | awk '{print $2}' | tr -d '\r\n')" - appNewVersion="$( echo "${downloadURL}" | sed -E 's/.*\/(go[0-9.]*)\..*/\1/g' )" # Version includes letters "go" + downloadURL="https://go.dev$(curl -fs "https://go.dev/dl/" | grep -i "downloadBox" | grep "pkg" | tr '"' '\n' | grep "pkg")" + appNewVersion="$( echo "${downloadURL}" | sed -E 's/.*\/(go[0-9.]*)\..*/\1/g' )" # Version includes letters "go" in the beginning expectedTeamID="EQHXZ8M8AV" blockingProcesses=( NONE ) ;; From c8071a2a63881582e91787bf681b20352a014b5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 12 Jan 2022 12:48:45 +0100 Subject: [PATCH 24/76] Create diskspace.sh --- fragments/labels/diskspace.sh | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 fragments/labels/diskspace.sh diff --git a/fragments/labels/diskspace.sh b/fragments/labels/diskspace.sh new file mode 100644 index 0000000..ab8f88c --- /dev/null +++ b/fragments/labels/diskspace.sh @@ -0,0 +1,8 @@ +diskspace) + name="diskspace" + type="pkg" + packageID="com.scriptingosx.diskspace" + downloadURL="$(downloadURLFromGit scriptingosx diskspace)" + appNewVersion="$(versionFromGit scriptingosx diskspace)" + expectedTeamID="JME5BW3F3R" + ;; From da21ea85824af465ebff25168e7bd29dd0674cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 12 Jan 2022 12:53:07 +0100 Subject: [PATCH 25/76] Update checkLabels.sh Need `INSTAL=force` and `IGNORE_APP_STORE_APPS=yes` to be able test any title on any system. --- utils/checkLabels.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/checkLabels.sh b/utils/checkLabels.sh index cf776f8..eeba7a2 100755 --- a/utils/checkLabels.sh +++ b/utils/checkLabels.sh @@ -219,7 +219,7 @@ for label in $allLabels; do if [[ $labelError != 0 ]]; then echo "${RED}########## ERROR in label: $label${NC}" echo "Testing using Installomator" - exit_status=$( . $repo_dir/assemble.sh $label DEBUG=2 INSTALL=force BLOCKING_PROCESS_ACTION=ignore | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) + exit_status=$( . $repo_dir/assemble.sh $label DEBUG=2 INSTALL=force IGNORE_APP_STORE_APPS=yes BLOCKING_PROCESS_ACTION=ignore | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) if [[ ${exit_status} -eq 0 ]] ; then echo "${GREEN}$label works fine!${NC}" #errorLabels=("${(@)errorLabels:#$errorLabel}") From a36e9fce43b8f09d076264b11cd0b9b4e9744163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 12 Jan 2022 13:53:48 +0100 Subject: [PATCH 26/76] Isaac Logging Improvements to logging: - Logging levels as DEBUG 0 INFO 1 WARN 2 ERROR 3 REQ 4 - External logging to Datadog - A function to shorten duplicate lines in installation logs - Ability to extract install.log in the time when Installomator was running, if further investigations needs to be done to logs --- CHANGELOG.md | 6 +++ fragments/functions.sh | 99 +++++++++++++++++++++++++++++++++++++++--- fragments/header.sh | 37 ++++++++++++++++ 3 files changed, 137 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dd2a79..c2843dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ - Changed logic if `IGNORE_APP_STORE_APPS=yes`. Before this version a label like `microsoftonedrive` that was installed from App Store, and that we want to replace with the “ordinary” version, Installomator would still use `updateTool`, even though `IGNORE_APP_STORE_APPS=yes`. So we would have to have `INSTALL=force` in order to have the app replaced, as `updateTool` would be used. But now if `IGNORE_APP_STORE_APPS=yes` then `updateTool` will be not set, and the App Store app will be replaced. BUT if the installed software was not from App Store, then `updateTool` will not be used, and it would be a kind of a forced install (in the example of `microsoftonedrive`), except if the version is the same (where installation is skipped). - Added variable `SYSTEMOWNER` that is used when copying files when installing. Default `0` is to change owner of the app to the current user on the Mac, like this user was installing this app themselves. When using `1` we will put “root:wheel” on the app, which can be useful for shared machines. +Big changes to logging: +- Logging levels as DEBUG 0 INFO 1 WARN 2 ERROR 3 REQ 4 +- External logging to Datadog +- A function to shorten duplicate lines in installation logs +- Ability to extract install.log in the time when Installomator was running, if further investigations needs to be done to logs + ## v8.0 - removed leading `0` from the version because it has lost all meaning (thanks to @grahampugh for the inspiration) diff --git a/fragments/functions.sh b/fragments/functions.sh index 0908662..dd20375 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -67,15 +67,104 @@ displaynotification() { # $1: message $2: title # MARK: Logging log_location="/private/var/log/Installomator.log" -printlog(){ +# Check if we're in debug mode, if so then set logging to DEBUG, otherwise default to INFO +# if no log level is specified. +if [[ $DEBUG -ne 0 ]]; then + LOGGING=DEBUG +elif [[ -z $LOGGING ]]; then + LOGGING=INFO + datadogLoggingLevel=INFO +fi +# Associate logging levels with a numerical value so that we are able to identify what +# should be removed. For example if the LOGGING=ERROR only printlog statements with the +# level REQ and ERROR will be displayed. LOGGING=DEBUG will show all printlog statements. +# If a printlog statement has no level set it's automatically assigned INFO. + +declare -A levels=(DEBUG 0 INFO 1 WARN 2 ERROR 3 REQ 4) + +# If we are able to detect an MDM URL (Jamf Pro) or another identifier for a customer/instance we grab it here, this is useful if we're centrally logging multiple MDM instances. +if [[ -f /Library/Preferences/com.jamfsoftware.jamf.plist ]]; then + mdmURL=$(defaults read /Library/Preferences/com.jamfsoftware.jamf.plist jss_url) +elif [[ -n "$MDMProfileName" ]]; then + mdmURL=$(sudo profiles show | grep -A3 "$MDMProfileName" | sed -n -e 's/^.*organization: //p') +else + mdmURL="Unknown" +fi + +# Generate a session key for this run, this is useful to idenify streams when we're centrally logging. +SESSION=$RANDOM + +printlog(){ + [ -z "$2" ] && 2=INFO + log_message=$1 + log_priority=$2 timestamp=$(date +%F\ %T) - if [[ "$(whoami)" == "root" ]]; then - echo "$timestamp" "$label" "$1" | tee -a $log_location - else - echo "$timestamp" "$label" "$1" + # Check to make sure that the log isn't the same as the last, if it is then don't log and increment a timer. + if [[ ${log_message} == ${previous_log_message} ]];then + let logrepeat=$logrepeat+1 + return fi + + previous_log_message=$log_message + + # Once we finally stop getting duplicate logs output the number of times we got a duplicate. + if [[ $logrepeat -gt 1 ]];then + echo "$timestamp" : "${log_priority} : ${VERSIONDATE//-/} : Last Log repeated ${logrepeat} times" | tee -a $log_location + + if [[ ! -z $datadogAPI ]]; then + curl -s -X POST https://http-intake.logs.datadoghq.com/v1/input -H "Content-Type: text/plain" -H "DD-API-KEY: $datadogAPI" -d "${log_priority} : $mdmURL : $APPLICATION : $VERSIONDATE : $SESSION : Last Log repeated ${logrepeat} times" > /dev/null + fi + logrepeat=0 + + # If the datadogAPI key value is set and our logging level is greaterthan or equal to our set level + # then post to Datadog's HTTPs endpoint. + if [[ -n $datadogAPI && ${levels[$log_priority]} -ge ${levels[$datadogLoggingLevel]} ]]; then + while IFS= read -r logmessage; do + curl -s -X POST https://http-intake.logs.datadoghq.com/v1/input -H "Content-Type: text/plain" -H "DD-API-KEY: $datadogAPI" -d "${log_priority} : $mdmURL : Installomator-${label} : ${VERSIONDATE//-/} : $SESSION : ${logmessage}" > /dev/null + done <<< "$log_message" + fi + + # If our logging level is greaterthan or equal to our set level then output locally. + if [[ ${levels[$log_priority]} -ge ${levels[$LOGGING]} ]]; then + while IFS= read -r logmessage; do + if [[ "$(whoami)" == "root" ]]; then + echo "$timestamp" : "${log_priority} : ${VERSIONDATE//-/} : ${logmessage}" | tee -a $log_location + else + echo "$timestamp" : "${log_priority} : ${VERSIONDATE//-/} : ${logmessage}" + fi + done <<< "$log_message" + fi + +# if [[ "$(whoami)" == "root" ]]; then +# echo "$timestamp" "$label" "$1" | tee -a $log_location +# else +# echo "$timestamp" "$label" "$1" +# fi +} + +# Used to remove dupplicate lines in large log output, for example from msupdate command +# after it finishes running. +deduplicatelogs() { + loginput=${1:-"Log"} + logoutput="" + # Read each line of the incoming log individually, match it with the previous. + # If it matches increment logrepeate then skip to the next line. + while read log; do + if [[ $log == $previous_log ]];then + let logrepeat=$logrepeat+1 + continue + fi + + previous_log="$log" + if [[ $logrepeat -gt 1 ]];then + logoutput+="Last Log repeated ${logrepeat} times\n" + logrepeat=0 + fi + + logoutput+="$log\n" + done <<< "$loginput" } # will get the latest release download from a github repo diff --git a/fragments/header.sh b/fragments/header.sh index 36f8500..27bc57f 100644 --- a/fragments/header.sh +++ b/fragments/header.sh @@ -239,3 +239,40 @@ REOPEN="yes" # installer that should be located after mounting/expanding the downloaded archive. # See label adobecreativeclouddesktop # +### Logging +# Logging behavior +LOGGING="" +# options: +# - DEBUG Everything is logged +# - INFO (default) normal logging level +# - WARN only warning +# - ERROR only errors +# - REQ ???? + +# MDM profile name +MDMProfileName="" +# options: +# - MDM Profile Addigy has this name on the profile +# - Mosyle Corporation MDM Mosyle uses this name on the profile +# From the LOGO variable we can know if Addigy og Mosyle is used, so if that variable +# is either of these, and this variable is empty, then we can will auto detect this. + +# Datadog logging used +datadogAPI="" +# Simply add your own API key for this in order to have logs sent to Datadog +# See more here: https://www.datadoghq.com/product/log-management/ + +# Log Date format used when parsing logs for debugging, this is the default used by +# install.log, override this in the case statements if you need something custom per +# application (See adobeillustrator). Using stadard GNU Date formatting. +LogDateFormat="%Y-%m-%d %H:%M:%S" + +# Get the start time for parsing install.log if we fail. +starttime=$(date "+$LogDateFormat") + +# Check if we have rosetta installed +if [[ $(/usr/bin/arch) == "arm64" ]]; then + if ! arch -x86_64 /usr/bin/true >/dev/null 2>&1; then # pgrep oahd >/dev/null 2>&1 + rosetta2=no + fi +fi From c0ce59a1ec81e09e8a86122c0f8570cd8a729ab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 12 Jan 2022 13:55:40 +0100 Subject: [PATCH 27/76] Update functions.sh --- fragments/functions.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fragments/functions.sh b/fragments/functions.sh index dd20375..c7184be 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -113,10 +113,11 @@ printlog(){ if [[ $logrepeat -gt 1 ]];then echo "$timestamp" : "${log_priority} : ${VERSIONDATE//-/} : Last Log repeated ${logrepeat} times" | tee -a $log_location - if [[ ! -z $datadogAPI ]]; then - curl -s -X POST https://http-intake.logs.datadoghq.com/v1/input -H "Content-Type: text/plain" -H "DD-API-KEY: $datadogAPI" -d "${log_priority} : $mdmURL : $APPLICATION : $VERSIONDATE : $SESSION : Last Log repeated ${logrepeat} times" > /dev/null + if [[ ! -z $datadogAPI ]]; then + curl -s -X POST https://http-intake.logs.datadoghq.com/v1/input -H "Content-Type: text/plain" -H "DD-API-KEY: $datadogAPI" -d "${log_priority} : $mdmURL : $APPLICATION : $VERSIONDATE : $SESSION : Last Log repeated ${logrepeat} times" > /dev/null + fi + logrepeat=0 fi - logrepeat=0 # If the datadogAPI key value is set and our logging level is greaterthan or equal to our set level # then post to Datadog's HTTPs endpoint. From 180ca0952baf69584dfc03d30e732cde477572db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 12 Jan 2022 14:03:30 +0100 Subject: [PATCH 28/76] Update checkLabels.sh --- utils/checkLabels.sh | 231 +++++++++++++++++++------------------------ 1 file changed, 100 insertions(+), 131 deletions(-) diff --git a/utils/checkLabels.sh b/utils/checkLabels.sh index eeba7a2..fa6144b 100755 --- a/utils/checkLabels.sh +++ b/utils/checkLabels.sh @@ -3,7 +3,7 @@ export PATH=/usr/bin:/bin:/usr/sbin:/sbin # Check Installomator labels from fragments -# 2021 Søren Theilgaard (@theilgaard) +# 2021-2022 Søren Theilgaard (@theilgaard) # This script will test labels and check if download link is active, and if version is defined. # If labels are written to the script only those will be tested. @@ -132,158 +132,127 @@ countError=0 # Loop through the 2 architectures for fixedArch in i386 arm64; do -echo "${BLUE}Architecture: $fixedArch${NC}" -echo + echo "${BLUE}Architecture: $fixedArch${NC}" + echo -# Loop through all labels -for label in $allLabels; do - echo "########## $label" - labelWarning=0; labelError=0; expectedExtension=""; URLextension="" - name=""; type=""; downloadURL=""; curlOptions=""; appNewVersion=""; expectedTeamID=""; blockingProcesses=""; updateTool=""; updateToolArguments=""; archiveName="" - - #caseLabel - if cat "${labels_dir}/${label}.sh" | grep -v -E '^[a-z0-9\_-]*(\)|\|\\)$' | grep -v ";;" > checkLabelCurrent.sh; then - source checkLabelCurrent.sh + # Loop through all labels + for label in $allLabels; do + echo "########## $label" + labelWarning=0; labelError=0; expectedExtension=""; URLextension="" + name=""; type=""; downloadURL=""; curlOptions=""; appNewVersion=""; expectedTeamID=""; blockingProcesses=""; updateTool=""; updateToolArguments=""; archiveName="" + + #caseLabel + if cat "${labels_dir}/${label}.sh" | grep -v -E '^[a-z0-9\_-]*(\)|\|\\)$' | grep -v ";;" > checkLabelCurrent.sh; then + source checkLabelCurrent.sh - echo "Name: $name" - echo "Download URL: $downloadURL" - echo "Type: $type" - case $type in - dmg|pkg|zip|tbz) - expectedExtension="$type" - ;; - pkgInDmg) - expectedExtension="dmg" - ;; - *InZip) - expectedExtension="zip" - ;; - *) - echo "Cannot handle type $type" - ;; - esac - if [[ "$appNewVersion" == "" ]] ; then - echo "No appNewVersion!" - else - if [[ $( echo "$appNewVersion" | grep -i "[0-9.]" ) == "" || $appNewVersion == "" ]]; then - echo "${RED}-> !! ERROR in appNewVersion${NC}" - labelError=1 + echo "Name: $name" + echo "Download URL: $downloadURL" + echo "Type: $type" + case $type in + dmg|pkg|zip|tbz) + expectedExtension="$type" + ;; + pkgInDmg) + expectedExtension="dmg" + ;; + *InZip) + expectedExtension="zip" + ;; + *) + echo "Cannot handle type $type" + ;; + esac + if [[ "$appNewVersion" == "" ]] ; then + echo "No appNewVersion!" else - if [[ $appNewVersion != $( echo "$appNewVersion" | sed -E 's/[^0-9]*([0-9.]*)[^0-9]*/\1/g' ) ]]; then - echo "${YELLOW}Warning: Version contain not only numbers and dots.${NC}" - labelWarning=1 + if [[ $( echo "$appNewVersion" | grep -i "[0-9.]" ) == "" || $appNewVersion == "" ]]; then + echo "${RED}-> !! ERROR in appNewVersion${NC}" + labelError=1 + else + if [[ $appNewVersion != $( echo "$appNewVersion" | sed -E 's/[^0-9]*([0-9.]*)[^0-9]*/\1/g' ) ]]; then + echo "${YELLOW}Warning: Version contain not only numbers and dots.${NC}" + labelWarning=1 + fi + echo "Version: $appNewVersion" ; fi - echo "Version: $appNewVersion" ; fi - fi - if curl -sfL ${curlOptions} --output /dev/null -r 0-0 "$downloadURL" ; then - echo "${GREEN}OK: downloadURL works OK${NC}" - if [[ $(echo "$downloadURL" | sed -E 's/.*\.([a-zA-Z]*)\s*/\1/g' ) == "${expectedExtension}" ]]; then - echo "${GREEN}OK: download extension MATCH on ${expectedExtension}${NC}" - else - if [[ $(echo "$downloadURL" | grep -io "github.com") != "github.com" ]]; then - URLheader=$( curl -fsIL "$downloadURL" ) - if [[ "${URLheader}" != "" ]]; then - URLlocation=$( echo "${URLheader}" | grep -i "^location" ) - URLfilename=$( echo "${URLheader}" | grep -i "filename=" ) - if [[ "${URLlocation}" != "" ]]; then - URLextension=$( echo "${URLlocation}" | tail -1 | sed -E 's/.*\.([a-zA-Z]*)\s*/\1/g' | tr -d '\r\n' ) + if curl -sfL ${curlOptions} --output /dev/null -r 0-0 "$downloadURL" ; then + echo "${GREEN}OK: downloadURL works OK${NC}" + if [[ $(echo "$downloadURL" | sed -E 's/.*\.([a-zA-Z]*)\s*/\1/g' ) == "${expectedExtension}" ]]; then + echo "${GREEN}OK: download extension MATCH on ${expectedExtension}${NC}" + else + if [[ $(echo "$downloadURL" | grep -io "github.com") != "github.com" ]]; then + URLheader=$( curl -fsIL "$downloadURL" ) + if [[ "${URLheader}" != "" ]]; then + URLlocation=$( echo "${URLheader}" | grep -i "^location" ) + URLfilename=$( echo "${URLheader}" | grep -i "filename=" ) + if [[ "${URLlocation}" != "" ]]; then + URLextension=$( echo "${URLlocation}" | tail -1 | sed -E 's/.*\.([a-zA-Z]*)\s*/\1/g' | tr -d '\r\n' ) + else + URLextension=$( echo "${URLfilename}" | tail -1 | sed -E 's/.*\.([a-zA-Z]*)\s*/\1/g' | tr -d '\r\n' ) + fi + URLextension=${${URLextension:l}%%\?*} + if [[ "${URLextension}" == "${expectedExtension}" ]]; then + echo "${GREEN}OK: download extension MATCH on ${URLextension}${NC}" + else + echo "${RED}-> !! ERROR in download extension, expected ${expectedExtension}, but got ${URLextension}.${NC}" + labelError=1 + fi else - URLextension=$( echo "${URLfilename}" | tail -1 | sed -E 's/.*\.([a-zA-Z]*)\s*/\1/g' | tr -d '\r\n' ) + echo "no header provided from server." fi - URLextension=${${URLextension:l}%%\?*} - if [[ "${URLextension}" == "${expectedExtension}" ]]; then - echo "${GREEN}OK: download extension MATCH on ${URLextension}${NC}" + else + githubPart="$(echo "$downloadURL" | cut -d "/" -f4-6)" + if [[ "$(curl -fsL "$downloadURL" | grep -io "${githubPart}.*\.${expectedExtension}")" != "" ]]; then + echo "${GREEN}OK: download extension MATCH on ${expectedExtension}${NC}" else - echo "${RED}-> !! ERROR in download extension, expected ${expectedExtension}, but got ${URLextension}.${NC}" + echo "${RED}-> !! ERROR in download extension, expected ${expectedExtension}, but it was wrong${NC}" labelError=1 fi - else - echo "no header provided from server." - fi - else - githubPart="$(echo "$downloadURL" | cut -d "/" -f4-6)" - if [[ "$(curl -fsL "$downloadURL" | grep -io "${githubPart}.*\.${expectedExtension}")" != "" ]]; then - echo "${GREEN}OK: download extension MATCH on ${expectedExtension}${NC}" - else - echo "${RED}-> !! ERROR in download extension, expected ${expectedExtension}, but it was wrong${NC}" - labelError=1 fi fi + else + echo "${RED}-> !! ERROR in downloadURL${NC}" + labelError=1 + fi + if [[ $labelWarning != 0 ]]; then; echo "${YELLOW}########## Warning in label: $label${NC}"; ((countWarning++)); warningLabels+=( "$label" ); fi + if [[ $labelError != 0 ]]; then + echo "${RED}########## ERROR in label: $label${NC}" + echo "Testing using Installomator" + exit_status=$( . $repo_dir/assemble.sh $label DEBUG=2 INSTALL=force IGNORE_APP_STORE_APPS=yes BLOCKING_PROCESS_ACTION=ignore | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) + if [[ ${exit_status} -eq 0 ]] ; then + echo "${GREEN}$label works fine!${NC}" + #errorLabels=("${(@)errorLabels:#$errorLabel}") + else + echo "${RED}$label NOT WORKING!${NC}" + ((countError++)) + errorLabels+=( "$label" ) + fi + + fi + + if (($archLabels[(Ie)$label])); then + secondRoundLabels+=( "$label" ) fi else - echo "${RED}-> !! ERROR in downloadURL${NC}" - labelError=1 - fi - if [[ $labelWarning != 0 ]]; then; echo "${YELLOW}########## Warning in label: $label${NC}"; ((countWarning++)); warningLabels+=( "$label" ); fi - if [[ $labelError != 0 ]]; then - echo "${RED}########## ERROR in label: $label${NC}" - echo "Testing using Installomator" - exit_status=$( . $repo_dir/assemble.sh $label DEBUG=2 INSTALL=force IGNORE_APP_STORE_APPS=yes BLOCKING_PROCESS_ACTION=ignore | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) - if [[ ${exit_status} -eq 0 ]] ; then - echo "${GREEN}$label works fine!${NC}" - #errorLabels=("${(@)errorLabels:#$errorLabel}") - else - echo "${RED}$label NOT WORKING!${NC}" - ((countError++)) - errorLabels+=( "$label" ) - fi - - fi - - if (($archLabels[(Ie)$label])); then - secondRoundLabels+=( "$label" ) + echo "Label: ${label} is not it's own file in Labels-folder. Skipping" fi + echo + done + if [[ $fixedArch == i386 ]] ; then + errorLabelsi386=( ${=errorLabels} ) else - echo "Label: ${label} is not it's own file in Labels-folder. Skipping" + errorLabelsarm64=( ${=errorLabels} ) fi + + errorLabels="" + allLabels=( ${=secondRoundLabels} ) + archLabels=() echo done -# check errorLabels using Installomator -#echo "Testing – $errorLabels – using Installomator" -#if [[ countError > 0 ]]; then -# allLabels=( ${=errorLabels} ) -# for errorLabel in $errorLabels; do -# exit_status=$( . $repo_dir/assemble.sh $errorLabel DEBUG=2 INSTALL=force | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) -# if [[ ${exit_status} -eq 0 ]] ; then -# echo "$errorLabel works fine" -# errorLabels=("${(@)errorLabels:#$errorLabel}") -# ((countError--)) -# fi -# done -#fi -if [[ $fixedArch == i386 ]] ; then - errorLabelsi386=( ${=errorLabels} ) -else - errorLabelsarm64=( ${=errorLabels} ) -fi -#eval errorLabels${fixedArch}="${errorLabels}" -errorLabels="" -allLabels=( ${=secondRoundLabels} ) -archLabels=() -echo -done -#errorLabels${fixedArch}=(${=errorLabels}) -# check errorLabels using Installomator -#echo "Testing – $errorLabels – using Installomator" -#if [[ countError > 0 ]]; then -# allLabels=( ${=errorLabels} ) -# for errorLabel in $errorLabels; do -# exit_status=$( . $repo_dir/assemble.sh $errorLabel DEBUG=2 INSTALL=force | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) -# if [[ ${exit_status} -eq 0 ]] ; then -# echo "$errorLabel works fine" -# errorLabels=("${(@)errorLabels:#$errorLabel}") -# ((countError--)) -# fi -# done -#fi -#errorLabels2=( ${=errorLabels} ) rm checkLabelCurrent.sh -#${SELFLOCATION}/Installomator.sh version -#echo - if [[ countWarning -gt 0 ]]; then echo "${YELLOW}Warnings counted: $countWarning${NC}" echo "${YELLOW}${warningLabels}${NC}" From 99b908f646065bd62d84fb9c078038a203707af2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 12 Jan 2022 21:34:16 +0100 Subject: [PATCH 29/76] Logging --- fragments/functions.sh | 115 ++++++++++++++++++++++++++++------------- fragments/main.sh | 14 +++-- 2 files changed, 90 insertions(+), 39 deletions(-) diff --git a/fragments/functions.sh b/fragments/functions.sh index c7184be..5540875 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -1,23 +1,24 @@ # MARK: Functions -cleanupAndExit() { # $1 = exit code, $2 message - if [[ -n $2 && $1 -ne 0 ]]; then - printlog "ERROR: $2" - fi +cleanupAndExit() { # $1 = exit code, $2 message, $3 level if [ "$DEBUG" -ne 1 ]; then # remove the temporary working directory when done - printlog "Deleting $tmpDir" + printlog "Deleting $tmpDir" DEBUG rm -Rf "$tmpDir" fi if [ -n "$dmgmount" ]; then # unmount disk image - printlog "Unmounting $dmgmount" + printlog "Unmounting $dmgmount" DEBUG hdiutil detach "$dmgmount" fi # If we closed any processes, reopen the app again reopenClosedProcess - printlog "################## End Installomator, exit code $1 \n\n" + if [[ -n $2 && $1 -ne 0 ]]; then + printlog "ERROR: $2" $3 + fi + printlog "################## End Installomator, exit code $1 \n\n" REQ + # if label is wrong and we wanted name of the label, then return ################## if [[ $RETURN_LABEL_NAME -eq 1 ]]; then echo "#" @@ -294,7 +295,7 @@ getAppVersion() { checkRunningProcesses() { # don't check in DEBUG mode 1 if [[ $DEBUG -eq 1 ]]; then - printlog "DEBUG mode 1, not checking for blocking processes" + printlog "DEBUG mode 1, not checking for blocking processes" DEBUG return fi @@ -386,7 +387,7 @@ checkRunningProcesses() { cleanupAndExit 11 "could not quit all processes, aborting..." fi - printlog "no more blocking processes, continue with update" + printlog "no more blocking processes, continue with update" REQ } reopenClosedProcess() { @@ -401,7 +402,7 @@ reopenClosedProcess() { # don't reopen in DEBUG mode 1 if [[ $DEBUG -eq 1 ]]; then - printlog "DEBUG mode 1, not reopening anything" + printlog "DEBUG mode 1, not reopening anything" DEBUG return fi @@ -428,15 +429,21 @@ installAppWithPath() { # $1: path to app to install in $targetDir fi # verify with spctl - printlog "Verifying: $appPath" - if ! teamID=$(spctl -a -vv "$appPath" 2>&1 | awk '/origin=/ {print $NF }' | tr -d '()' ); then - cleanupAndExit 4 "Error verifying $appPath" + printlog "Verifying: $appPath" INFO + appVerify=$(spctl -a -vv "$appPath" 2>&1 ) + appVerifyStatus=$(echo $?) + teamID=$(echo $appVerify | awk '/origin=/ {print $NF }' | tr -d '()' ) + deduplicatelogs "$appVerify" + printlog "Debugging enabled, App Verification output was: $logoutput" DEBUG + + if [[ $appVerifyStatus -ne 0 ]] ; then + #if ! teamID=$(spctl -a -vv "$appPath" 2>&1 | awk '/origin=/ {print $NF }' | tr -d '()' ); then + cleanupAndExit 4 "Error verifying $appPath error: $logoutput" ERROR fi - - printlog "Team ID matching: $teamID (expected: $expectedTeamID )" + printlog "Team ID matching: $teamID (expected: $expectedTeamID )" INFO if [ "$expectedTeamID" != "$teamID" ]; then - cleanupAndExit 5 "Team IDs do not match" + cleanupAndExit 5 "Team IDs do not match" ERROR fi # app versioncheck @@ -474,13 +481,13 @@ installAppWithPath() { # $1: path to app to install in $targetDir # skip install for DEBUG 1 if [ "$DEBUG" -eq 1 ]; then - printlog "DEBUG mode 1 enabled, skipping remove, copy and chown steps" + printlog "DEBUG mode 1 enabled, skipping remove, copy and chown steps" DEBUG return 0 fi # skip install for DEBUG 2 if [ "$DEBUG" -eq 2 ]; then - printlog "DEBUG mode 2 enabled, exiting" + printlog "DEBUG mode 2 enabled, exiting" DEBUG cleanupAndExit 0 fi @@ -551,24 +558,26 @@ installFromPKG() { # verify with spctl printlog "Verifying: $archiveName" - if ! spctlout=$(spctl -a -vv -t install "$archiveName" 2>&1 ); then - printlog "Error verifying $archiveName" - cleanupAndExit 4 + spctlOut=$(spctl -a -vv -t install "$archiveName" 2>&1 ) + spctlStatus=$(echo $?) + printlog "spctlOut is $spctlOut" DEBUG + teamID=$(echo $spctlOut | awk -F '(' '/origin=/ {print $2 }' | tr -d '()' ) + deduplicatelogs "$spctlOut" # Why this? + + if [[ $spctlStatus -ne 0 ]] ; then + #if ! spctlout=$(spctl -a -vv -t install "$archiveName" 2>&1 ); then + cleanupAndExit 4 "Error verifying $archiveName error: $logoutput" ERROR fi - teamID=$(echo $spctlout | awk -F '(' '/origin=/ {print $2 }' | tr -d '()' ) - # Apple signed software has no teamID, grab entire origin instead if [[ -z $teamID ]]; then teamID=$(echo $spctlout | awk -F '=' '/origin=/ {print $NF }') fi - printlog "Team ID: $teamID (expected: $expectedTeamID )" if [ "$expectedTeamID" != "$teamID" ]; then - printlog "Team IDs do not match!" - cleanupAndExit 5 + cleanupAndExit 5 "Team IDs do not match!" ERROR fi # Check version of pkg to be installed if packageID is set @@ -597,22 +606,39 @@ installFromPKG() { # skip install for DEBUG 1 if [ "$DEBUG" -eq 1 ]; then - printlog "DEBUG enabled, skipping installation" + printlog "DEBUG enabled, skipping installation" DEBUG return 0 fi # skip install for DEBUG 2 if [ "$DEBUG" -eq 2 ]; then - printlog "DEBUG mode 2 enabled, exiting" - cleanupAndExit 0 + cleanupAndExit 0 "DEBUG mode 2 enabled, exiting" DEBUG fi # install pkg printlog "Installing $archiveName to $targetDir" - if ! installer -pkg "$archiveName" -tgt "$targetDir" ; then - printlog "error installing $archiveName" - cleanupAndExit 9 + pkgInstall=$(installer -verbose -dumplog -pkg "$archiveName" -tgt "$targetDir" 2>&1) + pkgInstallStatus=$(echo $?) + sleep 1 + pkgEndTime=$(date "+$LogDateFormat") + pkgInstall+=$(echo "Output of /var/log/install.log below this line.\n") + pkgInstall+=$(echo "----------------------------------------------------------\n") + pkgInstall+=$(awk -v "b=$starttime" -v "e=$pkgEndTime" -F ',' '$1 >= b && $1 <= e' /var/log/install.log) + deduplicatelogs "$pkgInstall" + + if [[ $pkgInstallStatus -ne 0 ]] && [[ $logoutput == *"requires Rosetta 2"* ]] && [[ $rosetta2 == no ]]; then + printlog "Package requires Rosetta 2, Installing Rosetta 2 and Installing Package" INFO + /usr/sbin/softwareupdate --install-rosetta --agree-to-license + rosetta2=yes + installFromPKG fi + + if [ $pkginstallstatus -ne 0 ] ; then + #if ! installer -pkg "$archiveName" -tgt "$targetDir" ; then + cleanupAndExit 9 "Error installing $archiveName error: $logoutput" ERROR + + fi + printlog "Debugging enabled, installer output was: $logoutput" DEBUG } installFromZIP() { @@ -738,12 +764,29 @@ runUpdateTool() { if [[ -x $updateTool ]]; then printlog "running $updateTool $updateToolArguments" if [[ -n $updateToolRunAsCurrentUser ]]; then - runAsUser $updateTool ${updateToolArguments} + updateOutput=$(runAsUser $updateTool ${updateToolArguments} 2>&1) + updateStatus=$(echo $?) else - $updateTool ${updateToolArguments} + updateOutput=$($updateTool ${updateToolArguments} 2>&1) + updateStatus=$(echo $?) fi - if [[ $? -ne 0 ]]; then - cleanupAndExit 15 "Error running $updateTool" + sleep 1 + updateEndTime=$(date "+$updateToolLogDateFormat") + deduplicatelogs $updateOutput + if [[ -n $updateToolLog ]]; then + updateOutput+=$(echo "Output of Installer log of $updateToolLog below this line.\n") + updateOutput+=$(echo "----------------------------------------------------------\n") + updateOutput+=$(awk -v "b=$updatestarttime" -v "e=$updateEndTime" -F ',' '$1 >= b && $1 <= e' $updateToolLog) + fi + + if [[ $updateStatus -ne 0 ]]; then + printlog "Error running $updateTool, Procceding with normal installation. Exit Status: $updateStatus Error: $logoutput" WARN + return 1 + if [[ $type == updateronly ]]; then + cleanupAndExit 77 "No Download URL Set, this is an update only application and the updater failed" WARN + fi + elif [[ $updateStatus -eq 0 ]]; then + printlog "Debugging enabled, update tool output was: $logoutput" DEBUG fi else printlog "couldn't find $updateTool, continuing normally" diff --git a/fragments/main.sh b/fragments/main.sh index cef364c..e8bc2bf 100644 --- a/fragments/main.sh +++ b/fragments/main.sh @@ -35,14 +35,17 @@ case $LOGO in mosyleb) # Mosyle Business LOGO="/Applications/Self-Service.app/Contents/Resources/AppIcon.icns" + if [[ -z $MDMProfileName ]]; then; MDMProfileName="Mosyle Corporation MDM"; fi ;; mosylem) # Mosyle Manager (education) LOGO="/Applications/Manager.app/Contents/Resources/AppIcon.icns" + if [[ -z $MDMProfileName ]]; then; MDMProfileName="Mosyle Corporation MDM"; fi ;; addigy) # Addigy LOGO="/Library/Addigy/macmanage/MacManage.app/Contents/Resources/atom.icns" + if [[ -z $MDMProfileName ]]; then; MDMProfileName="MDM Profile"; fi ;; esac if [[ ! -a "${LOGO}" ]]; then @@ -112,7 +115,7 @@ else fi # MARK: change directory to temporary working directory -printlog "Changing directory to $tmpDir" +printlog "Changing directory to $tmpDir" DEBUG if ! cd "$tmpDir"; then printlog "error changing directory $tmpDir" cleanupAndExit 1 @@ -178,7 +181,12 @@ else displaynotification "Downloading new $name" "Download in progress …" fi fi - if ! curl --location --fail --silent "$downloadURL" -o "$archiveName"; then + curlDownload=$(curl -v -fsL --show-error "$downloadURL" -o "$archiveName" 2>&1) + curlDownloadStatus=$(echo $?) + deduplicatelogs "$curlDownload" + printlog "curl output was: $logoutput" DEBUG + if [[ $curlDownloadStatus -ne 0 ]]; then + #if ! curl --location --fail --silent "$downloadURL" -o "$archiveName"; then printlog "error downloading $downloadURL" message="$name update/installation failed. This will be logged, so IT can follow up." if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then @@ -189,7 +197,7 @@ else displaynotification "$message" "Error installing $name" fi fi - cleanupAndExit 2 + cleanupAndExit 2 "Error downloading $downloadURL error: $logoutput" ERROR fi fi From f96cd178c6abf0186bd5341bd3212454a24a43a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Thu, 13 Jan 2022 09:44:34 +0100 Subject: [PATCH 30/76] CLIInstaller included and a few other displaylog lines changed --- CHANGELOG.md | 10 ++++++++-- fragments/functions.sh | 41 +++++++++++++++++++++++------------------ fragments/header.sh | 2 +- fragments/main.sh | 12 ++++++------ 4 files changed, 38 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2843dd..f08aa97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,15 @@ - Added variable `SYSTEMOWNER` that is used when copying files when installing. Default `0` is to change owner of the app to the current user on the Mac, like this user was installing this app themselves. When using `1` we will put “root:wheel” on the app, which can be useful for shared machines. Big changes to logging: -- Logging levels as DEBUG 0 INFO 1 WARN 2 ERROR 3 REQ 4 +- Introducing variable `LOGGING`, that can be either of the logging levels +- Logging levels: + 0: DEBUG Everything is logged + 1: INFO Normal logging behavior + 2: WARN + 3: ERROR + 4: REQ - External logging to Datadog -- A function to shorten duplicate lines in installation logs +- A function to shorten duplicate lines in installation logs or output of longer commands - Ability to extract install.log in the time when Installomator was running, if further investigations needs to be done to logs ## v8.0 diff --git a/fragments/functions.sh b/fragments/functions.sh index 5540875..3960e39 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -415,7 +415,7 @@ reopenClosedProcess() { processuser=$(ps aux | grep -i "${appName}" | grep -vi "grep" | awk '{print $1}') printlog "Reopened ${appName} as $processuser" else - printlog "App not closed, so no reopen." + printlog "App not closed, so no reopen." DEBUG fi } @@ -434,12 +434,12 @@ installAppWithPath() { # $1: path to app to install in $targetDir appVerifyStatus=$(echo $?) teamID=$(echo $appVerify | awk '/origin=/ {print $NF }' | tr -d '()' ) deduplicatelogs "$appVerify" - printlog "Debugging enabled, App Verification output was: $logoutput" DEBUG - + if [[ $appVerifyStatus -ne 0 ]] ; then #if ! teamID=$(spctl -a -vv "$appPath" 2>&1 | awk '/origin=/ {print $NF }' | tr -d '()' ); then cleanupAndExit 4 "Error verifying $appPath error: $logoutput" ERROR fi + printlog "Debugging enabled, App Verification output was: $logoutput" DEBUG printlog "Team ID matching: $teamID (expected: $expectedTeamID )" INFO if [ "$expectedTeamID" != "$teamID" ]; then @@ -511,24 +511,24 @@ installAppWithPath() { # $1: path to app to install in $targetDir printlog "Changing owner to $currentUser" chown -R "$currentUser" "$targetDir/$appName" else - printlog "No user logged in or SYSTEMOWNER=1, setting owner to root:wheel" + printlog "No user logged in or SYSTEMOWNER=1, setting owner to root:wheel" chown -R root:wheel "$targetDir/$appName" fi elif [[ ! -z $CLIInstaller ]]; then mountname=$(dirname $appPath) - printlog "CLIInstaller exists, running installer command $mountname/$CLIInstaller $CLIArguments" #INFO + printlog "CLIInstaller exists, running installer command $mountname/$CLIInstaller $CLIArguments" INFO CLIoutput=$("$mountname/$CLIInstaller" "${CLIArguments[@]}" 2>&1) CLIstatus=$(echo $?) - logoutput="$CLIoutput" # dedupliatelogs "$CLIoutput" + dedupliatelogs "$CLIoutput" if [ $CLIstatus -ne 0 ] ; then - cleanupAndExit 3 "Error installing $mountname/$CLIInstaller $CLIArguments error:\n$logoutput" #ERROR + cleanupAndExit 3 "Error installing $mountname/$CLIInstaller $CLIArguments error: $logoutput" ERROR else - printlog "Succesfully ran $mountname/$CLIInstaller $CLIArguments" + printlog "Succesfully ran $mountname/$CLIInstaller $CLIArguments" INFO fi - printlog "Debugging enabled, update tool output was:\n$logoutput" #DEBUG + printlog "Debugging enabled, update tool output was: $logoutput" DEBUG fi } @@ -537,16 +537,22 @@ mountDMG() { # mount the dmg printlog "Mounting $tmpDir/$archiveName" # always pipe 'Y\n' in case the dmg requires an agreement - if ! dmgmount=$(echo 'Y'$'\n' | hdiutil attach "$tmpDir/$archiveName" -nobrowse -readonly | tail -n 1 | cut -c 54- ); then - cleanupAndExit 3 "Error mounting $tmpDir/$archiveName" + dmgmountOut=$(echo 'Y'$'\n' | hdiutil attach "$tmpDir/$archiveName" -nobrowse -readonly ) + dmgmountStatus=$(echo $?) + dmgmount=$(echo $dmgmountOut | tail -n 1 | cut -c 54- ) + printlog "dmgmountOut is $dmgmountOut" DEBUG + deduplicatelogs "$dmgmountOut" + + if [[ $dmgmountStatus -ne 0 ]] ; then + #if ! dmgmount=$(echo 'Y'$'\n' | hdiutil attach "$tmpDir/$archiveName" -nobrowse -readonly | tail -n 1 | cut -c 54- ); then + cleanupAndExit 3 "Error mounting $tmpDir/$archiveName error: $logoutput" ERROR fi - if [[ ! -e $dmgmount ]]; then - printlog "Error mounting $tmpDir/$archiveName" - cleanupAndExit 3 + cleanupAndExit 3 "Error accessing mountpoint for $tmpDir/$archiveName error: $logoutput" ERROR fi - - printlog "Mounted: $dmgmount" + printlog "Debugging enabled, installer output was: $logoutput" DEBUG + + printlog "Mounted: $dmgmount" INFO } installFromDMG() { @@ -562,7 +568,7 @@ installFromPKG() { spctlStatus=$(echo $?) printlog "spctlOut is $spctlOut" DEBUG teamID=$(echo $spctlOut | awk -F '(' '/origin=/ {print $2 }' | tr -d '()' ) - deduplicatelogs "$spctlOut" # Why this? + deduplicatelogs "$spctlOut" if [[ $spctlStatus -ne 0 ]] ; then #if ! spctlout=$(spctl -a -vv -t install "$archiveName" 2>&1 ); then @@ -636,7 +642,6 @@ installFromPKG() { if [ $pkginstallstatus -ne 0 ] ; then #if ! installer -pkg "$archiveName" -tgt "$targetDir" ; then cleanupAndExit 9 "Error installing $archiveName error: $logoutput" ERROR - fi printlog "Debugging enabled, installer output was: $logoutput" DEBUG } diff --git a/fragments/header.sh b/fragments/header.sh index 27bc57f..fbd926b 100644 --- a/fragments/header.sh +++ b/fragments/header.sh @@ -255,7 +255,7 @@ MDMProfileName="" # - MDM Profile Addigy has this name on the profile # - Mosyle Corporation MDM Mosyle uses this name on the profile # From the LOGO variable we can know if Addigy og Mosyle is used, so if that variable -# is either of these, and this variable is empty, then we can will auto detect this. +# is either of these, and this variable is empty, then we will auto detect this. # Datadog logging used datadogAPI="" diff --git a/fragments/main.sh b/fragments/main.sh index e8bc2bf..35723f6 100644 --- a/fragments/main.sh +++ b/fragments/main.sh @@ -172,7 +172,7 @@ if [ -f "$archiveName" ] && [ "$DEBUG" -eq 1 ]; then printlog "$archiveName exists and DEBUG mode 1 enabled, skipping download" else # download the dmg - printlog "Downloading $downloadURL to $archiveName" + printlog "Downloading $downloadURL to $archiveName" REQ if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then printlog "notifying" if [[ $updateDetected == "YES" ]]; then @@ -181,7 +181,7 @@ else displaynotification "Downloading new $name" "Download in progress …" fi fi - curlDownload=$(curl -v -fsL --show-error "$downloadURL" -o "$archiveName" 2>&1) + curlDownload=$(curl -v -fsL --show-error ${curlOptions} "$downloadURL" -o "$archiveName" 2>&1) curlDownloadStatus=$(echo $?) deduplicatelogs "$curlDownload" printlog "curl output was: $logoutput" DEBUG @@ -192,9 +192,9 @@ else if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then printlog "notifying" if [[ $updateDetected == "YES" ]]; then - displaynotification "$message" "Error updating $name" + displaynotification "$message" "Error updating $name" ERROR else - displaynotification "$message" "Error installing $name" + displaynotification "$message" "Error installing $name" ERROR fi fi cleanupAndExit 2 "Error downloading $downloadURL error: $logoutput" ERROR @@ -215,7 +215,7 @@ else fi # MARK: install the download -printlog "Installing $name" +printlog "Installing $name" REQ if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then printlog "notifying" if [[ $updateDetected == "YES" ]]; then @@ -227,7 +227,7 @@ fi if [ -n "$installerTool" ]; then # installerTool defined, and we use that for installation - printlog "installerTool used: $installerTool" + printlog "installerTool used: $installerTool" REQ appName="$installerTool" fi From 82faf74eb301a0ce99205ba74d7d08819d223a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Thu, 13 Jan 2022 14:12:51 +0100 Subject: [PATCH 31/76] Update functions.sh --- fragments/functions.sh | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/fragments/functions.sh b/fragments/functions.sh index 3960e39..fdbd066 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -190,8 +190,7 @@ downloadURLFromGit() { # $1 git user name, $2 git repo name | awk -F '"' "/browser_download_url/ && /$filetype\"/ { print \$4; exit }") fi if [ -z "$downloadURL" ]; then - cleanupAndExit 9 "could not retrieve download URL for $gitusername/$gitreponame" - #exit 9 + cleanupAndExit 9 "could not retrieve download URL for $gitusername/$gitreponame" ERROR else echo "$downloadURL" return 0 @@ -259,9 +258,9 @@ getAppVersion() { applist=$(mdfind "kind:application $appName" -0 ) fi if [[ -z applist ]]; then - printlog "No previous app found" + printlog "No previous app found" DEBUG else - printlog "App(s) found: ${applist}" + printlog "App(s) found: ${applist}" DEBUG fi appPathArray=( ${(0)applist} ) @@ -281,7 +280,7 @@ getAppVersion() { printlog "Replacing App Store apps, no matter the version" appversion=0 else - cleanupAndExit 1 "App previously installed from App Store, and we respect that" + cleanupAndExit 1 "App previously installed from App Store, and we respect that" ERROR fi fi else @@ -328,7 +327,7 @@ checkRunningProcesses() { prompt_user|prompt_user_then_kill) button=$(displaydialog "Quit “$x” to continue updating? (Leave this dialogue if you want to activate this update later)." "The application “$x” needs to be updated.") if [[ $button = "Not Now" ]]; then - cleanupAndExit 10 "user aborted update" + cleanupAndExit 10 "user aborted update" ERROR else if [[ $i > 2 && $BLOCKING_PROCESS_ACTION = "prompt_user_then_kill" ]]; then printlog "Changing BLOCKING_PROCESS_ACTION to kill" @@ -373,7 +372,7 @@ checkRunningProcesses() { fi ;; silent_fail) - cleanupAndExit 12 "blocking process '$x' found, aborting" + cleanupAndExit 12 "blocking process '$x' found, aborting" ERROR ;; esac @@ -384,7 +383,7 @@ checkRunningProcesses() { done if [[ $countedProcesses -ne 0 ]]; then - cleanupAndExit 11 "could not quit all processes, aborting..." + cleanupAndExit 11 "could not quit all processes, aborting..." ERROR fi printlog "no more blocking processes, continue with update" REQ @@ -425,7 +424,7 @@ installAppWithPath() { # $1: path to app to install in $targetDir # check if app exists if [ ! -e "$appPath" ]; then - cleanupAndExit 8 "could not find: $appPath" + cleanupAndExit 8 "could not find: $appPath" DEBUG fi # verify with spctl @@ -456,7 +455,7 @@ installAppWithPath() { # $1: path to app to install in $targetDir printlog "notifying" displaynotification "$message" "No update for $name!" fi - cleanupAndExit 0 "No new version to install" + cleanupAndExit 0 "No new version to install" INFO else printlog "Using force to install anyway." fi @@ -475,7 +474,7 @@ installAppWithPath() { # $1: path to app to install in $targetDir printlog "notifying" displaynotification "$message" "Error updating $name!" fi - cleanupAndExit 6 "Installed macOS is too old for this app." + cleanupAndExit 6 "Installed macOS is too old for this app." INFO fi fi @@ -496,14 +495,14 @@ installAppWithPath() { # $1: path to app to install in $targetDir # remove existing application if [ -e "$targetDir/$appName" ]; then - printlog "Removing existing $targetDir/$appName" + printlog "Removing existing $targetDir/$appName" DEBUG rm -Rf "$targetDir/$appName" fi # copy app to /Applications printlog "Copy $appPath to $targetDir" if ! ditto "$appPath" "$targetDir/$appName"; then - cleanupAndExit 7 "Error while copying" + cleanupAndExit 7 "Error while copying" ERROR fi # set ownership to current user @@ -603,7 +602,7 @@ installFromPKG() { printlog "notifying" displaynotification "$message" "No update for $name!" fi - cleanupAndExit 0 "No new version to install" + cleanupAndExit 0 "No new version to install" INFO else printlog "Using force to install anyway." fi @@ -679,7 +678,7 @@ installPkgInDmg() { findfiles=$(find "$dmgmount" -iname "*.pkg" -maxdepth 1 ) filearray=( ${(f)findfiles} ) if [[ ${#filearray} -eq 0 ]]; then - cleanupAndExit 20 "couldn't find pkg in dmg $archiveName" + cleanupAndExit 20 "couldn't find pkg in dmg $archiveName" ERROR fi archiveName="${filearray[1]}" printlog "found pkg: $archiveName" @@ -691,7 +690,7 @@ installPkgInDmg() { findfiles=$(find "$tmpDir" -iname "$pkgName") filearray=( ${(f)findfiles} ) if [[ ${#filearray} -eq 0 ]]; then - cleanupAndExit 20 "couldn't find pkg “$pkgName” in zip $archiveName" + cleanupAndExit 20 "couldn't find pkg “$pkgName” in zip $archiveName" ERROR fi # it is now safe to overwrite archiveName for installFromPKG archiveName="${filearray[1]}" @@ -714,7 +713,7 @@ installPkgInZip() { findfiles=$(find "$tmpDir" -iname "*.pkg" -maxdepth 2 ) filearray=( ${(f)findfiles} ) if [[ ${#filearray} -eq 0 ]]; then - cleanupAndExit 20 "couldn't find pkg in zip $archiveName" + cleanupAndExit 20 "couldn't find pkg in zip $archiveName" ERROR fi # it is now safe to overwrite archiveName for installFromPKG archiveName="${filearray[1]}" @@ -727,7 +726,7 @@ installPkgInZip() { findfiles=$(find "$tmpDir" -iname "$pkgName") filearray=( ${(f)findfiles} ) if [[ ${#filearray} -eq 0 ]]; then - cleanupAndExit 20 "couldn't find pkg “$pkgName” in zip $archiveName" + cleanupAndExit 20 "couldn't find pkg “$pkgName” in zip $archiveName" ERROR fi # it is now safe to overwrite archiveName for installFromPKG archiveName="${filearray[1]}" @@ -750,7 +749,7 @@ installAppInDmgInZip() { findfiles=$(find "$tmpDir" -iname "*.dmg" -maxdepth 2 ) filearray=( ${(f)findfiles} ) if [[ ${#filearray} -eq 0 ]]; then - cleanupAndExit 20 "couldn't find dmg in zip $archiveName" + cleanupAndExit 20 "couldn't find dmg in zip $archiveName" ERROR fi archiveName="$(basename ${filearray[1]})" # it is now safe to overwrite archiveName for installFromDMG From 7f2bdfb1df92c62f53592a9d6ab5d7157b8c1467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Thu, 13 Jan 2022 21:52:15 +0100 Subject: [PATCH 32/76] Local logging improvements Improved first lines of logs to be required and show `VERSION` and `VERSIONDATE` on separate lines. Logging sent to Datadog will have `VERSION` on each line. --- fragments/arguments.sh | 8 +++++--- fragments/functions.sh | 14 ++++---------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/fragments/arguments.sh b/fragments/arguments.sh index 6c01519..ea6e9db 100644 --- a/fragments/arguments.sh +++ b/fragments/arguments.sh @@ -43,12 +43,14 @@ if [[ $label == "version" ]]; then exit 0 fi -printlog "################## Start Installomator v. $VERSION" -printlog "################## $label" +printlog "################## Start Installomator" REQ +printlog "################## Version: $VERSION" REQ +printlog "################## Date: $VERSIONDATE" REQ +printlog "################## $label" REQ # Check for DEBUG mode if [[ $DEBUG -gt 0 ]]; then - printlog "DEBUG mode $DEBUG enabled." + printlog "DEBUG mode $DEBUG enabled." DEBUG fi # How we get version number from app diff --git a/fragments/functions.sh b/fragments/functions.sh index fdbd066..5e0ea55 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -112,10 +112,10 @@ printlog(){ # Once we finally stop getting duplicate logs output the number of times we got a duplicate. if [[ $logrepeat -gt 1 ]];then - echo "$timestamp" : "${log_priority} : ${VERSIONDATE//-/} : Last Log repeated ${logrepeat} times" | tee -a $log_location + echo "$timestamp" : "${log_priority} : Last Log repeated ${logrepeat} times" | tee -a $log_location if [[ ! -z $datadogAPI ]]; then - curl -s -X POST https://http-intake.logs.datadoghq.com/v1/input -H "Content-Type: text/plain" -H "DD-API-KEY: $datadogAPI" -d "${log_priority} : $mdmURL : $APPLICATION : $VERSIONDATE : $SESSION : Last Log repeated ${logrepeat} times" > /dev/null + curl -s -X POST https://http-intake.logs.datadoghq.com/v1/input -H "Content-Type: text/plain" -H "DD-API-KEY: $datadogAPI" -d "${log_priority} : $mdmURL : $APPLICATION : $VERSION : $SESSION : Last Log repeated ${logrepeat} times" > /dev/null fi logrepeat=0 fi @@ -132,18 +132,12 @@ printlog(){ if [[ ${levels[$log_priority]} -ge ${levels[$LOGGING]} ]]; then while IFS= read -r logmessage; do if [[ "$(whoami)" == "root" ]]; then - echo "$timestamp" : "${log_priority} : ${VERSIONDATE//-/} : ${logmessage}" | tee -a $log_location + echo "$timestamp" : "${log_priority} : ${logmessage}" | tee -a $log_location else - echo "$timestamp" : "${log_priority} : ${VERSIONDATE//-/} : ${logmessage}" + echo "$timestamp" : "${log_priority} : ${logmessage}" fi done <<< "$log_message" fi - -# if [[ "$(whoami)" == "root" ]]; then -# echo "$timestamp" "$label" "$1" | tee -a $log_location -# else -# echo "$timestamp" "$label" "$1" -# fi } # Used to remove dupplicate lines in large log output, for example from msupdate command From fee93947516536f75754b3f86e72c3a580ab1cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Fri, 14 Jan 2022 10:02:00 +0100 Subject: [PATCH 33/76] Few more DEBUG loggings --- fragments/functions.sh | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/fragments/functions.sh b/fragments/functions.sh index 5e0ea55..cb20292 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -4,13 +4,15 @@ cleanupAndExit() { # $1 = exit code, $2 message, $3 level if [ "$DEBUG" -ne 1 ]; then # remove the temporary working directory when done printlog "Deleting $tmpDir" DEBUG - rm -Rf "$tmpDir" + deleteTmpOut=$(rm -Rfv "$tmpDir") + printlog "Debugging enabled, Deleting tmpDir output was:\n$deleteTmpOut" DEBUG fi if [ -n "$dmgmount" ]; then # unmount disk image printlog "Unmounting $dmgmount" DEBUG - hdiutil detach "$dmgmount" + unmountingOut=$(hdiutil detach "$dmgmount" 2>&1) + printlog "Debugging enabled, Unmounting output was:\n$unmountingOut" DEBUG fi # If we closed any processes, reopen the app again reopenClosedProcess @@ -430,9 +432,9 @@ installAppWithPath() { # $1: path to app to install in $targetDir if [[ $appVerifyStatus -ne 0 ]] ; then #if ! teamID=$(spctl -a -vv "$appPath" 2>&1 | awk '/origin=/ {print $NF }' | tr -d '()' ); then - cleanupAndExit 4 "Error verifying $appPath error: $logoutput" ERROR + cleanupAndExit 4 "Error verifying $appPath error:\n$logoutput" ERROR fi - printlog "Debugging enabled, App Verification output was: $logoutput" DEBUG + printlog "Debugging enabled, App Verification output was:\n$logoutput" DEBUG printlog "Team ID matching: $teamID (expected: $expectedTeamID )" INFO if [ "$expectedTeamID" != "$teamID" ]; then @@ -480,7 +482,7 @@ installAppWithPath() { # $1: path to app to install in $targetDir # skip install for DEBUG 2 if [ "$DEBUG" -eq 2 ]; then - printlog "DEBUG mode 2 enabled, exiting" DEBUG + printlog "DEBUG mode 2 enabled, not installing anything, exiting" DEBUG cleanupAndExit 0 fi @@ -490,7 +492,8 @@ installAppWithPath() { # $1: path to app to install in $targetDir # remove existing application if [ -e "$targetDir/$appName" ]; then printlog "Removing existing $targetDir/$appName" DEBUG - rm -Rf "$targetDir/$appName" + deleteAppOut=$(rm -Rfv "$targetDir/$appName" 2>&1) + printlog "Debugging enabled, App removing output was:\n$deleteAppOut" DEBUG fi # copy app to /Applications @@ -517,11 +520,11 @@ installAppWithPath() { # $1: path to app to install in $targetDir dedupliatelogs "$CLIoutput" if [ $CLIstatus -ne 0 ] ; then - cleanupAndExit 3 "Error installing $mountname/$CLIInstaller $CLIArguments error: $logoutput" ERROR + cleanupAndExit 3 "Error installing $mountname/$CLIInstaller $CLIArguments error:\n$logoutput" ERROR else printlog "Succesfully ran $mountname/$CLIInstaller $CLIArguments" INFO fi - printlog "Debugging enabled, update tool output was: $logoutput" DEBUG + printlog "Debugging enabled, update tool output was:\n$logoutput" DEBUG fi } @@ -538,12 +541,12 @@ mountDMG() { if [[ $dmgmountStatus -ne 0 ]] ; then #if ! dmgmount=$(echo 'Y'$'\n' | hdiutil attach "$tmpDir/$archiveName" -nobrowse -readonly | tail -n 1 | cut -c 54- ); then - cleanupAndExit 3 "Error mounting $tmpDir/$archiveName error: $logoutput" ERROR + cleanupAndExit 3 "Error mounting $tmpDir/$archiveName error:\n$logoutput" ERROR fi if [[ ! -e $dmgmount ]]; then - cleanupAndExit 3 "Error accessing mountpoint for $tmpDir/$archiveName error: $logoutput" ERROR + cleanupAndExit 3 "Error accessing mountpoint for $tmpDir/$archiveName error:\n$logoutput" ERROR fi - printlog "Debugging enabled, installer output was: $logoutput" DEBUG + printlog "Debugging enabled, installer output was:\n$logoutput" DEBUG printlog "Mounted: $dmgmount" INFO } @@ -565,7 +568,7 @@ installFromPKG() { if [[ $spctlStatus -ne 0 ]] ; then #if ! spctlout=$(spctl -a -vv -t install "$archiveName" 2>&1 ); then - cleanupAndExit 4 "Error verifying $archiveName error: $logoutput" ERROR + cleanupAndExit 4 "Error verifying $archiveName error:\n$logoutput" ERROR fi # Apple signed software has no teamID, grab entire origin instead @@ -634,9 +637,9 @@ installFromPKG() { if [ $pkginstallstatus -ne 0 ] ; then #if ! installer -pkg "$archiveName" -tgt "$targetDir" ; then - cleanupAndExit 9 "Error installing $archiveName error: $logoutput" ERROR + cleanupAndExit 9 "Error installing $archiveName error:\n$logoutput" ERROR fi - printlog "Debugging enabled, installer output was: $logoutput" DEBUG + printlog "Debugging enabled, installer output was:\n$logoutput" DEBUG } installFromZIP() { @@ -778,13 +781,13 @@ runUpdateTool() { fi if [[ $updateStatus -ne 0 ]]; then - printlog "Error running $updateTool, Procceding with normal installation. Exit Status: $updateStatus Error: $logoutput" WARN + printlog "Error running $updateTool, Procceding with normal installation. Exit Status: $updateStatus Error:\n$logoutput" WARN return 1 if [[ $type == updateronly ]]; then cleanupAndExit 77 "No Download URL Set, this is an update only application and the updater failed" WARN fi elif [[ $updateStatus -eq 0 ]]; then - printlog "Debugging enabled, update tool output was: $logoutput" DEBUG + printlog "Debugging enabled, update tool output was:\n$logoutput" DEBUG fi else printlog "couldn't find $updateTool, continuing normally" From e4a5f47272bfdb57019ea4996a06f8f2940a70ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Fri, 14 Jan 2022 10:14:29 +0100 Subject: [PATCH 34/76] Label on each log line (again) --- fragments/functions.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fragments/functions.sh b/fragments/functions.sh index cb20292..3c6b17a 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -114,7 +114,7 @@ printlog(){ # Once we finally stop getting duplicate logs output the number of times we got a duplicate. if [[ $logrepeat -gt 1 ]];then - echo "$timestamp" : "${log_priority} : Last Log repeated ${logrepeat} times" | tee -a $log_location + echo "$timestamp" : "${log_priority} : $label : Last Log repeated ${logrepeat} times" | tee -a $log_location if [[ ! -z $datadogAPI ]]; then curl -s -X POST https://http-intake.logs.datadoghq.com/v1/input -H "Content-Type: text/plain" -H "DD-API-KEY: $datadogAPI" -d "${log_priority} : $mdmURL : $APPLICATION : $VERSION : $SESSION : Last Log repeated ${logrepeat} times" > /dev/null @@ -134,9 +134,9 @@ printlog(){ if [[ ${levels[$log_priority]} -ge ${levels[$LOGGING]} ]]; then while IFS= read -r logmessage; do if [[ "$(whoami)" == "root" ]]; then - echo "$timestamp" : "${log_priority} : ${logmessage}" | tee -a $log_location + echo "$timestamp" : "${log_priority} : $label : ${logmessage}" | tee -a $log_location else - echo "$timestamp" : "${log_priority} : ${logmessage}" + echo "$timestamp" : "${log_priority} : $label : ${logmessage}" fi done <<< "$log_message" fi From c98fd8f26cd62a3c1f59aa0ecd34f501e5258295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 17 Jan 2022 09:46:41 +0100 Subject: [PATCH 35/76] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a9e96e..b815d75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ ## v9? - We have moved the root check to the beginning of the script, and improved DEBUG handling with two different modes. `DEBUG=0` is still for production, and `1` is still for the DEBUG we previously knew downloading to the directory it is running from, but `2` will download to temporary folder, will detect updates, but will not install anything, but it will notify the user (almost as running the script without root before). -- Added option to not interrupt Do Not Disturb full screen apps like Keynote or Zoom with `INTERRUPT_DND="no"`. +- Added option to not interrupt Do Not Disturb full screen apps like Keynote or Zoom with `INTERRUPT_DND="no"`. Default is `"yes"` which is how it has worked until now. ## v8.0 From 197b34fe02c118be026cd787905b46c223044dca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 17 Jan 2022 15:40:03 +0100 Subject: [PATCH 36/76] Update buildLabel.sh --- utils/buildLabel.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/buildLabel.sh b/utils/buildLabel.sh index b5ca79f..a6de0c1 100755 --- a/utils/buildLabel.sh +++ b/utils/buildLabel.sh @@ -324,7 +324,7 @@ fi identifier=${name:l} # making lower case identifier=${identifier//\%[0-9a-fA-F][0-9a-fA-F]} # removing certain characters -identifier=${identifier//[,._*@$\(\)\-]} # removing more characters from label name +identifier=${identifier//[ ,._*@$\(\)\-]} # removing more characters from label name echo "identifier: $identifier" # github-part to figure out if we can find author and repo, to use our github functions for the label From 49337a4ae8f48fc7a521f13f1303985ab9bec8bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 19 Jan 2022 14:36:05 +0100 Subject: [PATCH 37/76] `versionKey` improved If `versionKey` is used as part of `valuesfromarguments` it will currently be replaced by our standard value `CFBundleShortVersionString` (it was only testet on labels). So added an `if...then` to know if it was already set as part of the arguments. Also improved logging to show what `versionKey` is. --- fragments/arguments.sh | 5 +++-- fragments/functions.sh | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/fragments/arguments.sh b/fragments/arguments.sh index 6c01519..ea4b471 100644 --- a/fragments/arguments.sh +++ b/fragments/arguments.sh @@ -52,8 +52,9 @@ if [[ $DEBUG -gt 0 ]]; then fi # How we get version number from app -# (alternative is "CFBundleVersion", that can be used in labels) -versionKey="CFBundleShortVersionString" +if [[ -z $versionKey ]]; then + versionKey="CFBundleShortVersionString" +fi # get current user currentUser=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }') diff --git a/fragments/functions.sh b/fragments/functions.sh index 0908662..ebc2a23 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -181,7 +181,7 @@ getAppVersion() { installedAppPath=$filteredAppPaths[1] #appversion=$(mdls -name kMDItemVersion -raw $installedAppPath ) appversion=$(defaults read $installedAppPath/Contents/Info.plist $versionKey) #Not dependant on Spotlight indexing - printlog "found app at $installedAppPath, version $appversion" + printlog "found app at $installedAppPath, version $appversion, on versionKey $versionKey" updateDetected="YES" # Is current app from App Store if [[ -d "$installedAppPath"/Contents/_MASReceipt ]];then @@ -352,7 +352,7 @@ installAppWithPath() { # $1: path to app to install in $targetDir # app versioncheck appNewVersion=$(defaults read $appPath/Contents/Info.plist $versionKey) if [[ -n $appNewVersion && $appversion == $appNewVersion ]]; then - printlog "Downloaded version of $name is $appNewVersion, same as installed." + printlog "Downloaded version of $name is $appNewVersion on versionKey $versionKey, same as installed." if [[ $INSTALL != "force" ]]; then message="$name, version $appNewVersion, is the latest version." if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then @@ -364,7 +364,7 @@ installAppWithPath() { # $1: path to app to install in $targetDir printlog "Using force to install anyway." fi else - printlog "Downloaded version of $name is $appNewVersion (replacing version $appversion)." + printlog "Downloaded version of $name is $appNewVersion on versionKey $versionKey (replacing version $appversion)." fi # macOS versioncheck From 621d6df3467c48b131166b748fc3065eab2532a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Sat, 22 Jan 2022 06:18:00 +0100 Subject: [PATCH 38/76] Update arguments.sh --- fragments/arguments.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fragments/arguments.sh b/fragments/arguments.sh index ea6e9db..a73dafd 100644 --- a/fragments/arguments.sh +++ b/fragments/arguments.sh @@ -43,10 +43,10 @@ if [[ $label == "version" ]]; then exit 0 fi -printlog "################## Start Installomator" REQ -printlog "################## Version: $VERSION" REQ -printlog "################## Date: $VERSIONDATE" REQ -printlog "################## $label" REQ +printlog "################## Start Installomator v. $VERSION, date $VERSIONDATE" REQ +printlog "################## Version: $VERSION" INFO +printlog "################## Date: $VERSIONDATE" INFO +printlog "################## $label" INFO # Check for DEBUG mode if [[ $DEBUG -gt 0 ]]; then From 64a33a7f6ba4f0382991c59336d841de9e9e2cde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 31 Jan 2022 09:49:47 +0100 Subject: [PATCH 39/76] Update README.md --- README.md | 56 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index c9f3ad6..4ec1cc3 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Later on a few more contributers came on the project: ## Support and Contributing -__Please note, that if you are contributing to this project with new labels or other suggestions in PRs, please put your changes in the files below `fragments`-folder. DO NOT edit the full `Installomator.sh` script. The full script is now a build of the fragments, and will be overwritten. See the REAMDME.md file in the `utils` directory for detailed instructions.__ +__Please note, that if you are contributing to this project with new labels or other suggestions in PRs, please put your changes in the files below `fragments`-folder. DO NOT edit the full `Installomator.sh` script. The full script is now a build of the fragments, and will be overwritten. See the [README.md](utils/README.md) file in the `utils` directory for detailed instructions.__ Discussion, support and advice around Installomator happens in the `#installomator` channel in the [MacAdmins.org Slack](https://macadmins.org). Go there for support questions. @@ -34,6 +34,10 @@ Please see [CONTRIBUTING.md](https://github.com/Installomator/Installomator/blob ## More reading +Our wiki: + +- [Wiki](https://github.com/Installomator/Installomator/wiki) + There are a few interesting post on Installomator on Armin’s weblog: - [Introducing Installomator](https://scriptingosx.com/2020/05/introducing-installomator/) @@ -41,23 +45,32 @@ There are a few interesting post on Installomator on Armin’s weblog: ## Background -As a system engineer at [an Apple Authorized Enterprise Reseller](https://prowarehouse.nl), we manage a lot of Jamf instances. +In the world of managing Apple Macs, organizations can have two different approaches to the management. Either the IT department will tightly manage and verify each piece of software, or they will just want the latest software to be deployed as fast as possible. -Some of these instances are tightly managed, i.e. the versions of the operating system and third party software are controlled and updates will only be pushed with the management system when the administration and security team went through an approval process and then the update is automated. This is an important and valid workflow and the right fit for many deployments. +OK, maybe some software should be tightly managed and others not, but you get the point. + +### Tightly managed + +If your solution needs to be tightly managed, i.e. the versions of the operating system and third party software are controlled and updates will only be pushed with the management system when the administration and security team went through an approval process and then the update is automated. This is an important and valid workflow and the right fit for many deployments. Installomator was _not_ written for these kinds of deployment. If you are running this kind of deployment, you want to use [AutoPkg](https://github.com/autopkg/autopkg) and you can stop reading here. -There are other kinds of deployments, though. In these deployments the management system is merely used to "get the user ready" as quickly as possible when they set up a new machine, and to offer software from a self service portal. In these deployments, system and software installations are 'latest version available' and updates are user driven (though we do want to nag them). +### Latest version always -These deployments are +There are other kinds of deployments, though. In these deployments the management system is merely used to “get the user ready” as quickly as possible when they set up a new machine, and to offer software from a self service portal. In these deployments, system and software installations are ‘latest version available’ and updates are user driven (though we do want to nag them and push them). + +Installomator can help with this. + +These deployments can be - user driven - low control - minimal maintenance effort +- latest version is best -These are mostly 'user controlled' Macs and we (the admins) just want to assist the user in doing the right thing. And the right thing is (often) to install the latest versions and updates when they are available. +These can be 'user controlled' Macs and we (the admins) just want to assist the user in doing the right thing. And the right thing is (often) to install the latest versions and updates when they are available. The Mac App Store and software pushed through the Mac App Store follow this approach. When you manage and deploy software through the App Store — whether it is on iOS or macOS — neither the MacAdmin nor the user get a choice of the application version. They will get the latest version. @@ -74,7 +87,15 @@ Some of these disadvantages can be seen as advantages in different setups. When Because this is an attractive solution for _certain kinds_ of deployment, there are already many scripts out there that will download and install the latest version of a given software. And we have built and used quite a few in-house, as well. Most importantly, [William Smith has this script](https://gist.github.com/talkingmoose/a16ca849416ce5ce89316bacd75fc91a) which can be used to install several different Microsoft applications and bundles, because Microsoft has a nice unified URL scheme. -At some point, earlier this year, I got frustrated at the number of scripts we were maintaining (or failing to). Also, my concern that most of the scripts weren't doing _any_ verification of the download was getting unbearable. So, I set out to write the one install script to rule them all... +At some point, in 2018, Armin got frustrated at the number of scripts he was maintaining (or failing to). Also, his concern that most of the scripts weren’t doing _any_ verification of the download was getting unbearable. So, he set out to write _the one install script to rule them all…_ + +### Locally installed + +So Armin made the version for Jamf Pro. + +Søren looked at this, and wanted this approach to work in Mosyle and Addigy, and for these solutions we need Installomator to be locally installed on. the Mac, and then the MDM can call this script from their scripts features. For some time Søren had a version of Installomator that was supplied with a notarized pkg, so it could be deployed as part of DEP or however was needed. + +This has now been merged into Installomator, and with contributions of Isaac and Adam, new features and labels have been added more frequently. ## Goals @@ -84,6 +105,7 @@ The goals for Installomator are: - verify the downloaded archive or application - have a simple ‘interface’ to the admin - single script file so it can ‘easily’ be copied into a management system +- signed and notarized pkg-installer for local installation - extensible without deep scripting knowledge - work independently of a specific management system - no dependencies that may be removed from macOS in the future or are not pre-installed @@ -100,9 +122,9 @@ Installomator can work with the following common archive and installer types: When the download yields a pkg file, Installomator will run `installer` to install it on the current system. -Applications in dmgs or zips will be copied to `/Applications` and their owner will be set to the current user, so the install works like a standard drag'n drop installation. +Applications in dmgs or zips will be copied to `/Applications` and their owner will be set to the current user, so the install works like a standard drag'n drop installation. Owner can also be set to root/wheel. -(I consider it a disgrace, that Jamf, after nearly 20 years, _still_ cannot deal with ‘drag’n drop installation dmgs’ natively. It's not _that_ hard.) +(I consider it a disgrace, that Jamf, after nearly 20 years, _still_ cannot deal with ‘drag’n drop installation dmgs natively. It’s not _that_ hard.) ### Verify the download @@ -119,7 +141,7 @@ When used to install software, Installomator has a single argument: the label or ./Installomator.sh firefox LOGO=jamf BLOCKING_PROCESS_ACTION=tell_user_then_kill NOTIFY=all ``` -There is a debug mode and one other setting that can be controlled with variables in the code. This simplifies the actual use of the script from within a management system. +There is a debug mode and other settings that can be controlled with variables in the code. This simplifies the actual use of the script from within a management system. ### Extensible @@ -144,19 +166,21 @@ googlechrome) When you know how to extract these pieces of information from the application and/or download, then you can add an application to Installomator. -The script `buildCaseStatement.sh` can help with the label creation. +The script `buildLabel.sh` can help with the label creation. Just server the URL to the script, and it will try to figure out things and write out a label as output. See [Wiki Tutorials](https://github.com/Installomator/Installomator/wiki#tutorials). Please note: Labels should be named in small caps, numbers 0-9, “-”, and “_”. No other characters allowed. +Actually labels are part of a case-statement, and must be formatted accordingly. + ### Not specific to a management system -I wrote this script mainly for use with Jamf Pro, because that is what we use. For testing, you can run the script interactively from the command line. However, I have tried to keep anything that is specific to Jamf optional, or so flexible that it will work anywhere. Even if it does not work with your management system 'out of the box,' the adaptations should be straightforward. +Armin wrote this script mainly for use with Jamf Pro, because that is what he used. For testing, you can run the script interactively from the command line. However, we have tried to keep anything that is specific to Jamf optional, or so flexible that it will work anywhere. Even if it does not work with your management system ‘out of the box’, the adaptations should be straightforward. Not all MDMs can include the full script, for those MDMs it might be more useful to install it on the client machines, and run it from there. So a PKG to be installed on client Macs is also provided here. ### No dependencies -The script started out as a pure `sh` script, and when I needed arrays I 'switched' to `zsh`, because that is what [we can rely on being in macOS for the foreseeable future](https://scriptingosx.com/zsh). There are quite a few places where using python would have been easier and safer, but with the python 2 run-time being deprecated, that would have added a requirement for a Python 3 run-time to be installed. XML and JSON parsing would have been better with a tool like [scout](https://github.com/ABridoux/scout) or [jq](https://stedolan.github.io/jq/), but those would again require additional installations on the client before the script can run. +The script started out as a pure `sh` script, and when arrays was needed it was ‘switched’ to `zsh`, because that is what [we can rely on being in macOS for the foreseeable future](https://scriptingosx.com/zsh). There are quite a few places where using python would have been easier and safer, but with the python 2 run-time being deprecated, that would have added a requirement for a Python 3 run-time to be installed. XML and JSON parsing would have been better with a tool like [scout](https://github.com/ABridoux/scout) or [jq](https://stedolan.github.io/jq/), but those would again require additional installations on the client before the script can run. Keeping the script as a `zsh` allows you to paste it into your management system's interface (and disable the DEBUG mode) and use it without requiring any other installations. @@ -201,7 +225,7 @@ _Always remember_ to change the `DEBUG` variable to `0` when deploying. The inst ### Use Installomator with various MDM solutions -In the wiki we have provided documentation on how Installomator is used in various MDM solution, like Jamf Pro, Mosyle, and Addigy. +In the wiki we have provided documentation on how Installomator is used in various MDM solution, like [Jamf Pro](https://github.com/Installomator/Installomator/wiki/MDM:-Jamf-Pro), [Mosyle](https://github.com/Installomator/Installomator/wiki/MDM:-Mosyle-(Business,-Fuse,-and-Manager)), and [Addigy](https://github.com/Installomator/Installomator/wiki/MDM:-Addigy). ## What it does @@ -209,7 +233,7 @@ When it runs with a known label, the script will perform the following: - Check the version installed with the version online. Only continue if it's different - download the latest version from the vendor -- when the application is running, prompt the user to quit or cancel +- when the application is running, prompt the user to quit or cancel (customizable) - dmg or zip archives: - extract the application and copy it to /Applications - change the owner of the application to the current user @@ -217,7 +241,7 @@ When it runs with a known label, the script will perform the following: - when necessary, extract the pkg from the enclosing archive - install the pkg with the `installer` tool - clean up the downloaded files -- notify the user +- notify the user (also customizable) ## Configuring the script From 1e68b7e5017c966bacea66f0eddaaa3e257f8905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 31 Jan 2022 10:00:07 +0100 Subject: [PATCH 40/76] Update README.md --- README.md | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/README.md b/README.md index 4ec1cc3..9fbff98 100644 --- a/README.md +++ b/README.md @@ -324,6 +324,117 @@ The order of the variables and label is not relevant. But, when you provide more Providing all the variables this way might be useful for certain downloads that have a customized URL for each vendor/customer (like customized TeamView or Watchman Monitoring) or are local downloads. +## Adding applications/label blocks + +### Required Variables + +The script requires four pieces of information to download and install an application: + +``` +spotify) + name="Spotify" + type="dmg" + downloadURL="https://download.scdn.co/Spotify.dmg" + expectedTeamID="2FNC3A47ZF" + ;; +``` + +The four required variables are + +- `name`: +The display name of the installed application without the `.app` extensions. + +- `type`: +The type of installation. Possible values: + - `dmg`: application in disk image file (drag'n drop installation) + - `pkg`: flat pkg download + - `zip`: application in zip archive (`zip` extension) + - `tbz`: application in tbz archive (`tbz` extension) + - `pkgInDmg`: a pkg file inside a disk image + - `pkgInZip`: a pkg file inside a zip + - `appInDmgInZip`: an app in a dmg file that has been zip'ed + +- `downloadURL`: +The URL from which to download the archive. +The URL can be generated by a series of commands, for example when you need to parse an xml file for the latest URL. (See `bbedit`, `desktoppr`, or `omnigraffle` for examples.) +Sometimes version differs between Intel and Apple Silicon versions. (See `brave`, `obsidian`, `omnidisksweeper`, or `notion`). + +- `appNewVersion` (optional, but recommended): +Version of the downloaded software. +If given, it will be compared to installed version, to see if download is different. +It does not check for newer or not, only different. +Not always easy to figure out how to make this. Sometimes this is listed on the downloads page, sometimes in other places. And how can we isolate it in a genral manner? (See `abstract`, `bbedit`, `brave`, `desktoppr`, `googlechrome`, or `omnidisksweeper`). + +- `packageID` (optional, but recommended for pkgs without an app) +This variable is for pkg bundle IDs. Very usefull if a pkg only install command line tools, or the like that does not install an app. (See label `desktoppr`, `golang`, `installomator_st`, `odrive`, or `teamviewerhost`). + +- `expectedTeamID`: +The 10-character Developer Team ID with which the application or pkg is signed and notarized. + + Obtain the team ID by running: + + - Applications (in dmgs or zips) + `spctl -a -vv /Applications/BBEdit.app` + + - Installation Packages (pkg) + `spctl -a -vv -t install ~/Downloads/desktoppr-0.2.pkg` + +### Optional Variables + +Depending on the application or pkg there are a few more variables you can or need to set. Many of these are derived from the required variables, but may need to be set manually if those derived values do not work. + +- `archiveName`: (optional) + The name of the downloaded file. + When not given the `archiveName` is set to `$name.$type` + +- `appName`: (optional) + File name of the app bundle in the dmg to verify and copy (include the `.app`). + When not given, the `appName` is set to `$name.app`. + This is also the name of the app that will get reopned, if we closed any `blockingProcesses` (see further down) + +- `targetDir`: (optional) + dmg or zip: + Applications will be copied to this directory. + Default value is '`/Applications`' for dmg and zip installations. + pkg: + `targetDir` is used as the install-location. Default is '`/`'. + +- `blockingProcesses`: (optional) + Array of process names that will block the installation or update. + If no `blockingProcesses` array is given the default will be: + `blockingProcesses=( $name )` + When a package contains multiple applications, _all_ should be listed, e.g: + `blockingProcesses=( "Keynote" "Pages" "Numbers" )` + When a workflow has no blocking processes, use + `blockingProcesses=( NONE )` + +- `pkgName`: (optional, only used for `dmgInPkg` and `dmgInZip`) + File name of the pkg file _inside_ the dmg or zip. + When not given the pkgName is set to `$name.pkg`. + +- `updateTool`, `updateToolArguments`: + When Installomator detects an existing installation of the application, + and the `updateTool` variable is set then + `$updateTool $updateArguments` + Will be run instead of of downloading and installing a complete new version. + Use this when the `updateTool` does differential and optimized downloads. + e.g. `msupdate` (see various Microsoft installations). + +- `updateToolRunAsCurrentUser`: + When this variable is set (any value), `$updateTool` will be run as the current user. Default is unset and + +- `CLIInstaller`: +- `CLIArguments`: + If the downloaded dmg is actually an installer that we can call using CLI, we can use these two variables for what to call. + We need to define `name` for the installed app (to be version checked), as well as `installerTool` for the installer app (if named differently that `name`. Installomator will add the path to the folder/disk image with the binary, and it will be called like this: + `$CLIInstaller $CLIArguments` + For most installations `CLIInstaller` should contain the `installerTool` for the CLI call (if it’s the same). + We can support a whole range of other software titles by implementing this. + See label adobecreativeclouddesktop. + +- `installerTool`: + Introduced as part of `CLIInstaller`. If the installer in the DMG or ZIP is named differently than the installed app, then this variable can be used to name the installer that should be located after mounting/expanding the downloaded archive. + See label adobecreativeclouddesktop ## Frequently Asked Questions From ec2debc9a84acba3d087a12f9e57c805ed4cf083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 31 Jan 2022 12:57:31 +0100 Subject: [PATCH 41/76] Update README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9fbff98..d84dddc 100644 --- a/README.md +++ b/README.md @@ -253,15 +253,15 @@ The `BLOCKING_PROCESS_ACTION` variable controls the behavior of the script when There are eight options: -- `ignore`: continue even when blocking processes are found. -- `silent_fail`: exit script without prompt or installation. -- `prompt_user`: (default) show a user dialog for each blocking process found abort after three attempts to quit (only if user accepts to quit the apps, otherwise the update is cancelled). -- `prompt_user_then_kill`: show a user dialog for each blocking process found, attempt to quit two times, kill the process finally. +- `ignore`: Continue even when blocking processes are found. +- `silent_fail`: Exit script without prompt or installation. +- `prompt_user`: Show a user dialog for each blocking process found abort after three attempts to quit (only if user accepts to quit the apps, otherwise the update is cancelled). +- `prompt_user_then_kill`: Show a user dialog for each blocking process found, attempt to quit two times, kill the process finally. - `prompt_user_loop`: Like prompt-user, but clicking "Not Now", will just wait an hour, and then it will ask again. WARNING! It might block the MDM agent on the machine, as the scripts gets stuct in waiting until the hour has passed, possibly blocking for other management actions in this time. -- `tell_user`: User will be showed a notification about the important update, but user is only allowed to quit and continue, and then we ask the app to quit. +- `tell_user`: (Default) User will be showed a notification about the important update, but user is only allowed to quit and continue, and then we ask the app to quit. This is default. - `tell_user_then_kill`: Show dialog 2 times, and if the quitting fails, the blocking processes will be killed. -- `kill`: kill process without prompting or giving the user a chance to save. +- `kill`: Kill process without prompting or giving the user a chance to save. If any process was closed, Installomator will try to open the app again, after the update process is done. From bc26aa0ca631cf8067b86039e6b53bb2873add07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 31 Jan 2022 23:41:07 +0100 Subject: [PATCH 42/76] Update functions.sh Had a problem with `dbeaverce` that claimed LSMinimumSystemVersion was used even though it was not, so improved the handling. --- fragments/functions.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fragments/functions.sh b/fragments/functions.sh index 0908662..41ee28c 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -368,8 +368,8 @@ installAppWithPath() { # $1: path to app to install in $targetDir fi # macOS versioncheck - minimumOSversion=$(defaults read $appPath/Contents/Info.plist LSMinimumSystemVersion) - if [[ $minimumOSversion =~ '[0-9.]*' ]]; then + minimumOSversion=$(defaults read $appPath/Contents/Info.plist LSMinimumSystemVersion 2>/dev/null ) + if [[ -n $minimumOSversion && $minimumOSversion =~ '[0-9.]*' ]]; then printlog "App has LSMinimumSystemVersion: $minimumOSversion" if ! is-at-least $minimumOSversion $installedOSversion; then printlog "App requires higher System Version than installed: $installedOSversion" From dd2af4a40e9e1ec68c26a1694cbbeac34900e338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Tue, 1 Feb 2022 00:13:51 +0100 Subject: [PATCH 43/76] Create checkInstallomator.sh This script will check certain labels. It's meant to check all (or most) of Installomator, to see if the code is working. We need labels that are representative for alle the functionality in the script. (Bug-fix for LSMinimumSystemVersion is needed for some of these to work) --- utils/checkInstallomator.sh | 107 ++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100755 utils/checkInstallomator.sh diff --git a/utils/checkInstallomator.sh b/utils/checkInstallomator.sh new file mode 100755 index 0000000..ff3bce7 --- /dev/null +++ b/utils/checkInstallomator.sh @@ -0,0 +1,107 @@ +#!/bin/zsh + +export PATH=/usr/bin:/bin:/usr/sbin:/sbin + +# Check Installomator with various labels in various modes +# 2022 Søren Theilgaard (@theilgaard) + +# This script will use various labels to check if Installomator is working as it is supposed to do + +# To check this script use these labels: +# desktoppr dbeaverce brave microsoftteams whatsapp citrixworkspace aircall devonthink + + +# MARK: Constants +allLabels=( dbeaverce signal brave inkscape devonthink microsoftteams applenyfonts sketch sqlpropostgres desktoppr marathon) + +# dbeaverse: dmg without appNewVersion +# signal: dmg with appNewVersion +# brave: dmg with appNewVersion from versionKey +# inkscape: dmg with appCustomVersion +# adobecreativeclouddesktop: dmg with appNewVersion and installerTool +# devonthink: appInDmgInZip +# microsoftteams: pkg with appNewVersion from packageID +# applenyfonts: pkgInDmg from Apple with packageID and no appNewVersion +# sketch: zip with appNewVersion +# sqlpropostgres: zip without appNewVersion +# desktoppr: pkg from github with packageID +# marathon: dmg from github with archiveName + + +#setup some folders +script_dir=$(dirname ${0:A}) +repo_dir=$(dirname $script_dir) +build_dir="$repo_dir/build" +destination_file="$build_dir/Installomator.sh" +fragments_dir="$repo_dir/fragments" +labels_dir="$fragments_dir/labels" + +# MARK: Script +# Check minimal macOS requirement +if [[ $(sw_vers -buildVersion ) < "18" ]]; then + echo "Installomator requires at least macOS 10.14 Mojave." + exit 98 +fi + +currentUser=$(stat -f "%Su" /dev/console) + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[1;34m' +NC='\033[0m' # No Color +countWarning=0 +countError=0 + +for label in $allLabels; do + cmd_output=$( $repo_dir/assemble.sh $label DEBUG=2 INSTALL=force IGNORE_APP_STORE_APPS=yes BLOCKING_PROCESS_ACTION=ignore ) + #echo "$cmd_output" + no_appNewVersion=$( echo $cmd_output | grep -ic "Latest version not specified." ) + echo "No appNewVersion: $no_appNewVersion (1 for no)" + latest_appNewVersion=$( echo $cmd_output | grep -i "Latest version of " | sed -E 's/.* is ([0-9.]*),*.*$/\1/g' ) + echo "Latest vesion: $latest_appNewVersion" + github_label=$( echo $cmd_output | grep -ci "Downloading https://github.com" ) + echo "github: $github_label (1 for true)" + downloaded_version=$( echo $cmd_output | grep -ioE "Downloaded (package.*version|version of.*is) [0-9.]*" | grep -v "is the same as installed" | sed -E 's/.* (is|version) ([0-9.]*).*/\2/g' ) + echo "Downloaded version: $downloaded_version" + exit_status=$( echo $cmd_output | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) + echo "Exit: $exit_status" + if [[ ${exit_status} -eq 0 ]] ; then + if [[ $no_appNewVersion -eq 1 ]]; then + echo "${GREEN}$label works fine, but no appNewVersion.${NC}" + elif [[ $latest_appNewVersion == $downloaded_version && $github_label -eq 0 ]]; then + echo "${GREEN}$label works fine, with version $latest_appNewVersion.${NC}" + elif [[ $github_label -eq 1 ]]; then + echo "${GREEN}$label works fine, with GitHub version $latest_appNewVersion.${NC}" + elif [[ $latest_appNewVersion != $downloaded_version && $github_label -eq 0 ]]; then + echo "${YELLOW}$label has version warning, with latest $latest_appNewVersion not matching downloaded $downloaded_version.${NC}" + ((countWarning++)) + echo "$cmd_output" + else + echo "${RED}$label NOT WORKING:${NC}" + ((countError++)) + errorLabels+=( "$label" ) + echo "$cmd_output" + fi + else + echo "${RED}$label NOT WORKING:${NC}" + ((countError++)) + errorLabels+=( "$label" ) + echo "$cmd_output" + fi +done + +echo +if [[ countWarning -gt 0 ]]; then + echo "${YELLOW}Warnings counted: $countWarning${NC}" + echo "${YELLOW}${warningLabels}${NC}" +else + echo "${GREEN}No warnings detected!${NC}" +fi +if [[ countError -gt 0 ]]; then + echo "${RED}ERRORS counted: $countError${NC}" +else + echo "${GREEN}No errors detected!${NC}" +fi + +echo "Done!" From 9416700da294c3dce44d9ee34cff57b4b0c06ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Tue, 1 Feb 2022 09:12:50 +0100 Subject: [PATCH 44/76] Update checkInstallomator.sh More description on what to test --- utils/checkInstallomator.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/utils/checkInstallomator.sh b/utils/checkInstallomator.sh index ff3bce7..570efe7 100755 --- a/utils/checkInstallomator.sh +++ b/utils/checkInstallomator.sh @@ -14,11 +14,14 @@ export PATH=/usr/bin:/bin:/usr/sbin:/sbin # MARK: Constants allLabels=( dbeaverce signal brave inkscape devonthink microsoftteams applenyfonts sketch sqlpropostgres desktoppr marathon) -# dbeaverse: dmg without appNewVersion +## Testing for combinations of these +# Label types: dmg, pkg, zip, tbz, pkgInDmg, pkgInZip, appInDmgInZip +# Label fields: packageID, appNewVersion, versionKey, appCustomVersion(){}, archiveName, appName, pkgName + +# dbeaverse: dmg without appNewVersion and does not have LSMinimumSystemVersion in Info.plist # signal: dmg with appNewVersion # brave: dmg with appNewVersion from versionKey # inkscape: dmg with appCustomVersion -# adobecreativeclouddesktop: dmg with appNewVersion and installerTool # devonthink: appInDmgInZip # microsoftteams: pkg with appNewVersion from packageID # applenyfonts: pkgInDmg from Apple with packageID and no appNewVersion @@ -27,6 +30,10 @@ allLabels=( dbeaverce signal brave inkscape devonthink microsoftteams applenyfon # desktoppr: pkg from github with packageID # marathon: dmg from github with archiveName +# Label types not possible to test in DEBUG mode: updateronly +# Label fields not possible to test in DEBUG mode: targetDir, blockingProcesses, updateTool, updateToolRunAsCurrentUser, installerTool, CLIInstaller, CLIArguments +# adobecreativeclouddesktop: dmg with appNewVersion and installerTool, CLIInstaller, CLIArguments + #setup some folders script_dir=$(dirname ${0:A}) From ded71fdf8d53f0bbd6a4a6f96f156bbc8ebf65e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 2 Feb 2022 15:02:31 +0100 Subject: [PATCH 45/76] Error in cleanupAndExit fixed Unmounted drive after we deleted the temporary items. Reversed order. --- fragments/functions.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fragments/functions.sh b/fragments/functions.sh index 647ef85..3abbdfb 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -1,19 +1,19 @@ # MARK: Functions cleanupAndExit() { # $1 = exit code, $2 message, $3 level - if [ "$DEBUG" -ne 1 ]; then - # remove the temporary working directory when done - printlog "Deleting $tmpDir" DEBUG - deleteTmpOut=$(rm -Rfv "$tmpDir") - printlog "Debugging enabled, Deleting tmpDir output was:\n$deleteTmpOut" DEBUG - fi - if [ -n "$dmgmount" ]; then # unmount disk image printlog "Unmounting $dmgmount" DEBUG unmountingOut=$(hdiutil detach "$dmgmount" 2>&1) printlog "Debugging enabled, Unmounting output was:\n$unmountingOut" DEBUG fi + if [ "$DEBUG" -ne 1 ]; then + # remove the temporary working directory when done (only if DEBUG is not used) + printlog "Deleting $tmpDir" DEBUG + deleteTmpOut=$(rm -Rfv "$tmpDir") + printlog "Debugging enabled, Deleting tmpDir output was:\n$deleteTmpOut" DEBUG + fi + # If we closed any processes, reopen the app again reopenClosedProcess if [[ -n $2 && $1 -ne 0 ]]; then From 790dabaa27306a839ebe0610c0507dd0bf472cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 2 Feb 2022 15:08:39 +0100 Subject: [PATCH 46/76] Comment on exit value if only label name is requested --- fragments/functions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fragments/functions.sh b/fragments/functions.sh index 3abbdfb..78e7704 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -23,7 +23,7 @@ cleanupAndExit() { # $1 = exit code, $2 message, $3 level # if label is wrong and we wanted name of the label, then return ################## if [[ $RETURN_LABEL_NAME -eq 1 ]]; then - 1=0 + 1=0 # If only label name should be returned we exit without any errors echo "#" fi exit "$1" From bbf4b22296f19f48fa65965344599f771d02cef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 2 Feb 2022 15:23:46 +0100 Subject: [PATCH 47/76] Fix for Apple signed software Somehow went missing in the Isaac logging. --- fragments/functions.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fragments/functions.sh b/fragments/functions.sh index 78e7704..2e1fc8a 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -564,7 +564,13 @@ installFromPKG() { spctlOut=$(spctl -a -vv -t install "$archiveName" 2>&1 ) spctlStatus=$(echo $?) printlog "spctlOut is $spctlOut" DEBUG + teamID=$(echo $spctlOut | awk -F '(' '/origin=/ {print $2 }' | tr -d '()' ) + # Apple signed software has no teamID, grab entire origin instead + if [[ -z $teamID ]]; then + teamID=$(echo $spctlOut | awk -F '=' '/origin=/ {print $NF }') + fi + deduplicatelogs "$spctlOut" if [[ $spctlStatus -ne 0 ]] ; then From 3a397c58817d09c9bc26de636d40e682e9a66249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 2 Feb 2022 15:37:08 +0100 Subject: [PATCH 48/76] Label name and better handling --- utils/checkInstallomator.sh | 62 ++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/utils/checkInstallomator.sh b/utils/checkInstallomator.sh index 570efe7..7003c3b 100755 --- a/utils/checkInstallomator.sh +++ b/utils/checkInstallomator.sh @@ -61,40 +61,46 @@ countWarning=0 countError=0 for label in $allLabels; do - cmd_output=$( $repo_dir/assemble.sh $label DEBUG=2 INSTALL=force IGNORE_APP_STORE_APPS=yes BLOCKING_PROCESS_ACTION=ignore ) - #echo "$cmd_output" - no_appNewVersion=$( echo $cmd_output | grep -ic "Latest version not specified." ) - echo "No appNewVersion: $no_appNewVersion (1 for no)" - latest_appNewVersion=$( echo $cmd_output | grep -i "Latest version of " | sed -E 's/.* is ([0-9.]*),*.*$/\1/g' ) - echo "Latest vesion: $latest_appNewVersion" - github_label=$( echo $cmd_output | grep -ci "Downloading https://github.com" ) - echo "github: $github_label (1 for true)" - downloaded_version=$( echo $cmd_output | grep -ioE "Downloaded (package.*version|version of.*is) [0-9.]*" | grep -v "is the same as installed" | sed -E 's/.* (is|version) ([0-9.]*).*/\2/g' ) - echo "Downloaded version: $downloaded_version" - exit_status=$( echo $cmd_output | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) - echo "Exit: $exit_status" - if [[ ${exit_status} -eq 0 ]] ; then - if [[ $no_appNewVersion -eq 1 ]]; then - echo "${GREEN}$label works fine, but no appNewVersion.${NC}" - elif [[ $latest_appNewVersion == $downloaded_version && $github_label -eq 0 ]]; then - echo "${GREEN}$label works fine, with version $latest_appNewVersion.${NC}" - elif [[ $github_label -eq 1 ]]; then - echo "${GREEN}$label works fine, with GitHub version $latest_appNewVersion.${NC}" - elif [[ $latest_appNewVersion != $downloaded_version && $github_label -eq 0 ]]; then - echo "${YELLOW}$label has version warning, with latest $latest_appNewVersion not matching downloaded $downloaded_version.${NC}" - ((countWarning++)) - echo "$cmd_output" + label_name=$( $repo_dir/assemble.sh $label DEBUG=2 RETURN_LABEL_NAME=1 | tail -1 ) + if [[ "$label_name" == "#" ]]; then + echo "${RED}Label $label does not exist. Skipping.${NC}" + else + echo "Label $label: $label_name" + cmd_output=$( $repo_dir/assemble.sh $label DEBUG=2 INSTALL=force IGNORE_APP_STORE_APPS=yes BLOCKING_PROCESS_ACTION=ignore ) + #echo "$cmd_output" + no_appNewVersion=$( echo $cmd_output | grep -ic "Latest version not specified." ) + echo "No appNewVersion: $no_appNewVersion (1 for no)" + latest_appNewVersion=$( echo $cmd_output | grep -i "Latest version of " | sed -E 's/.* is ([0-9.]*),*.*$/\1/g' ) + echo "Latest version: $latest_appNewVersion" + github_label=$( echo $cmd_output | grep -ci "Downloading https://github.com" ) + echo "GitHub: $github_label (1 for true)" + downloaded_version=$( echo $cmd_output | grep -ioE "Downloaded (package.*version|version of.*is) [0-9.]*" | grep -v "is the same as installed" | sed -E 's/.* (is|version) ([0-9.]*).*/\2/g' ) + echo "Downloaded version: $downloaded_version" + exit_status=$( echo $cmd_output | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) + echo "Exit: $exit_status" + if [[ ${exit_status} -eq 0 ]] ; then + if [[ $no_appNewVersion -eq 1 ]]; then + echo "${GREEN}$label works fine, but no appNewVersion.${NC}" + elif [[ $latest_appNewVersion == $downloaded_version && $github_label -eq 0 ]]; then + echo "${GREEN}$label works fine, with version $latest_appNewVersion.${NC}" + elif [[ $github_label -eq 1 ]]; then + echo "${GREEN}$label works fine, with GitHub version $latest_appNewVersion.${NC}" + elif [[ $latest_appNewVersion != $downloaded_version && $github_label -eq 0 ]]; then + echo "${YELLOW}$label has version warning, with latest $latest_appNewVersion not matching downloaded $downloaded_version.${NC}" + ((countWarning++)) + echo "$cmd_output" + else + echo "${RED}$label NOT WORKING:${NC}" + ((countError++)) + errorLabels+=( "$label" ) + echo "$cmd_output" + fi else echo "${RED}$label NOT WORKING:${NC}" ((countError++)) errorLabels+=( "$label" ) echo "$cmd_output" fi - else - echo "${RED}$label NOT WORKING:${NC}" - ((countError++)) - errorLabels+=( "$label" ) - echo "$cmd_output" fi done From 29fadb78b4271677fd7ba15ccde13efcef510a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 2 Feb 2022 15:57:30 +0100 Subject: [PATCH 49/76] Update checkInstallomator.sh --- utils/checkInstallomator.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/checkInstallomator.sh b/utils/checkInstallomator.sh index 7003c3b..793761a 100755 --- a/utils/checkInstallomator.sh +++ b/utils/checkInstallomator.sh @@ -101,6 +101,7 @@ for label in $allLabels; do errorLabels+=( "$label" ) echo "$cmd_output" fi + echo fi done From 62734a2acc7f2f388e950be841d8690ec26969b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 2 Feb 2022 16:00:23 +0100 Subject: [PATCH 50/76] 403 labels! --- Labels.txt | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Labels.txt b/Labels.txt index 20c2d91..4ea3c51 100644 --- a/Labels.txt +++ b/Labels.txt @@ -22,6 +22,7 @@ anydesk apparency appcleaner applenyfonts +applesfarabic applesfcompact applesfmono applesfpro @@ -72,6 +73,7 @@ cormorant craftmanager cryptomator cyberduck +daisydisk dangerzone darktable dbeaverce @@ -84,6 +86,7 @@ devonthink dialog dialpad discord +diskspace docker drift dropbox @@ -110,6 +113,7 @@ firefoxesr_intl firefoxesrpkg firefoxpkg flowjo +flux front fsmonitor gimp @@ -136,7 +140,9 @@ hazel hpeasyadmin hpeasystart hyper +ibarcoder icons +iina imazingprofileeditor inkscape insomnia @@ -145,6 +151,7 @@ installomator_theile intellijideace istatmenus iterm2 +itsycal jabradirect jamfconnect jamfconnectconfiguration @@ -177,6 +184,7 @@ libreoffice logitechoptions logseq loom +lowprofile lucifer lulu maccyapp @@ -211,6 +219,12 @@ microsoftvisualstudiocode microsoftword microsoftyammer miro +mobikinassistantforandroid +mochakeyboard +mochatelnet +mochatn3270 +mochatn3812 +mochatn5250 montereyblocker mowgliiitsycal musescore @@ -242,6 +256,7 @@ ottomatic overflow pacifist pandoc +paretosecurity parsec pdfsam perimeter81 @@ -251,16 +266,21 @@ platypus plisteditpro postman prism9 +pritunl privileges proctortrack promiseutilityr +protonvpn proxyman pycharmce pymol r ramboxce +rancherdesktop rectangle redeye +remotedesktopmanagerenterprise +remotedesktopmanagerfree remotix remotixagent resiliosynchome @@ -280,6 +300,8 @@ scaleft screamingfrogseospider screencloudplayer screenflick +sdnotary +secretive sequelpro sfsymbols shield @@ -314,6 +336,7 @@ suspiciouspackage swiftruntimeforcommandlinetools sync tableaudesktop +tableaupublic tableaureader tageditor talkdeskcallbar @@ -343,7 +366,7 @@ utm vagrant vanilla veracrypt -virtualbox +vimac viscosity visualstudiocode vivaldi @@ -376,4 +399,5 @@ zoomrooms zulujdk11 zulujdk13 zulujdk15 +zulujdk17 zulujdk8 From 434b755946acc8d55c009eb1b7591264937f9b8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 2 Feb 2022 16:13:33 +0100 Subject: [PATCH 51/76] Renamed to promiseutility Not sure why the "r" was there in the first place. --- Labels.txt | 1 + fragments/labels/promiseutilityr.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/Labels.txt b/Labels.txt index 4ea3c51..dd319a3 100644 --- a/Labels.txt +++ b/Labels.txt @@ -269,6 +269,7 @@ prism9 pritunl privileges proctortrack +promiseutility promiseutilityr protonvpn proxyman diff --git a/fragments/labels/promiseutilityr.sh b/fragments/labels/promiseutilityr.sh index 78ef92b..99d2c32 100644 --- a/fragments/labels/promiseutilityr.sh +++ b/fragments/labels/promiseutilityr.sh @@ -1,3 +1,4 @@ +promiseutility|\ promiseutilityr) name="Promise Utility" type="pkgInDmg" From d36b42acf4839aa51107a993bf252bcab2a17312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 2 Feb 2022 19:39:48 +0100 Subject: [PATCH 52/76] Isaac logging improvements/fixes Moved the variable declarations from `functions.sh` to `arguments.sh`. We need the argument parsing before setting the logging level and other variables. --- fragments/arguments.sh | 32 ++++++++++++++++++++++++++++++++ fragments/functions.sh | 41 ++++------------------------------------- fragments/header.sh | 2 +- fragments/main.sh | 5 +++-- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/fragments/arguments.sh b/fragments/arguments.sh index dfd26e4..45a933c 100644 --- a/fragments/arguments.sh +++ b/fragments/arguments.sh @@ -43,6 +43,38 @@ if [[ $label == "version" ]]; then exit 0 fi +# MARK: Logging +log_location="/private/var/log/Installomator.log" + +# Check if we're in debug mode, if so then set logging to DEBUG, otherwise default to INFO +# if no log level is specified. +if [[ $DEBUG -ne 0 ]]; then + LOGGING=DEBUG +elif [[ -z $LOGGING ]]; then + LOGGING=INFO + datadogLoggingLevel=INFO +fi + +# Associate logging levels with a numerical value so that we are able to identify what +# should be removed. For example if the LOGGING=ERROR only printlog statements with the +# level REQ and ERROR will be displayed. LOGGING=DEBUG will show all printlog statements. +# If a printlog statement has no level set it's automatically assigned INFO. + +declare -A levels=(DEBUG 0 INFO 1 WARN 2 ERROR 3 REQ 4) + +# If we are able to detect an MDM URL (Jamf Pro) or another identifier for a customer/instance we grab it here, this is useful if we're centrally logging multiple MDM instances. +if [[ -f /Library/Preferences/com.jamfsoftware.jamf.plist ]]; then + mdmURL=$(defaults read /Library/Preferences/com.jamfsoftware.jamf.plist jss_url) +elif [[ -n "$MDMProfileName" ]]; then + mdmURL=$(sudo profiles show | grep -A3 "$MDMProfileName" | sed -n -e 's/^.*organization: //p') +else + mdmURL="Unknown" +fi + +# Generate a session key for this run, this is useful to idenify streams when we're centrally logging. +SESSION=$RANDOM + +# Mark: START printlog "################## Start Installomator v. $VERSION, date $VERSIONDATE" REQ printlog "################## Version: $VERSION" INFO printlog "################## Date: $VERSIONDATE" INFO diff --git a/fragments/functions.sh b/fragments/functions.sh index 2e1fc8a..efdcead 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -67,38 +67,6 @@ displaynotification() { # $1: message $2: title fi } - -# MARK: Logging -log_location="/private/var/log/Installomator.log" - -# Check if we're in debug mode, if so then set logging to DEBUG, otherwise default to INFO -# if no log level is specified. -if [[ $DEBUG -ne 0 ]]; then - LOGGING=DEBUG -elif [[ -z $LOGGING ]]; then - LOGGING=INFO - datadogLoggingLevel=INFO -fi - -# Associate logging levels with a numerical value so that we are able to identify what -# should be removed. For example if the LOGGING=ERROR only printlog statements with the -# level REQ and ERROR will be displayed. LOGGING=DEBUG will show all printlog statements. -# If a printlog statement has no level set it's automatically assigned INFO. - -declare -A levels=(DEBUG 0 INFO 1 WARN 2 ERROR 3 REQ 4) - -# If we are able to detect an MDM URL (Jamf Pro) or another identifier for a customer/instance we grab it here, this is useful if we're centrally logging multiple MDM instances. -if [[ -f /Library/Preferences/com.jamfsoftware.jamf.plist ]]; then - mdmURL=$(defaults read /Library/Preferences/com.jamfsoftware.jamf.plist jss_url) -elif [[ -n "$MDMProfileName" ]]; then - mdmURL=$(sudo profiles show | grep -A3 "$MDMProfileName" | sed -n -e 's/^.*organization: //p') -else - mdmURL="Unknown" -fi - -# Generate a session key for this run, this is useful to idenify streams when we're centrally logging. -SESSION=$RANDOM - printlog(){ [ -z "$2" ] && 2=INFO log_message=$1 @@ -106,11 +74,10 @@ printlog(){ timestamp=$(date +%F\ %T) # Check to make sure that the log isn't the same as the last, if it is then don't log and increment a timer. - if [[ ${log_message} == ${previous_log_message} ]];then + if [[ ${log_message} == ${previous_log_message} ]]; then let logrepeat=$logrepeat+1 return fi - previous_log_message=$log_message # Once we finally stop getting duplicate logs output the number of times we got a duplicate. @@ -123,7 +90,7 @@ printlog(){ logrepeat=0 fi - # If the datadogAPI key value is set and our logging level is greaterthan or equal to our set level + # If the datadogAPI key value is set and our logging level is greater than or equal to our set level # then post to Datadog's HTTPs endpoint. if [[ -n $datadogAPI && ${levels[$log_priority]} -ge ${levels[$datadogLoggingLevel]} ]]; then while IFS= read -r logmessage; do @@ -143,8 +110,8 @@ printlog(){ fi } -# Used to remove dupplicate lines in large log output, for example from msupdate command -# after it finishes running. +# Used to remove dupplicate lines in large log output, +# for example from msupdate command after it finishes running. deduplicatelogs() { loginput=${1:-"Log"} logoutput="" diff --git a/fragments/header.sh b/fragments/header.sh index 25dfaf4..cc19927 100644 --- a/fragments/header.sh +++ b/fragments/header.sh @@ -266,7 +266,7 @@ IGNORE_DND_APPS="" # ### Logging # Logging behavior -LOGGING="" +LOGGING="INFO" # options: # - DEBUG Everything is logged # - INFO (default) normal logging level diff --git a/fragments/main.sh b/fragments/main.sh index f77335f..3f75085 100644 --- a/fragments/main.sh +++ b/fragments/main.sh @@ -24,6 +24,7 @@ fi printlog "BLOCKING_PROCESS_ACTION=${BLOCKING_PROCESS_ACTION}" printlog "NOTIFY=${NOTIFY}" +printlog "LOGGING=${LOGGING}" # Finding LOGO to use in dialogs case $LOGO in @@ -191,7 +192,6 @@ else curlDownload=$(curl -v -fsL --show-error ${curlOptions} "$downloadURL" -o "$archiveName" 2>&1) curlDownloadStatus=$(echo $?) deduplicatelogs "$curlDownload" - printlog "curl output was: $logoutput" DEBUG if [[ $curlDownloadStatus -ne 0 ]]; then #if ! curl --location --fail --silent "$downloadURL" -o "$archiveName"; then printlog "error downloading $downloadURL" @@ -204,8 +204,9 @@ else displaynotification "$message" "Error installing $name" ERROR fi fi - cleanupAndExit 2 "Error downloading $downloadURL error: $logoutput" ERROR + cleanupAndExit 2 "Error downloading $downloadURL error:\n$logoutput" ERROR fi + printlog "curl output was:\n$logoutput" DEBUG fi # MARK: when user is logged in, and app is running, prompt user to quit app From 0a05b533a5cf70c3568a50dd4413d19f0d475b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 2 Feb 2022 19:59:14 +0100 Subject: [PATCH 53/76] Logging info and a fix --- fragments/functions.sh | 2 +- fragments/main.sh | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/fragments/functions.sh b/fragments/functions.sh index efdcead..a7cc17e 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -609,7 +609,7 @@ installFromPKG() { installFromPKG fi - if [ $pkginstallstatus -ne 0 ] ; then + if [[ $pkginstallstatus -ne 0 ]] ; then #if ! installer -pkg "$archiveName" -tgt "$targetDir" ; then cleanupAndExit 9 "Error installing $archiveName error:\n$logoutput" ERROR fi diff --git a/fragments/main.sh b/fragments/main.sh index 3f75085..88b0fbb 100644 --- a/fragments/main.sh +++ b/fragments/main.sh @@ -65,6 +65,8 @@ if [[ ! -a "${LOGO}" ]]; then fi printlog "LOGO=${LOGO}" +printlog "Label type: $type" + # MARK: extract info from data if [ -z "$archiveName" ]; then case $type in @@ -85,6 +87,7 @@ if [ -z "$archiveName" ]; then ;; esac fi +printlog "archiveName: $archiveName" DEBUG if [ -z "$appName" ]; then # when not given derive from name From f1616d0d021362fc3c72f4d68eb976ecd8175840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 2 Feb 2022 21:23:41 +0100 Subject: [PATCH 54/76] Logging fixes --- fragments/functions.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fragments/functions.sh b/fragments/functions.sh index a7cc17e..691c7e9 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -461,7 +461,9 @@ installAppWithPath() { # $1: path to app to install in $targetDir if [ -e "$targetDir/$appName" ]; then printlog "Removing existing $targetDir/$appName" DEBUG deleteAppOut=$(rm -Rfv "$targetDir/$appName" 2>&1) - printlog "Debugging enabled, App removing output was:\n$deleteAppOut" DEBUG + deleteAppOut=$(echo $deleteAppOut | cut -c 1-80) + deduplicatelogs "$deleteAppOut" + printlog "Debugging enabled, App removing output was:\n$logoutput" DEBUG fi # copy app to /Applications @@ -485,7 +487,7 @@ installAppWithPath() { # $1: path to app to install in $targetDir CLIoutput=$("$mountname/$CLIInstaller" "${CLIArguments[@]}" 2>&1) CLIstatus=$(echo $?) - dedupliatelogs "$CLIoutput" + deduplicatelogs "$CLIoutput" if [ $CLIstatus -ne 0 ] ; then cleanupAndExit 3 "Error installing $mountname/$CLIInstaller $CLIArguments error:\n$logoutput" ERROR @@ -597,7 +599,7 @@ installFromPKG() { pkgInstallStatus=$(echo $?) sleep 1 pkgEndTime=$(date "+$LogDateFormat") - pkgInstall+=$(echo "Output of /var/log/install.log below this line.\n") + pkgInstall+=$(echo "\nOutput of /var/log/install.log below this line.\n") pkgInstall+=$(echo "----------------------------------------------------------\n") pkgInstall+=$(awk -v "b=$starttime" -v "e=$pkgEndTime" -F ',' '$1 >= b && $1 <= e' /var/log/install.log) deduplicatelogs "$pkgInstall" From 890c26e2e13d3a044e5950c3026ecd4b50e86ce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 2 Feb 2022 21:47:59 +0100 Subject: [PATCH 55/76] Logging correction for app delete --- fragments/functions.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fragments/functions.sh b/fragments/functions.sh index 691c7e9..6958a13 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -461,7 +461,9 @@ installAppWithPath() { # $1: path to app to install in $targetDir if [ -e "$targetDir/$appName" ]; then printlog "Removing existing $targetDir/$appName" DEBUG deleteAppOut=$(rm -Rfv "$targetDir/$appName" 2>&1) - deleteAppOut=$(echo $deleteAppOut | cut -c 1-80) + tempName="$targetDir/$appName" + tempNameLength=$((${#tempName} + 10)) + deleteAppOut=$(echo $deleteAppOut | cut -c 1-$tempNameLength) deduplicatelogs "$deleteAppOut" printlog "Debugging enabled, App removing output was:\n$logoutput" DEBUG fi From 36fc48682e382ab5d2da411a34af736bb1e749d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 2 Feb 2022 21:58:06 +0100 Subject: [PATCH 56/76] Testing improved Will now ask for admin credentials to run a real installation of 3 different labels with different notifications --- utils/checkInstallomator.sh | 113 +++++++++++++++++++++++++----------- 1 file changed, 78 insertions(+), 35 deletions(-) diff --git a/utils/checkInstallomator.sh b/utils/checkInstallomator.sh index 793761a..2941690 100755 --- a/utils/checkInstallomator.sh +++ b/utils/checkInstallomator.sh @@ -12,7 +12,7 @@ export PATH=/usr/bin:/bin:/usr/sbin:/sbin # MARK: Constants -allLabels=( dbeaverce signal brave inkscape devonthink microsoftteams applenyfonts sketch sqlpropostgres desktoppr marathon) +allLabels=( dbeaverce signal mochatn3270 eshareosx googlechrome brave macports inkscape devonthink omnidisksweeper microsoftteams applenyfonts sketch sqlpropostgres desktoppr marathon) ## Testing for combinations of these # Label types: dmg, pkg, zip, tbz, pkgInDmg, pkgInZip, appInDmgInZip @@ -20,9 +20,14 @@ allLabels=( dbeaverce signal brave inkscape devonthink microsoftteams applenyfon # dbeaverse: dmg without appNewVersion and does not have LSMinimumSystemVersion in Info.plist # signal: dmg with appNewVersion +# mochatn3270: appInDmgInZip with curlOptions +# eshareosx: with packageID, versionKey, and appNewVerseion +# googlechrome: with appNewVersion # brave: dmg with appNewVersion from versionKey +# macports: with custom code for archiveName, and with appNewVersion and appCustomVersion # inkscape: dmg with appCustomVersion # devonthink: appInDmgInZip +# omnidisksweeper: with appNewVersion, and uses xpath # microsoftteams: pkg with appNewVersion from packageID # applenyfonts: pkgInDmg from Apple with packageID and no appNewVersion # sketch: zip with appNewVersion @@ -32,8 +37,8 @@ allLabels=( dbeaverce signal brave inkscape devonthink microsoftteams applenyfon # Label types not possible to test in DEBUG mode: updateronly # Label fields not possible to test in DEBUG mode: targetDir, blockingProcesses, updateTool, updateToolRunAsCurrentUser, installerTool, CLIInstaller, CLIArguments -# adobecreativeclouddesktop: dmg with appNewVersion and installerTool, CLIInstaller, CLIArguments +# adobecreativeclouddesktop: dmg with appNewVersion and installerTool, CLIInstaller, CLIArguments #setup some folders script_dir=$(dirname ${0:A}) @@ -50,6 +55,12 @@ if [[ $(sw_vers -buildVersion ) < "18" ]]; then exit 98 fi +echo "TESTING Installoamator" +echo "Version: $($repo_dir/assemble.sh version)\n" +echo "\nRemember to follow log in another terminal window:" +echo "tail -f /var/log/Installomator.log\n" + + currentUser=$(stat -f "%Su" /dev/console) RED='\033[0;31m' @@ -60,6 +71,43 @@ NC='\033[0m' # No Color countWarning=0 countError=0 +mostWorkAndCheck() { + no_appNewVersion=$( echo $cmd_output | grep -ic "Latest version not specified." ) + echo "No appNewVersion: $no_appNewVersion (1 for no)" + latest_appNewVersion=$( echo $cmd_output | grep -i "Latest version of " | sed -E 's/.* is ([0-9.]*),*.*$/\1/g' ) + echo "Latest version: $latest_appNewVersion" + github_label=$( echo $cmd_output | grep -ci "Downloading https://github.com" ) + echo "GitHub: $github_label (1 for true)" + downloaded_version=$( echo $cmd_output | grep -ioE "Downloaded (package.*version|version of.*is) [0-9.]*" | grep -v "is the same as installed" | sed -E 's/.* (is|version) ([0-9.]*).*/\2/g' ) + echo "Downloaded version: $downloaded_version" + exit_status=$( echo $cmd_output | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) + echo "Exit: $exit_status" + if [[ ${exit_status} -eq 0 ]] ; then + if [[ $no_appNewVersion -eq 1 ]]; then + echo "${GREEN}$label works fine, but no appNewVersion.${NC}" + elif [[ $latest_appNewVersion == $downloaded_version && $github_label -eq 0 ]]; then + echo "${GREEN}$label works fine, with version $latest_appNewVersion.${NC}" + elif [[ $github_label -eq 1 ]]; then + echo "${GREEN}$label works fine, with GitHub version $latest_appNewVersion.${NC}" + elif [[ $latest_appNewVersion != $downloaded_version && $github_label -eq 0 ]]; then + echo "${YELLOW}$label has version warning, with latest $latest_appNewVersion not matching downloaded $downloaded_version.${NC}" + ((countWarning++)) + echo "$cmd_output" + else + echo "${RED}$label NOT WORKING:${NC}" + ((countError++)) + errorLabels+=( "$label" ) + echo "$cmd_output" + fi + else + echo "${RED}$label NOT WORKING:${NC}" + ((countError++)) + errorLabels+=( "$label" ) + echo "$cmd_output" + fi +} + +# Mark: First part in DEBUG mode for label in $allLabels; do label_name=$( $repo_dir/assemble.sh $label DEBUG=2 RETURN_LABEL_NAME=1 | tail -1 ) if [[ "$label_name" == "#" ]]; then @@ -68,39 +116,34 @@ for label in $allLabels; do echo "Label $label: $label_name" cmd_output=$( $repo_dir/assemble.sh $label DEBUG=2 INSTALL=force IGNORE_APP_STORE_APPS=yes BLOCKING_PROCESS_ACTION=ignore ) #echo "$cmd_output" - no_appNewVersion=$( echo $cmd_output | grep -ic "Latest version not specified." ) - echo "No appNewVersion: $no_appNewVersion (1 for no)" - latest_appNewVersion=$( echo $cmd_output | grep -i "Latest version of " | sed -E 's/.* is ([0-9.]*),*.*$/\1/g' ) - echo "Latest version: $latest_appNewVersion" - github_label=$( echo $cmd_output | grep -ci "Downloading https://github.com" ) - echo "GitHub: $github_label (1 for true)" - downloaded_version=$( echo $cmd_output | grep -ioE "Downloaded (package.*version|version of.*is) [0-9.]*" | grep -v "is the same as installed" | sed -E 's/.* (is|version) ([0-9.]*).*/\2/g' ) - echo "Downloaded version: $downloaded_version" - exit_status=$( echo $cmd_output | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) - echo "Exit: $exit_status" - if [[ ${exit_status} -eq 0 ]] ; then - if [[ $no_appNewVersion -eq 1 ]]; then - echo "${GREEN}$label works fine, but no appNewVersion.${NC}" - elif [[ $latest_appNewVersion == $downloaded_version && $github_label -eq 0 ]]; then - echo "${GREEN}$label works fine, with version $latest_appNewVersion.${NC}" - elif [[ $github_label -eq 1 ]]; then - echo "${GREEN}$label works fine, with GitHub version $latest_appNewVersion.${NC}" - elif [[ $latest_appNewVersion != $downloaded_version && $github_label -eq 0 ]]; then - echo "${YELLOW}$label has version warning, with latest $latest_appNewVersion not matching downloaded $downloaded_version.${NC}" - ((countWarning++)) - echo "$cmd_output" - else - echo "${RED}$label NOT WORKING:${NC}" - ((countError++)) - errorLabels+=( "$label" ) - echo "$cmd_output" - fi - else - echo "${RED}$label NOT WORKING:${NC}" - ((countError++)) - errorLabels+=( "$label" ) - echo "$cmd_output" - fi + mostWorkAndCheck + echo + fi +done + +# Mark: Testing for real + +allLabelsArg=( +"vlc" +"depnotify NOTIFY=all" +"brave NOTIFY=silent" +) + +for labelArg in $allLabelsArg; do + echo $labelArg + label=$(echo $labelArg | cut -d" " -f1 ) + arg1=$(echo $labelArg | cut -d" " -f2 ) + arg2=$(echo $labelArg | cut -d" " -f3 ) + label_name=$( $repo_dir/assemble.sh $label DEBUG=2 RETURN_LABEL_NAME=1 | tail -1 ) + if [[ "$label_name" == "#" ]]; then + echo "${RED}Label $label does not exist. Skipping.${NC}" + else + echo "Label $label: $label_name" + cmd_output=$( sudo $repo_dir/assemble.sh $label $arg1 $arg2 DEBUG=0 LOGGING=DEBUG INSTALL=force BLOCKING_PROCESS_ACTION=quit ) + #echo "$cmd_output" + argument_variables=$( echo $cmd_output | grep -i "setting variable from argument" | sed -E 's/.*setting variable from argument (.*)$/\1/g') + echo $argument_variables + mostWorkAndCheck echo fi done From f2782989cec1217ce206b56664145f8a80ebc4bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 2 Feb 2022 22:01:41 +0100 Subject: [PATCH 57/76] Minor changes --- utils/checkInstallomator.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/checkInstallomator.sh b/utils/checkInstallomator.sh index 2941690..8feb106 100755 --- a/utils/checkInstallomator.sh +++ b/utils/checkInstallomator.sh @@ -56,8 +56,8 @@ if [[ $(sw_vers -buildVersion ) < "18" ]]; then fi echo "TESTING Installoamator" -echo "Version: $($repo_dir/assemble.sh version)\n" -echo "\nRemember to follow log in another terminal window:" +echo "Version: $($repo_dir/assemble.sh version)" +echo "\nRemember to follow log in another terminal window (for the REAL tests):" echo "tail -f /var/log/Installomator.log\n" @@ -122,12 +122,12 @@ for label in $allLabels; do done # Mark: Testing for real - allLabelsArg=( "vlc" "depnotify NOTIFY=all" "brave NOTIFY=silent" ) +echo "\nTesting for REAL:\n" for labelArg in $allLabelsArg; do echo $labelArg From e181a02838545f9503503709ee7f23e796ea49f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Wed, 2 Feb 2022 22:09:40 +0100 Subject: [PATCH 58/76] Update checkInstallomator.sh --- utils/checkInstallomator.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/utils/checkInstallomator.sh b/utils/checkInstallomator.sh index 8feb106..fb99d38 100755 --- a/utils/checkInstallomator.sh +++ b/utils/checkInstallomator.sh @@ -12,7 +12,7 @@ export PATH=/usr/bin:/bin:/usr/sbin:/sbin # MARK: Constants -allLabels=( dbeaverce signal mochatn3270 eshareosx googlechrome brave macports inkscape devonthink omnidisksweeper microsoftteams applenyfonts sketch sqlpropostgres desktoppr marathon) +allLabels=( dbeaverce signal mochatn3270 googlechrome brave macports inkscape devonthink omnidisksweeper microsoftteams applenyfonts sketch sqlpropostgres desktoppr marathon) ## Testing for combinations of these # Label types: dmg, pkg, zip, tbz, pkgInDmg, pkgInZip, appInDmgInZip @@ -21,7 +21,6 @@ allLabels=( dbeaverce signal mochatn3270 eshareosx googlechrome brave macports i # dbeaverse: dmg without appNewVersion and does not have LSMinimumSystemVersion in Info.plist # signal: dmg with appNewVersion # mochatn3270: appInDmgInZip with curlOptions -# eshareosx: with packageID, versionKey, and appNewVerseion # googlechrome: with appNewVersion # brave: dmg with appNewVersion from versionKey # macports: with custom code for archiveName, and with appNewVersion and appCustomVersion From 516f05a4cb3e4b76a4c57b41792327bd810ad660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Thu, 3 Feb 2022 06:32:23 +0100 Subject: [PATCH 59/76] No packageID in eshareosx --- fragments/labels/eshareosx.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fragments/labels/eshareosx.sh b/fragments/labels/eshareosx.sh index d46b9b8..4c173ff 100644 --- a/fragments/labels/eshareosx.sh +++ b/fragments/labels/eshareosx.sh @@ -1,7 +1,7 @@ eshareosx) name="e-Share" type="pkg" - packageID="com.ncryptedcloud.e-Share.pkg" + #packageID="com.ncryptedcloud.e-Share.pkg" downloadURL=https://www.ncryptedcloud.com/static/downloads/osx/$(curl -fs https://www.ncryptedcloud.com/static/downloads/osx/ | grep -o -i "href.*\".*\"" | cut -d '"' -f2) versionKey="CFBundleVersion" appNewVersion=$( echo "${downloadURL}" | sed -E 's/.*\/[a-zA-Z\-]*_([0-9.]*)\.pkg/\1/g' ) From ee9861c0f52dfcef839ed230cc0af07f18aaecfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Fri, 4 Feb 2022 09:02:56 +0100 Subject: [PATCH 60/76] Extra space to align log output --- fragments/functions.sh | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/fragments/functions.sh b/fragments/functions.sh index 6958a13..c0b4c91 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -97,14 +97,21 @@ printlog(){ curl -s -X POST https://http-intake.logs.datadoghq.com/v1/input -H "Content-Type: text/plain" -H "DD-API-KEY: $datadogAPI" -d "${log_priority} : $mdmURL : Installomator-${label} : ${VERSIONDATE//-/} : $SESSION : ${logmessage}" > /dev/null done <<< "$log_message" fi - + + # Extra spaces + space_char="" + if [[ ${#log_priority} -eq 3 ]]; then + space_char=" " + elif [[ ${#log_priority} -eq 4 ]]; then + space_char=" " + fi # If our logging level is greaterthan or equal to our set level then output locally. if [[ ${levels[$log_priority]} -ge ${levels[$LOGGING]} ]]; then while IFS= read -r logmessage; do if [[ "$(whoami)" == "root" ]]; then - echo "$timestamp" : "${log_priority} : $label : ${logmessage}" | tee -a $log_location + echo "$timestamp" : "${log_priority}${space_char} : $label : ${logmessage}" | tee -a $log_location else - echo "$timestamp" : "${log_priority} : $label : ${logmessage}" + echo "$timestamp" : "${log_priority}${space_char} : $label : ${logmessage}" fi done <<< "$log_message" fi From 83c1911248c967489aeeb291f2cd6fd415371364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Fri, 4 Feb 2022 09:26:42 +0100 Subject: [PATCH 61/76] Ended up with double-log-lines --- fragments/functions.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/fragments/functions.sh b/fragments/functions.sh index c0b4c91..45496db 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -515,7 +515,6 @@ mountDMG() { dmgmountOut=$(echo 'Y'$'\n' | hdiutil attach "$tmpDir/$archiveName" -nobrowse -readonly ) dmgmountStatus=$(echo $?) dmgmount=$(echo $dmgmountOut | tail -n 1 | cut -c 54- ) - printlog "dmgmountOut is $dmgmountOut" DEBUG deduplicatelogs "$dmgmountOut" if [[ $dmgmountStatus -ne 0 ]] ; then From 378b16616498bb026b0ba8240d7c11b71f36c2e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Fri, 4 Feb 2022 10:55:14 +0100 Subject: [PATCH 62/76] Labels fixed --- fragments/labels/logitechoptions.sh | 5 +++-- fragments/labels/mattermost.sh | 4 ++-- fragments/labels/tom4aconverter.sh | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/fragments/labels/logitechoptions.sh b/fragments/labels/logitechoptions.sh index c3cf225..125362e 100644 --- a/fragments/labels/logitechoptions.sh +++ b/fragments/labels/logitechoptions.sh @@ -1,8 +1,9 @@ logitechoptions) name="Logitech Options" type="pkgInZip" - downloadURL=$(curl -fs https://support.logi.com/api/v2/help_center/en-us/articles.json | tr "," "\n" | grep -A 10 "macOS" | grep -oie "https.*/.*/options/.*\.zip") - appNewVersion=$(curl -fs https://support.logi.com/api/v2/help_center/en-us/articles.json | tr "," "\n" | grep -A 10 "macOS" | grep -B 5 -ie "https.*/.*/options/.*\.zip" | grep "Software Version" | sed 's/\\u[0-9a-z][0-9a-z][0-9a-z][0-9a-z]//g' | grep -ioe "Software Version.*[0-9.]*" | tr "/" "\n" | grep -oe "[0-9.]*" | head -1) + #downloadURL=$(curl -fs https://support.logi.com/api/v2/help_center/en-us/articles.json | tr "," "\n" | grep -A 10 "macOS" | grep -oie "https.*/.*/options/.*\.zip") + downloadURL="https://download01.logi.com/web/ftp/pub/techsupport/options/options_installer.zip" + #appNewVersion=$(curl -fs https://support.logi.com/api/v2/help_center/en-us/articles.json | tr "," "\n" | grep -A 10 "macOS" | grep -B 5 -ie "https.*/.*/options/.*\.zip" | grep "Software Version" | sed 's/\\u[0-9a-z][0-9a-z][0-9a-z][0-9a-z]//g' | grep -ioe "Software Version.*[0-9.]*" | tr "/" "\n" | grep -oe "[0-9.]*" | head -1) #pkgName="LogiMgr Installer "*".app/Contents/Resources/LogiMgr.pkg" pkgName=LogiMgr.pkg expectedTeamID="QED4VVPZWA" diff --git a/fragments/labels/mattermost.sh b/fragments/labels/mattermost.sh index 532a436..eab4c0a 100644 --- a/fragments/labels/mattermost.sh +++ b/fragments/labels/mattermost.sh @@ -3,7 +3,7 @@ mattermost) type="dmg" archiveName="mac-universal.dmg" downloadURL=$(downloadURLFromGit mattermost desktop) - appNewVersion=$(versionFromGit mattermost desktop ) + appNewVersion=$(versionFromGit mattermost desktop) expectedTeamID="UQ8HT4Q2XM" - Mattermost Helper (Renderer).app app.asar + blockingProcesses=( "Mattermost Helper.app" "Mattermost Helper (Renderer).app" "Mattermost Helper (GPU).app" "Mattermost Helper (Plugin).app" ) ;; diff --git a/fragments/labels/tom4aconverter.sh b/fragments/labels/tom4aconverter.sh index bfc2b77..72dafa4 100644 --- a/fragments/labels/tom4aconverter.sh +++ b/fragments/labels/tom4aconverter.sh @@ -2,6 +2,6 @@ tom4aconverter) name="To M4A Converter" type="dmg" downloadURL="https://amvidia.com/downloads/to-m4a-converter-mac.dmg" - appNewVersion=curl -sf "https://amvidia.com/to-m4a-converter" | grep -o -E '"softwareVersion":.'"{8}" | sed 's/\"//g' | awk -F ': ' '{print $2}' + appNewVersion=$(curl -sf "https://amvidia.com/to-m4a-converter" | grep -o -E '"softwareVersion":.'"{8}" | sed 's/\"//g' | awk -F ': ' '{print $2}') expectedTeamID="F2TH9XX9CJ" ;; From 08e9e634220e55af2d3147a34daa88e8066b9665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Fri, 4 Feb 2022 11:59:51 +0100 Subject: [PATCH 63/76] Align a function and improve checking in `checkLabels` Will now also go through labels with warnings in the, to figure out if the label works. Many warnings are about version checking, so those will be verified now. --- utils/checkInstallomator.sh | 34 ++++++++++++----------- utils/checkLabels.sh | 54 ++++++++++++++++++++++++++++--------- 2 files changed, 60 insertions(+), 28 deletions(-) diff --git a/utils/checkInstallomator.sh b/utils/checkInstallomator.sh index fb99d38..532213d 100755 --- a/utils/checkInstallomator.sh +++ b/utils/checkInstallomator.sh @@ -48,6 +48,12 @@ fragments_dir="$repo_dir/fragments" labels_dir="$fragments_dir/labels" # MARK: Script +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[1;34m' +NC='\033[0m' # No Color + # Check minimal macOS requirement if [[ $(sw_vers -buildVersion ) < "18" ]]; then echo "Installomator requires at least macOS 10.14 Mojave." @@ -59,28 +65,24 @@ echo "Version: $($repo_dir/assemble.sh version)" echo "\nRemember to follow log in another terminal window (for the REAL tests):" echo "tail -f /var/log/Installomator.log\n" - currentUser=$(stat -f "%Su" /dev/console) -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[1;34m' -NC='\033[0m' # No Color +warningLabels="" # variable for labels with warnings +errorLabels="" # variable for labels with errors countWarning=0 countError=0 -mostWorkAndCheck() { +checkCmd_output() { no_appNewVersion=$( echo $cmd_output | grep -ic "Latest version not specified." ) - echo "No appNewVersion: $no_appNewVersion (1 for no)" + #echo "No appNewVersion: $no_appNewVersion (1 for no)" latest_appNewVersion=$( echo $cmd_output | grep -i "Latest version of " | sed -E 's/.* is ([0-9.]*),*.*$/\1/g' ) - echo "Latest version: $latest_appNewVersion" + #echo "Latest version: $latest_appNewVersion" github_label=$( echo $cmd_output | grep -ci "Downloading https://github.com" ) - echo "GitHub: $github_label (1 for true)" + #echo "GitHub: $github_label (1 for true)" downloaded_version=$( echo $cmd_output | grep -ioE "Downloaded (package.*version|version of.*is) [0-9.]*" | grep -v "is the same as installed" | sed -E 's/.* (is|version) ([0-9.]*).*/\2/g' ) - echo "Downloaded version: $downloaded_version" + #echo "Downloaded version: $downloaded_version" exit_status=$( echo $cmd_output | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) - echo "Exit: $exit_status" + #echo "Exit: $exit_status" if [[ ${exit_status} -eq 0 ]] ; then if [[ $no_appNewVersion -eq 1 ]]; then echo "${GREEN}$label works fine, but no appNewVersion.${NC}" @@ -91,6 +93,7 @@ mostWorkAndCheck() { elif [[ $latest_appNewVersion != $downloaded_version && $github_label -eq 0 ]]; then echo "${YELLOW}$label has version warning, with latest $latest_appNewVersion not matching downloaded $downloaded_version.${NC}" ((countWarning++)) + warningLabels+=( "$label" ) echo "$cmd_output" else echo "${RED}$label NOT WORKING:${NC}" @@ -99,7 +102,7 @@ mostWorkAndCheck() { echo "$cmd_output" fi else - echo "${RED}$label NOT WORKING:${NC}" + echo "${RED}$label FAILED with exit code ${exit_status}:${NC}" ((countError++)) errorLabels+=( "$label" ) echo "$cmd_output" @@ -115,7 +118,7 @@ for label in $allLabels; do echo "Label $label: $label_name" cmd_output=$( $repo_dir/assemble.sh $label DEBUG=2 INSTALL=force IGNORE_APP_STORE_APPS=yes BLOCKING_PROCESS_ACTION=ignore ) #echo "$cmd_output" - mostWorkAndCheck + checkCmd_output echo fi done @@ -142,7 +145,7 @@ for labelArg in $allLabelsArg; do #echo "$cmd_output" argument_variables=$( echo $cmd_output | grep -i "setting variable from argument" | sed -E 's/.*setting variable from argument (.*)$/\1/g') echo $argument_variables - mostWorkAndCheck + checkCmd_output echo fi done @@ -156,6 +159,7 @@ else fi if [[ countError -gt 0 ]]; then echo "${RED}ERRORS counted: $countError${NC}" + echo "${YELLOW}${errorLabels}${NC}" else echo "${GREEN}No errors detected!${NC}" fi diff --git a/utils/checkLabels.sh b/utils/checkLabels.sh index fa6144b..5539bba 100755 --- a/utils/checkLabels.sh +++ b/utils/checkLabels.sh @@ -89,6 +89,42 @@ arch () { echo $fixedArch } +checkCmd_output() { + no_appNewVersion=$( echo $cmd_output | grep -ic "Latest version not specified." ) + #echo "No appNewVersion: $no_appNewVersion (1 for no)" + latest_appNewVersion=$( echo $cmd_output | grep -i "Latest version of " | sed -E 's/.* is ([0-9.]*),*.*$/\1/g' ) + #echo "Latest version: $latest_appNewVersion" + github_label=$( echo $cmd_output | grep -ci "Downloading https://github.com" ) + #echo "GitHub: $github_label (1 for true)" + downloaded_version=$( echo $cmd_output | grep -ioE "Downloaded (package.*version|version of.*is) [0-9.]*" | grep -v "is the same as installed" | sed -E 's/.* (is|version) ([0-9.]*).*/\2/g' ) + #echo "Downloaded version: $downloaded_version" + exit_status=$( echo $cmd_output | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) + #echo "Exit: $exit_status" + if [[ ${exit_status} -eq 0 ]] ; then + if [[ $no_appNewVersion -eq 1 ]]; then + echo "${GREEN}$label works fine, but no appNewVersion.${NC}" + elif [[ $latest_appNewVersion == $downloaded_version && $github_label -eq 0 ]]; then + echo "${GREEN}$label works fine, with version $latest_appNewVersion.${NC}" + elif [[ $github_label -eq 1 ]]; then + echo "${GREEN}$label works fine, with GitHub version $latest_appNewVersion.${NC}" + elif [[ $latest_appNewVersion != $downloaded_version && $github_label -eq 0 ]]; then + echo "${YELLOW}$label has version warning, with latest $latest_appNewVersion not matching downloaded $downloaded_version.${NC}" + ((countWarning++)) + warningLabels+=( "$label" ) + echo "$cmd_output" + else + echo "${RED}$label NOT WORKING:${NC}" + ((countError++)) + errorLabels+=( "$label" ) + echo "$cmd_output" + fi + else + echo "${RED}$label FAILED with exit code ${exit_status}:${NC}" + ((countError++)) + errorLabels+=( "$label" ) + echo "$cmd_output" + fi +} # MARK: Script RED='\033[0;31m' @@ -215,22 +251,14 @@ for fixedArch in i386 arm64; do echo "${RED}-> !! ERROR in downloadURL${NC}" labelError=1 fi - if [[ $labelWarning != 0 ]]; then; echo "${YELLOW}########## Warning in label: $label${NC}"; ((countWarning++)); warningLabels+=( "$label" ); fi - if [[ $labelError != 0 ]]; then + if [[ $labelError != 0 || $labelWarning != 0 ]]; then echo "${RED}########## ERROR in label: $label${NC}" echo "Testing using Installomator" - exit_status=$( . $repo_dir/assemble.sh $label DEBUG=2 INSTALL=force IGNORE_APP_STORE_APPS=yes BLOCKING_PROCESS_ACTION=ignore | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) - if [[ ${exit_status} -eq 0 ]] ; then - echo "${GREEN}$label works fine!${NC}" - #errorLabels=("${(@)errorLabels:#$errorLabel}") - else - echo "${RED}$label NOT WORKING!${NC}" - ((countError++)) - errorLabels+=( "$label" ) - fi - + #exit_status=$( . $repo_dir/assemble.sh $label DEBUG=2 INSTALL=force IGNORE_APP_STORE_APPS=yes BLOCKING_PROCESS_ACTION=ignore | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) + cmd_output=$( $repo_dir/assemble.sh $label DEBUG=2 INSTALL=force IGNORE_APP_STORE_APPS=yes BLOCKING_PROCESS_ACTION=ignore ) + #echo "$cmd_output" + checkCmd_output fi - if (($archLabels[(Ie)$label])); then secondRoundLabels+=( "$label" ) fi From 4bc67f3de3eaa45593dac55e55d6694976d2a186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Fri, 4 Feb 2022 14:36:44 +0100 Subject: [PATCH 64/76] Minor logging correction --- fragments/functions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fragments/functions.sh b/fragments/functions.sh index 45496db..ba12731 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -524,7 +524,7 @@ mountDMG() { if [[ ! -e $dmgmount ]]; then cleanupAndExit 3 "Error accessing mountpoint for $tmpDir/$archiveName error:\n$logoutput" ERROR fi - printlog "Debugging enabled, installer output was:\n$logoutput" DEBUG + printlog "Debugging enabled, dmgmount output was:\n$logoutput" DEBUG printlog "Mounted: $dmgmount" INFO } From bb4a396788c41f8a89f6a06173d2b6a93c4247da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Fri, 4 Feb 2022 14:37:03 +0100 Subject: [PATCH 65/76] Renaming file to match primary label name --- fragments/labels/{promiseutilityr.sh => promiseutility.sh} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename fragments/labels/{promiseutilityr.sh => promiseutility.sh} (100%) diff --git a/fragments/labels/promiseutilityr.sh b/fragments/labels/promiseutility.sh similarity index 100% rename from fragments/labels/promiseutilityr.sh rename to fragments/labels/promiseutility.sh From d74036e853228d7040a25a553379c037fb22ecb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 7 Feb 2022 09:42:18 +0100 Subject: [PATCH 66/76] Update logitechoptions.sh --- fragments/labels/logitechoptions.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fragments/labels/logitechoptions.sh b/fragments/labels/logitechoptions.sh index 125362e..14a2a8a 100644 --- a/fragments/labels/logitechoptions.sh +++ b/fragments/labels/logitechoptions.sh @@ -1,9 +1,9 @@ logitechoptions) name="Logitech Options" type="pkgInZip" - #downloadURL=$(curl -fs https://support.logi.com/api/v2/help_center/en-us/articles.json | tr "," "\n" | grep -A 10 "macOS" | grep -oie "https.*/.*/options/.*\.zip") + #downloadURL=$(curl -fs "https://support.logi.com/api/v2/help_center/en-us/articles.json?label_names=webcontent=productdownload,webos=mac-macos-x-11.0" | tr "," "\n" | grep -A 10 "macOS" | grep -oie "https.*/.*/options/.*\.zip" | head -1) downloadURL="https://download01.logi.com/web/ftp/pub/techsupport/options/options_installer.zip" - #appNewVersion=$(curl -fs https://support.logi.com/api/v2/help_center/en-us/articles.json | tr "," "\n" | grep -A 10 "macOS" | grep -B 5 -ie "https.*/.*/options/.*\.zip" | grep "Software Version" | sed 's/\\u[0-9a-z][0-9a-z][0-9a-z][0-9a-z]//g' | grep -ioe "Software Version.*[0-9.]*" | tr "/" "\n" | grep -oe "[0-9.]*" | head -1) + appNewVersion=$(curl -fs "https://support.logi.com/api/v2/help_center/en-us/articles.json?label_names=webcontent=productdownload,webos=mac-macos-x-11.0" | tr "," "\n" | grep -A 10 "macOS" | grep -B 5 -ie "https.*/.*/options/.*\.zip" | grep "Software Version" | sed 's/\\u[0-9a-z][0-9a-z][0-9a-z][0-9a-z]//g' | grep -ioe "Software Version.*[0-9.]*" | tr "/" "\n" | grep -oe "[0-9.]*" | head -1) #pkgName="LogiMgr Installer "*".app/Contents/Resources/LogiMgr.pkg" pkgName=LogiMgr.pkg expectedTeamID="QED4VVPZWA" From d34f3102fc754c624c7c10b41ab396b718aaa07b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 7 Feb 2022 11:40:31 +0100 Subject: [PATCH 67/76] Update checkInstallomator.sh --- utils/checkInstallomator.sh | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/utils/checkInstallomator.sh b/utils/checkInstallomator.sh index 532213d..493ccb8 100755 --- a/utils/checkInstallomator.sh +++ b/utils/checkInstallomator.sh @@ -12,7 +12,18 @@ export PATH=/usr/bin:/bin:/usr/sbin:/sbin # MARK: Constants -allLabels=( dbeaverce signal mochatn3270 googlechrome brave macports inkscape devonthink omnidisksweeper microsoftteams applenyfonts sketch sqlpropostgres desktoppr marathon) + +# Labels to test in DEBUG mode +allLabels=( dbeaverce signal mochatn3270 logitechoptions googlechrome brave macports inkscape devonthink omnidisksweeper microsoftteams applenyfonts sketch sqlpropostgres desktoppr marathon) + +# Labels to test for real (script must be run as root, with sudo, to run) +# Purpose is only toest things that are being skipped in DEBUG mode +allLabelsArg=( +"vlc" +"depnotify NOTIFY=all" +"brave NOTIFY=silent" +) + ## Testing for combinations of these # Label types: dmg, pkg, zip, tbz, pkgInDmg, pkgInZip, appInDmgInZip @@ -21,6 +32,7 @@ allLabels=( dbeaverce signal mochatn3270 googlechrome brave macports inkscape de # dbeaverse: dmg without appNewVersion and does not have LSMinimumSystemVersion in Info.plist # signal: dmg with appNewVersion # mochatn3270: appInDmgInZip with curlOptions +# logitechoptions pkgInZip with pkgName # googlechrome: with appNewVersion # brave: dmg with appNewVersion from versionKey # macports: with custom code for archiveName, and with appNewVersion and appCustomVersion @@ -124,11 +136,6 @@ for label in $allLabels; do done # Mark: Testing for real -allLabelsArg=( -"vlc" -"depnotify NOTIFY=all" -"brave NOTIFY=silent" -) echo "\nTesting for REAL:\n" for labelArg in $allLabelsArg; do From 842b1e19cb9cd09076d28d2ad6276c96c9fc5d63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 7 Feb 2022 12:08:50 +0100 Subject: [PATCH 68/76] Testing `SYSTEMOWNER=1` --- utils/checkInstallomator.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/utils/checkInstallomator.sh b/utils/checkInstallomator.sh index 493ccb8..70db80a 100755 --- a/utils/checkInstallomator.sh +++ b/utils/checkInstallomator.sh @@ -13,7 +13,7 @@ export PATH=/usr/bin:/bin:/usr/sbin:/sbin # MARK: Constants -# Labels to test in DEBUG mode +# Labels to test in DEBUG=2 mode allLabels=( dbeaverce signal mochatn3270 logitechoptions googlechrome brave macports inkscape devonthink omnidisksweeper microsoftteams applenyfonts sketch sqlpropostgres desktoppr marathon) # Labels to test for real (script must be run as root, with sudo, to run) @@ -22,6 +22,7 @@ allLabelsArg=( "vlc" "depnotify NOTIFY=all" "brave NOTIFY=silent" +"handbrake SYSTEMOWNER=1" ) @@ -49,6 +50,13 @@ allLabelsArg=( # Label types not possible to test in DEBUG mode: updateronly # Label fields not possible to test in DEBUG mode: targetDir, blockingProcesses, updateTool, updateToolRunAsCurrentUser, installerTool, CLIInstaller, CLIArguments +# Labels tested for real + +# vlc: app-copy +# depnotify: pkg-install +# brave: app-copy but with few extras +# handbrake: app-copy + # adobecreativeclouddesktop: dmg with appNewVersion and installerTool, CLIInstaller, CLIArguments #setup some folders @@ -121,7 +129,7 @@ checkCmd_output() { fi } -# Mark: First part in DEBUG mode +# Mark: First part in DEBUG=2 mode for label in $allLabels; do label_name=$( $repo_dir/assemble.sh $label DEBUG=2 RETURN_LABEL_NAME=1 | tail -1 ) if [[ "$label_name" == "#" ]]; then From 2a1176a94794d7cfcf2d131807141528be964abc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 7 Feb 2022 12:56:13 +0100 Subject: [PATCH 69/76] Different check for file The ls command to check for this file will throw an error when the file does not exist. Better to simply test for the file (with size greater than zero). --- fragments/functions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fragments/functions.sh b/fragments/functions.sh index ba12731..037086f 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -700,7 +700,7 @@ installPkgInZip() { archiveName="${filearray[1]}" printlog "found pkg: $archiveName" else - if ls "$tmpDir/$pkgName" ; then + if [[ -s "$tmpDir/$pkgName" ]]; then archiveName="$tmpDir/$pkgName" else # try searching for pkg From b3d3f25e1944defb5dd7bcdd8d24a1cb859144c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 7 Feb 2022 14:12:06 +0100 Subject: [PATCH 70/76] Update checkInstallomator.sh --- utils/checkInstallomator.sh | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/utils/checkInstallomator.sh b/utils/checkInstallomator.sh index 70db80a..9a722b9 100755 --- a/utils/checkInstallomator.sh +++ b/utils/checkInstallomator.sh @@ -16,12 +16,13 @@ export PATH=/usr/bin:/bin:/usr/sbin:/sbin # Labels to test in DEBUG=2 mode allLabels=( dbeaverce signal mochatn3270 logitechoptions googlechrome brave macports inkscape devonthink omnidisksweeper microsoftteams applenyfonts sketch sqlpropostgres desktoppr marathon) -# Labels to test for real (script must be run as root, with sudo, to run) +# Labels to test for real (script use sudo to ask for admin rights) # Purpose is only toest things that are being skipped in DEBUG mode allLabelsArg=( "vlc" "depnotify NOTIFY=all" "brave NOTIFY=silent" +"dialog" "handbrake SYSTEMOWNER=1" ) @@ -33,7 +34,7 @@ allLabelsArg=( # dbeaverse: dmg without appNewVersion and does not have LSMinimumSystemVersion in Info.plist # signal: dmg with appNewVersion # mochatn3270: appInDmgInZip with curlOptions -# logitechoptions pkgInZip with pkgName +# logitechoptions pkgInZip with pkgName but without packageID # googlechrome: with appNewVersion # brave: dmg with appNewVersion from versionKey # macports: with custom code for archiveName, and with appNewVersion and appCustomVersion @@ -53,8 +54,9 @@ allLabelsArg=( # Labels tested for real # vlc: app-copy -# depnotify: pkg-install +# depnotify: pkg-install without appNewVersion # brave: app-copy but with few extras +# dialog: pkg from GitHub # handbrake: app-copy # adobecreativeclouddesktop: dmg with appNewVersion and installerTool, CLIInstaller, CLIArguments @@ -93,16 +95,17 @@ countWarning=0 countError=0 checkCmd_output() { - no_appNewVersion=$( echo $cmd_output | grep -ic "Latest version not specified." ) - #echo "No appNewVersion: $no_appNewVersion (1 for no)" - latest_appNewVersion=$( echo $cmd_output | grep -i "Latest version of " | sed -E 's/.* is ([0-9.]*),*.*$/\1/g' ) - #echo "Latest version: $latest_appNewVersion" - github_label=$( echo $cmd_output | grep -ci "Downloading https://github.com" ) - #echo "GitHub: $github_label (1 for true)" - downloaded_version=$( echo $cmd_output | grep -ioE "Downloaded (package.*version|version of.*is) [0-9.]*" | grep -v "is the same as installed" | sed -E 's/.* (is|version) ([0-9.]*).*/\2/g' ) - #echo "Downloaded version: $downloaded_version" - exit_status=$( echo $cmd_output | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) - #echo "Exit: $exit_status" + #echo "$cmd_output" + no_appNewVersion=$( echo "$cmd_output" | grep --binary-files=text -ic "Latest version not specified." ) + echo "No appNewVersion: $no_appNewVersion (1 for no)" + latest_appNewVersion=$( echo "$cmd_output" | grep --binary-files=text -i "Latest version of " | sed -E 's/.* is ([0-9.]*),*.*$/\1/g' ) + echo "Latest version: $latest_appNewVersion" + github_label=$( echo "$cmd_output" | grep --binary-files=text -ci "Downloading https://github.com" ) + echo "GitHub: $github_label (1 for true)" + downloaded_version=$( echo "$cmd_output" | grep --binary-files=text -ioE "Downloaded (package.*version|version of.*is) [0-9.]*" | grep -v "is the same as installed" | sed -E 's/.* (is|version) ([0-9.]*).*/\2/g' ) + echo "Downloaded version: $downloaded_version" + exit_status=$( echo "$cmd_output" | grep --binary-files=text exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) + echo "Exit: $exit_status" if [[ ${exit_status} -eq 0 ]] ; then if [[ $no_appNewVersion -eq 1 ]]; then echo "${GREEN}$label works fine, but no appNewVersion.${NC}" @@ -110,6 +113,8 @@ checkCmd_output() { echo "${GREEN}$label works fine, with version $latest_appNewVersion.${NC}" elif [[ $github_label -eq 1 ]]; then echo "${GREEN}$label works fine, with GitHub version $latest_appNewVersion.${NC}" + elif [[ $downloaded_version == "" ]]; then + echo "${GREEN}$label works fine, but downloaded version can not be checked without packageID.${NC}" elif [[ $latest_appNewVersion != $downloaded_version && $github_label -eq 0 ]]; then echo "${YELLOW}$label has version warning, with latest $latest_appNewVersion not matching downloaded $downloaded_version.${NC}" ((countWarning++)) @@ -158,7 +163,7 @@ for labelArg in $allLabelsArg; do echo "Label $label: $label_name" cmd_output=$( sudo $repo_dir/assemble.sh $label $arg1 $arg2 DEBUG=0 LOGGING=DEBUG INSTALL=force BLOCKING_PROCESS_ACTION=quit ) #echo "$cmd_output" - argument_variables=$( echo $cmd_output | grep -i "setting variable from argument" | sed -E 's/.*setting variable from argument (.*)$/\1/g') + argument_variables=$( echo "$cmd_output" | grep --binary-files=text -i "setting variable from argument" | sed -E 's/.*setting variable from argument (.*)$/\1/g') echo $argument_variables checkCmd_output echo From c238f94a9b761ba03a14bafd2818442eb9ebae39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 7 Feb 2022 14:31:34 +0100 Subject: [PATCH 71/76] Update checkLabels.sh --- utils/checkLabels.sh | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/utils/checkLabels.sh b/utils/checkLabels.sh index 5539bba..c682717 100755 --- a/utils/checkLabels.sh +++ b/utils/checkLabels.sh @@ -90,16 +90,17 @@ arch () { } checkCmd_output() { - no_appNewVersion=$( echo $cmd_output | grep -ic "Latest version not specified." ) - #echo "No appNewVersion: $no_appNewVersion (1 for no)" - latest_appNewVersion=$( echo $cmd_output | grep -i "Latest version of " | sed -E 's/.* is ([0-9.]*),*.*$/\1/g' ) - #echo "Latest version: $latest_appNewVersion" - github_label=$( echo $cmd_output | grep -ci "Downloading https://github.com" ) - #echo "GitHub: $github_label (1 for true)" - downloaded_version=$( echo $cmd_output | grep -ioE "Downloaded (package.*version|version of.*is) [0-9.]*" | grep -v "is the same as installed" | sed -E 's/.* (is|version) ([0-9.]*).*/\2/g' ) - #echo "Downloaded version: $downloaded_version" - exit_status=$( echo $cmd_output | grep exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) - #echo "Exit: $exit_status" + #echo "$cmd_output" + no_appNewVersion=$( echo "$cmd_output" | grep --binary-files=text -ic "Latest version not specified." ) + echo "No appNewVersion: $no_appNewVersion (1 for no)" + latest_appNewVersion=$( echo "$cmd_output" | grep --binary-files=text -i "Latest version of " | sed -E 's/.* is ([0-9.]*),*.*$/\1/g' ) + echo "Latest version: $latest_appNewVersion" + github_label=$( echo "$cmd_output" | grep --binary-files=text -ci "Downloading https://github.com" ) + echo "GitHub: $github_label (1 for true)" + downloaded_version=$( echo "$cmd_output" | grep --binary-files=text -ioE "Downloaded (package.*version|version of.*is) [0-9.]*" | grep -v "is the same as installed" | sed -E 's/.* (is|version) ([0-9.]*).*/\2/g' ) + echo "Downloaded version: $downloaded_version" + exit_status=$( echo "$cmd_output" | grep --binary-files=text exit | tail -1 | sed -E 's/.*exit code ([0-9]).*/\1/g' ) + echo "Exit: $exit_status" if [[ ${exit_status} -eq 0 ]] ; then if [[ $no_appNewVersion -eq 1 ]]; then echo "${GREEN}$label works fine, but no appNewVersion.${NC}" @@ -107,6 +108,8 @@ checkCmd_output() { echo "${GREEN}$label works fine, with version $latest_appNewVersion.${NC}" elif [[ $github_label -eq 1 ]]; then echo "${GREEN}$label works fine, with GitHub version $latest_appNewVersion.${NC}" + elif [[ $downloaded_version == "" ]]; then + echo "${GREEN}$label works fine, but downloaded version can not be checked without packageID.${NC}" elif [[ $latest_appNewVersion != $downloaded_version && $github_label -eq 0 ]]; then echo "${YELLOW}$label has version warning, with latest $latest_appNewVersion not matching downloaded $downloaded_version.${NC}" ((countWarning++)) From ae3f7117383830050fe3a4fbf69c34ea5521c287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 7 Feb 2022 16:32:23 +0100 Subject: [PATCH 72/76] Further logging, finding pkg only return files Important change, when we use `find` to locate pkgs. Now only files will be returned. --- fragments/functions.sh | 8 +++++--- fragments/main.sh | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/fragments/functions.sh b/fragments/functions.sh index 037086f..a851077 100644 --- a/fragments/functions.sh +++ b/fragments/functions.sh @@ -400,6 +400,7 @@ installAppWithPath() { # $1: path to app to install in $targetDir # verify with spctl printlog "Verifying: $appPath" INFO + printlog "App size: $(du -sh "$appPath")" DEBUG appVerify=$(spctl -a -vv "$appPath" 2>&1 ) appVerifyStatus=$(echo $?) teamID=$(echo $appVerify | awk '/origin=/ {print $NF }' | tr -d '()' ) @@ -537,7 +538,8 @@ installFromDMG() { installFromPKG() { # verify with spctl printlog "Verifying: $archiveName" - + printlog "File list: $(ls -lh "$archiveName")" DEBUG + printlog "File type: $(file "$archiveName")" DEBUG spctlOut=$(spctl -a -vv -t install "$archiveName" 2>&1 ) spctlStatus=$(echo $?) printlog "spctlOut is $spctlOut" DEBUG @@ -656,7 +658,7 @@ installPkgInDmg() { # locate pkg in dmg if [[ -z $pkgName ]]; then # find first file ending with 'pkg' - findfiles=$(find "$dmgmount" -iname "*.pkg" -maxdepth 1 ) + findfiles=$(find "$dmgmount" -iname "*.pkg" -type f -maxdepth 1 ) filearray=( ${(f)findfiles} ) if [[ ${#filearray} -eq 0 ]]; then cleanupAndExit 20 "couldn't find pkg in dmg $archiveName" ERROR @@ -691,7 +693,7 @@ installPkgInZip() { # locate pkg in zip if [[ -z $pkgName ]]; then # find first file ending with 'pkg' - findfiles=$(find "$tmpDir" -iname "*.pkg" -maxdepth 2 ) + findfiles=$(find "$tmpDir" -iname "*.pkg" -type f -maxdepth 2 ) filearray=( ${(f)findfiles} ) if [[ ${#filearray} -eq 0 ]]; then cleanupAndExit 20 "couldn't find pkg in zip $archiveName" ERROR diff --git a/fragments/main.sh b/fragments/main.sh index 88b0fbb..1de095f 100644 --- a/fragments/main.sh +++ b/fragments/main.sh @@ -207,8 +207,12 @@ else displaynotification "$message" "Error installing $name" ERROR fi fi + printlog "File list: $(ls -lh "$archiveName")" ERROR + printlog "File type: $(file "$archiveName")" ERROR cleanupAndExit 2 "Error downloading $downloadURL error:\n$logoutput" ERROR fi + printlog "File list: $(ls -lh "$archiveName")" DEBUG + printlog "File type: $(file "$archiveName")" DEBUG printlog "curl output was:\n$logoutput" DEBUG fi From cf414f7dc60aee44a9aa161034973efb21352c9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 7 Feb 2022 16:52:17 +0100 Subject: [PATCH 73/76] Fixing wacomdrivers --- fragments/labels/wacomdrivers.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fragments/labels/wacomdrivers.sh b/fragments/labels/wacomdrivers.sh index 32098be..5be902b 100644 --- a/fragments/labels/wacomdrivers.sh +++ b/fragments/labels/wacomdrivers.sh @@ -1,8 +1,8 @@ wacomdrivers) name="Wacom Desktop Center" type="pkgInDmg" - downloadURL="$(curl -fs https://www.wacom.com/en-us/support/product-support/drivers | grep -e "drivers/mac/professional.*dmg" | head -1 | sed -e 's/data-download-link="//g' -e 's/"//' | awk '{$1=$1}{ print }' | sed 's/\r//')" + downloadURL="$(curl -fs https://www.wacom.com/en-us/support/product-support/drivers | grep -e "drivers/mac/professional.*dmg" | head -1 | tr '"' "\n" | grep -i http)" expectedTeamID="EG27766DY7" - pkgName="Install Wacom Tablet.pkg" - appNewVersion="$(curl -fs https://www.wacom.com/en-us/support/product-support/drivers | grep mac/professional/releasenotes | head -1 | awk -F"|" '{print $1}' | awk -F"Driver" '{print $3}' | sed -e 's/ (.*//g' | tr -d ' ')" + #pkgName="Install Wacom Tablet.pkg" + appNewVersion="$(curl -fs https://www.wacom.com/en-us/support/product-support/drivers | grep mac/professional/releasenotes | head -1 | tr '"' "\n" | grep -e "Driver [0-9][-0-9.]*" | sed -E 's/Driver ([-0-9.]*).*/\1/g')" ;; From 435a60ac9f6c15098bf3d49c4bd6e4334fc091de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 7 Feb 2022 19:11:28 +0100 Subject: [PATCH 74/76] Minor additions --- fragments/labels/wallyezflash.sh | 1 + utils/checkInstallomator.sh | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/fragments/labels/wallyezflash.sh b/fragments/labels/wallyezflash.sh index 17ffb7a..b4444cb 100644 --- a/fragments/labels/wallyezflash.sh +++ b/fragments/labels/wallyezflash.sh @@ -2,6 +2,7 @@ wallyezflash) name="Wally" type="dmg" downloadURL="https://configure.zsa.io/wally/osx" + # 2022-02-07: Info.plist is totally wrong defined and contains no version information #appNewVersion=$(curl -fsIL "${downloadURL}" | grep -i ^location | head -1 | sed -E 's/.*\/[a-zA-Z\-]*-([0-9.]*)\..*/\1/g') expectedTeamID="V32BWKSNYH" #versionKey="CFBundleVersion" diff --git a/utils/checkInstallomator.sh b/utils/checkInstallomator.sh index 9a722b9..dcfb3f4 100755 --- a/utils/checkInstallomator.sh +++ b/utils/checkInstallomator.sh @@ -14,7 +14,7 @@ export PATH=/usr/bin:/bin:/usr/sbin:/sbin # MARK: Constants # Labels to test in DEBUG=2 mode -allLabels=( dbeaverce signal mochatn3270 logitechoptions googlechrome brave macports inkscape devonthink omnidisksweeper microsoftteams applenyfonts sketch sqlpropostgres desktoppr marathon) +allLabels=( dbeaverce signal malwarebytes mochatn3270 logitechoptions googlechrome brave macports inkscape devonthink omnidisksweeper microsoftteams applenyfonts sketch sqlpropostgres desktoppr marathon) # Labels to test for real (script use sudo to ask for admin rights) # Purpose is only toest things that are being skipped in DEBUG mode @@ -33,9 +33,10 @@ allLabelsArg=( # dbeaverse: dmg without appNewVersion and does not have LSMinimumSystemVersion in Info.plist # signal: dmg with appNewVersion +# malwarebytes: pkg with appNewVersion but not packageID # mochatn3270: appInDmgInZip with curlOptions # logitechoptions pkgInZip with pkgName but without packageID -# googlechrome: with appNewVersion +# googlechrome: dmg with appNewVersion # brave: dmg with appNewVersion from versionKey # macports: with custom code for archiveName, and with appNewVersion and appCustomVersion # inkscape: dmg with appCustomVersion From 7d60f0a11f47f55e40fe09f24df8127041860f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 7 Feb 2022 19:19:57 +0100 Subject: [PATCH 75/76] Can handle .gz archives --- utils/buildLabel.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/buildLabel.sh b/utils/buildLabel.sh index a6de0c1..6b200df 100755 --- a/utils/buildLabel.sh +++ b/utils/buildLabel.sh @@ -265,7 +265,7 @@ echo "archivePath: $archivePath" # So we want to investigate which one has the filename try1archiveName=${${archiveTempName##*/}%%\?*} try2archiveName=${${archivePath##*/}%%\?*} -fileName_re='^([a-zA-Z0-9\_.%-]*)\.(dmg|pkg|zip|tbz)$' # regular expression for matching +fileName_re='^([a-zA-Z0-9\_.%-]*)\.(dmg|pkg|zip|tbz|gz)$' # regular expression for matching if [[ "${try1archiveName}" =~ $fileName_re ]]; then archiveName=${try1archiveName} elif [[ "${try2archiveName}" =~ $fileName_re ]]; then From 806c87266b93b51471fb42bf85e5c7719ba8f0a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Theilgaard?= Date: Mon, 7 Feb 2022 19:38:48 +0100 Subject: [PATCH 76/76] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22ab930..6286983 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,9 @@ Big changes to logging: - A function to shorten duplicate lines in installation logs or output of longer commands - Ability to extract install.log in the time when Installomator was running, if further investigations needs to be done to logs +Fixes: +- Fixed a problem with pkgs: If they were mounted with .pkg in the name, then we would find the directory and not the pkg file itself. +- Minor fix for a check for a pkgName on a DMG. We used `ls` that would throw an error when not found, so the check was corrected. ## v8.0