-
Notifications
You must be signed in to change notification settings - Fork 37
Expand file tree
/
Copy pathmacOSMaxVersionCheck-EA.sh
More file actions
131 lines (109 loc) · 4.89 KB
/
macOSMaxVersionCheck-EA.sh
File metadata and controls
131 lines (109 loc) · 4.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/bin/zsh --no-rcs
# shellcheck shell=bash
# Check latest available compatible version of macOS using SOFA
# by Graham Pugh
#
# To use in a Smart Groups to scope computers based on max compatible macOS, e.g.:
# macOS Max Version - is - 14
#
# For example, when using erase-install, you may wish to prevent Macs compatible with macOS 15 from
# upgrading to macOS 15, but wish for all older Macs to get the max compatible version.
# In this case you can scope one policy to computers where Max Version is 15 with
# erase-install.sh --os 14`, and another policy to other computers (Max Version is not 15)
# where you don't specify an --os value.
# autoload is-at-least module for version comparisons
autoload is-at-least
# Get current system OS
system_version=$( /usr/bin/sw_vers -productVersion )
# system_version=14.1 # UNCOMMENT AND ADJUST TO TEST OLDER VERSIONS
system_os=$(cut -d. -f1 <<< "$system_version")
echo "System Version: $system_version"
if [[ $system_os -ge 12 ]]; then
# use plistlib
os_compatibility="current"
else
# use python 2.7
os_compatibility="legacy"
python_path="/usr/bin/python"
fi
# URL to the online JSON data
online_json_url="https://sofafeed.macadmins.io/v1/macos_data_feed.json"
user_agent="SOFA-Jamf-EA-macOSMaxVersionCheck/1.1"
# local store
json_cache_dir="/private/var/tmp/sofa"
json_cache="$json_cache_dir/macos_data_feed.json"
etag_cache="$json_cache_dir/macos_data_feed_etag.txt"
etag_cache_temp="$json_cache_dir/macos_data_feed_etag_temp.txt"
# ensure local cache folder exists
/bin/mkdir -p "$json_cache_dir"
# check local vs online using etag (only available on macOS 12+)
if [[ -f "$etag_cache" && -f "$json_cache" ]]; then
etag_old=$(/bin/cat "$etag_cache")
/usr/bin/curl --compressed --silent --etag-compare "$etag_cache" --etag-save "$etag_cache_temp" --header "User-Agent: $user_agent" "$online_json_url" --output "$json_cache"
etag_temp=$(/bin/cat "$etag_cache_temp")
if [[ "$etag_old" == "$etag_temp" || $etag_temp == "" ]]; then
echo "Cached ETag matched online ETag - cached json file is up to date"
/bin/rm "$etag_cache_temp"
else
echo "Cached ETag did not match online ETag, so downloaded new SOFA json file"
/bin/mv "$etag_cache_temp" "$etag_cache"
fi
elif [[ "$os_compatibility" == "legacy" ]]; then
echo "OS not compatible with e-tags, proceeding to download SOFA json file"
/usr/bin/curl --compressed --location --max-time 3 --silent --header "User-Agent: $user_agent" "$online_json_url" --output "$json_cache"
else
echo "No e-tag or SOFA json file cached, proceeding to download SOFA json file"
/usr/bin/curl --compressed --location --max-time 3 --silent --header "User-Agent: $user_agent" "$online_json_url" --etag-save "$etag_cache" --output "$json_cache"
fi
echo
if [[ ! -f "$json_cache" ]]; then
echo "<result>Could not obtain data</result>"
exit
elif [[ "$os_compatibility" == "legacy" ]]; then
if ! "$python_path" -c 'import sys, json; print json.load(sys.stdin)["UpdateHash"]' < "$json_cache" > /dev/null; then
echo "<result>Could not obtain data</result>"
exit
fi
elif ! /usr/bin/plutil -extract "UpdateHash" raw "$json_cache" > /dev/null; then
echo "<result>Could not obtain data</result>"
exit
fi
echo
# 1. Get model (DeviceID)
model=$(/usr/sbin/sysctl -n hw.model)
echo "Model Identifier: $model"
# check that the model is virtual or is in the feed at all
if [[ $model == "VirtualMac"* ]]; then
# if virtual, we need to arbitrarily choose a model that supports all current OSes. Plucked for an M1 Mac mini
model="Macmini9,1"
elif ! grep -q "$model" "$json_cache"; then
echo "<result>Unsupported Hardware</result>"
exit
fi
# 2. Get current system OS
system_version=$( /usr/bin/sw_vers -productVersion )
# system_version=14.1 # UNCOMMENT TO TEST OLDER VERSIONS
system_os=$(cut -d. -f1 <<< "$system_version")
echo "System Version: $system_version"
echo
# exit if less than macOS 12
if ! is-at-least 12 "$system_os"; then
echo "<result>Unsupported macOS</result>"
exit
fi
# 3. idenfity latest compatible major OS
latest_compatible_os=$(/usr/bin/plutil -extract "Models.$model.SupportedOS.0" raw -expect string "$json_cache" | /usr/bin/head -n 1)
latest_compatible_os_version=$(/usr/bin/cut -d' ' -f2 <<< "$latest_compatible_os")
echo "Latest Compatible macOS: $latest_compatible_os_version"
# 4. Get OSVersions.Latest.ProductVersion
for i in {0..3}; do
os_version=$(/usr/bin/plutil -extract "OSVersions.$i.OSVersion" raw "$json_cache" | /usr/bin/head -n 1 | grep -v "<stdin>")
if [[ $os_version ]]; then
if [[ "$os_version" == "$latest_compatible_os" ]]; then
product_version=$(/usr/bin/plutil -extract "OSVersions.$i.Latest.ProductVersion" raw "$json_cache" | /usr/bin/head -n 1)
echo "Latest Compatible macOS Version: $product_version"
fi
fi
done
echo
echo "<result>$latest_compatible_os_version</result>"