├── .gitignore ├── FileVault_Status_Report.sh ├── LICENSE ├── README.md ├── Sophos Scripts ├── sophosInstall.sh └── sophosUninstall.sh ├── installGenericPKG.sh └── seedChannelReport.sh /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /FileVault_Status_Report.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Written by Trevor Sysock, Second Son Consulting 4 | #v. 1.0 5 | 6 | FDE_STATUS=$(fdesetup status) 7 | ESCROW_PLIST="/var/db/ConfigurationProfiles/Settings/com.apple.security.FDERecoveryKeyEscrow.plist" 8 | 9 | echo -n "$FDE_STATUS " 10 | 11 | if [ "FileVault is On." != "$FDE_STATUS" ]; then 12 | exit 0 13 | fi 14 | 15 | if [ -a "$ESCROW_PLIST" ]; then 16 | echo "Key Set to be Escrowed to: $(defaults read "$ESCROW_PLIST" Location)" 17 | else 18 | echo "KEY NOT ESCROWED" 19 | fi 20 | 21 | exit 0 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # macOS-Scripts 2 | A collection of useful macOS scripts we've made to share with the community 3 | 4 | -------------------------------------------------------------------------------- /Sophos Scripts/sophosInstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #set -x 3 | 4 | ##Written by Trevor Sysock (aka @bigmacadmin) at Second Son Consulting Inc. 5 | # 6 | #Usage: 7 | # Change the "downloadURL" variable to match the specific Sophos environment you are installing for. 8 | # Can be run as a Mosyle Custom Command or locally. 9 | # If Sophos is already installed, the installer errors out. 10 | # Any other step in the script that fails will produce an easily read error report to standard output. 11 | # Find "YOUR_SOPHOS_URL" by using developer tools in your browser to identify the URL when you click the "Protect Devices" download 12 | 13 | ###################################### 14 | # 15 | # User Configuration 16 | # 17 | ###################################### 18 | 19 | #Every Sophos environment needs its own unique URL. 20 | #If using the Mosyle CDN variable, you can omit the "quotation marks" 21 | #This can be passed as an argument, or defined in the script. If there's a conflict, the one passed as an argument wins. 22 | downloadURL="" 23 | 24 | if [[ ${1:0:4} == "http" ]]; then 25 | # Appears a URL was passed as a script argument. Setting the downloadURL accordingly. 26 | downloadURL="${1}" 27 | fi 28 | 29 | ###################################### 30 | # 31 | # Do not modify below for normal use 32 | # 33 | ###################################### 34 | 35 | function cleanup_and_exit() 36 | { 37 | rm -r "$tmpDir" 38 | exit $@ 39 | } 40 | 41 | #Make tmp folder 42 | tmpDir=$(mktemp -d /var/tmp/SSC-SophosInstall.XXXXXX) 43 | 44 | #Declare primary working directory 45 | installDir="$tmpDir/SophosInstall" 46 | 47 | #Check if the downloadURL was actually provided 48 | if [ -z $downloadURL ]; then 49 | echo "ERROR: No download URL provided" 50 | cleanup_and_exit 1 51 | fi 52 | 53 | #Download installer to tmp folder 54 | curl -LJs "$downloadURL" -o "$tmpDir"/SophosInstall.zip 55 | downloadResult=$? 56 | 57 | #Verify curl exited with 0 58 | if [ "$downloadResult" != 0 ]; then 59 | echo "Download failed. Exiting." 60 | cleanup_and_exit 1 61 | fi 62 | 63 | #Unzip silently to tmp dir 64 | unzip -qq "$installDir".zip -d "$installDir" 65 | unzipResult=$? 66 | 67 | #Verify unzip exited with 0 68 | if [ "$unzipResult" != 0 ]; then 69 | echo "Unzip failed. Exiting." 70 | cleanup_and_exit 1 71 | fi 72 | 73 | #Verify TeamIdentifier matches the expected 74 | 75 | expectedTeamID='TeamIdentifier=2H5GFH3774' 76 | actualTeamID=$(codesign -dv "$installDir/Sophos Installer.app" 2>&1 | grep "TeamIdentifier") 77 | 78 | if [[ "$expectedTeamID" != "$actualTeamID" ]]; then 79 | echo "Verification Failed" 80 | echo "Expected Team Identifier: $expectedTeamID" 81 | echo "Actual Team Identifier: $actualTeamID" 82 | cleanup_and_exit 1 83 | fi 84 | 85 | #Set executables 86 | chmod a+x "$installDir/Sophos Installer.app/Contents/MacOS/Sophos Installer" 87 | chmod a+x "$installDir/Sophos Installer.app/Contents/MacOS/tools/com.sophos.bootstrap.helper" 88 | 89 | #Run the installer and capture output to variable in case of error 90 | sophosExitMessage=$( { "$installDir/Sophos Installer.app/Contents/MacOS/Sophos Installer" --install > "$tmpDir"/fail.txt; } 2>&1 ) 91 | installResult=$(echo $?) 92 | #Verify install exited with 0 93 | if [ "$installResult" != 0 ]; then 94 | echo "Install failed." 95 | echo "$sophosExitMessage" 96 | cleanup_and_exit 1 97 | fi 98 | 99 | #No failures. Cleanup and exit 100 | echo "Success" 101 | cleanup_and_exit 0 102 | -------------------------------------------------------------------------------- /Sophos Scripts/sophosUninstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #set -x 3 | 4 | echo -n "Sophos Uninstall: " 5 | 6 | sudo rm /Library/Sophos\ Anti-Virus/SophosSecure.keychain 7 | sudo defaults write /Library/Preferences/com.sophos.sav TamperProtectionEnabled -bool false 8 | sudo /Library/Application\ Support/Sophos/saas/Installer.app/Contents/MacOS/tools/InstallationDeployer --remove 9 | SOPHOS_UNINSTALL_STATUS=$? 10 | if [ $SOPHOS_UNINSTALL_STATUS != 0 ]; then 11 | /bin/echo "***WARNING*** SOPHOS DID NOT UNINSTALL SUCCESSFULLY ***WARNING***" 12 | fi -------------------------------------------------------------------------------- /installGenericPKG.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #set -x 3 | 4 | verboseMode=false 5 | 6 | scriptVersion="v2.4" 7 | 8 | ##Written by Trevor Sysock (aka @bigmacadmin) at Second Son Consulting Inc. 9 | # 10 | # THIS SOFTWARE IS BEING PROVIDED WITH THE ASSOCIATED LICENSE ON GITHUB: 11 | # https://github.com/SecondSonConsulting/macOS-Scripts 12 | # 13 | # This is provided with no warranty or assurances of any kind, please review in detail prior to use 14 | # 15 | ######################################################################## 16 | # # 17 | # Covered Software is provided under this License on an "as is" # 18 | # basis, without warranty of any kind, either expressed, implied, or # 19 | # statutory, including, without limitation, warranties that the # 20 | # Covered Software is free of defects, merchantable, fit for a # 21 | # particular purpose or non-infringing. The entire risk as to the # 22 | # quality and performance of the Covered Software is with You. # 23 | # Should any Covered Software prove defective in any respect, You # 24 | # (not any Contributor) assume the cost of any necessary servicing, # 25 | # repair, or correction. This disclaimer of warranty constitutes an # 26 | # essential part of this License. No use of any Covered Software is # 27 | # authorized under this License except under this disclaimer. # 28 | # # 29 | ######################################################################## 30 | # 31 | #Usage: 32 | # Can be run as a Mosyle Custom Command or locally. 33 | # Any step in the script that fails will produce an easily read error report to standard output. 34 | # Uncomment set -x and/or verboseMode=true at the top of the script for advanced debugging 35 | 36 | # Arguments can be defined here in the script, or passed at the command line. 37 | # If passed at the command line, arguments MUST BE IN THE FOLLOWING ORDER: 38 | # ./installGenericPKG.sh [pathtopackage] [md5 | TeamID] 39 | 40 | # TeamID and MD5 are not required fields, but are strongly recommended to ensure you install 41 | # what you think you are installing. 42 | 43 | # PKGs can be validated prior to install by either the TeamID or an MD5 hash. 44 | # If both TeamID and MD5 are defined in the script, both will be checked. 45 | # When running from the command line, md5 and TeamID can be passed as either argument 2 or 3 or both 46 | # 47 | # Example: Download a PKG at https://test.example.host.tld/Remote.pkg and verify by TeamID 48 | # ./installGenericPKG.sh https://test.example.host.tld/Remote.pkg 7Q6XP5698G 49 | # 50 | # Example: Run a PKG from the local disk and verify by TeamID and MD5 51 | # ./installGenericPKG.sh /path/to/installer.pkg 7Q6XP5698G 9741c346eeasdf31163e13b9db1241b3 52 | # 53 | 54 | # Additional features have been added since the original release. These features are not supported 55 | # when using command line arguments, and must be configured within the script 56 | 57 | # Package Identifier. 58 | # If you fill out this option, you also must fill out the pkgVersion option. 59 | # If this option is included, the script will exit if the same version of this pkg has already been successfully installed on the device. 60 | # The script only prevents install if the expectedPackageVersion is an exact match. 61 | # Example: expectedPackageID="com.secondsonconsulting.pkg.Renew" expectedPackageVersion="1.0.1" 62 | 63 | # Package in Zip 64 | # This script supports pkgs contained within a .zip 65 | # Some packages use the old style bundle format (such as Adobe CC custom PKGs) and this doesn't play well with curl, etc. 66 | # Set the pkgInZip=true option to add steps to unzip the download prior to running the package contained within 67 | # When using the expectedMD5 validation option in conjunciton with pkgInZip, you MUST specify the md5 checksum of the .zip file, not the pkg within 68 | # TeamID is still supported with pkgInZip, and will be checked against the package after being unzipped 69 | # DO NOT include multiple pkgs in your zip file. Other files can be bundled in the zip, and will be unzipped right beside your pkg 70 | 71 | ###################################### 72 | # 73 | # User Configuration 74 | # 75 | ###################################### 76 | 77 | # This is low consequence, and only used for the temp directory. Make it something meaningful to you. No special characters. 78 | # This can typically be left as default: nameOfInstall="InstallPKG" 79 | nameOfInstall="InstallPKG" 80 | 81 | # Where is the PKG located? 82 | pathToPKG="" 83 | 84 | # Is this PKG inside a .zip? Must be either true or false or unset 85 | #pkgInZip=true 86 | pkgInZip=false 87 | 88 | # TeamID value is optional, but recommended. If not in use, this should read: expectedTeamID="" 89 | # Get this by running this command against your package: spctl -a -vv -t install /path/to/package.pkg 90 | expectedTeamID="" 91 | 92 | # MD5 value is optional, but recommended. If not in use, this should read: expectedMD5="" 93 | # Get this by running this command against your package: md5 -q /path/to/package.pkg 94 | expectedMD5="" 95 | 96 | # Package Identifier and Expected Version. If the device already has a receipt for this package ID for the specified version, script will exit 97 | expectedPackageID="" 98 | 99 | expectedPackageVersion="" 100 | 101 | ###################################### 102 | # 103 | # Do not modify below for normal use 104 | # 105 | ###################################### 106 | 107 | scriptName=$(basename "$0") 108 | 109 | ################# 110 | # Functions # 111 | ################# 112 | 113 | function verify_root_user() 114 | { 115 | # check we are running as root 116 | if [[ $(id -u) -ne 0 ]]; then 117 | echo "ERROR: This script must be run as root **EXITING**" 118 | exit 1 119 | fi 120 | 121 | } 122 | 123 | function rm_if_exists() 124 | { 125 | #Only rm something if the variable has a value and the thing exists! 126 | if [ -n "${1}" ] && [ -e "${1}" ];then 127 | rm -r "${1}" 128 | fi 129 | } 130 | 131 | #This function exits the script, deleting the temp files. first argument is the exit code, second argument is the message reported. 132 | #example: cleanup_and_exit 1 "Download Failed." 133 | function cleanup_and_exit() 134 | { 135 | echo "${2}" 136 | rm_if_exists "$tmpDir" 137 | kill "$caffeinatepid" > /dev/null 2>&1 138 | exit "$1" 139 | } 140 | 141 | # Prevent the computer from sleeping while this is running, capture the PID of caffeinate so we can kill it in our exit function 142 | function no_sleeping() 143 | { 144 | 145 | /usr/bin/caffeinate -d -i -m -u & 146 | caffeinatepid=$! 147 | 148 | } 149 | 150 | # Used in debugging to give feedback via standard out 151 | function debug_message() 152 | { 153 | #set +x 154 | if "$verboseMode"; then 155 | /bin/echo "DEBUG: $*" 156 | fi 157 | #set -x 158 | } 159 | 160 | # Check if the specified expectedPackageID and version have already run on this machine 161 | function check_package_receipt(){ 162 | # If the expectedPackageID variable is not empty 163 | if [ ! -z "$expectedPackageID" ] || [ ! -z "$expectedPackageVersion" ];then 164 | # Verify a version has also been included. Otherwise, exit with an error (this is a misconfiguration) 165 | if [ -z "$expectedPackageID" ] || [ -z "$expectedPackageVersion" ]; then 166 | cleanup_and_exit 1 "ERROR: Misconfiguration. Both expectedPackageID and expectedPackageVersion are required if using that feature." 167 | fi 168 | # Check the receipts and get the version if it exists 169 | installedPackageVersion=$(/usr/libexec/PlistBuddy -c 'Print :pkg-version' /dev/stdin <<< "$(pkgutil --pkg-info-plist "$expectedPackageID" 2> /dev/null)" 2> /dev/null) 170 | # Check if the install is not needed 171 | if [[ "$installedPackageVersion" == "$expectedPackageVersion" ]]; then 172 | echo "$scriptName - $scriptVersion" 173 | echo "$(date '+%Y%m%dT%H%M%S%z'): " 174 | echo "Package ID $expectedPackageID is already on $expectedPackageVersion no action needed" 175 | cleanup_and_exit 0 "Success" 176 | else 177 | echo "No receipt for $expectedPackageID $expectedPackageVersion - Proceeding with install" 178 | fi 179 | else 180 | echo "No Package ID defined" 181 | fi 182 | } 183 | 184 | # This is a report regarding the installation details that gets printed prior to the script actually running 185 | function preinstall_summary_report() 186 | { 187 | echo "$scriptName - $scriptVersion" 188 | echo "$(date '+%Y%m%dT%H%M%S%z'): " 189 | echo "Location: $pathToPKG" 190 | echo "Location Type: $pkgLocationType" 191 | echo "Expected MD5 is: $expectedMD5" 192 | echo "Expected TeamID is: $expectedTeamID" 193 | #If there is no TeamID and no MD5 verification configured print a warning 194 | if [ -z "$expectedTeamID" ] && [ -z "$expectedMD5" ]; then 195 | echo "**WARNING: No verification of the PKG before it is installed. Provide an MD5 or TeamID for better security and stability.**" 196 | fi 197 | } 198 | 199 | #This function will download the pkg (if it is hosted via url) and then verify the MD5 or TeamID if provided. 200 | function download_pkg() 201 | { 202 | # First, check if we're downloading a pkg or a zip 203 | if [ ! -z $pkgInZip ] && $pkgInZip; then 204 | downloadFileType="zip" 205 | else 206 | downloadFileType="pkg" 207 | fi 208 | # Next, check if we have to download the PKG 209 | if [ "$pkgLocationType" = "url" ]; then 210 | pkgInstallerPath="$tmpDir"/"$nameOfInstall.$downloadFileType" 211 | #Download installer to tmp folder 212 | curl -LJs "$pathToPKG" -o "$pkgInstallerPath" 213 | downloadResult=$? 214 | #Verify curl exited with 0 215 | if [ "$downloadResult" != 0 ]; then 216 | cleanup_and_exit 1 "Download failed. Exiting." 217 | fi 218 | debug_message "Download completed." 219 | else 220 | #If the PKG is a local file, set our installer path variable accordingly 221 | pkgInstallerPath="$pathToPKG" 222 | fi 223 | } 224 | 225 | function unzip_the_download(){ 226 | ditto -x -k "$pkgInstallerPath" "$tmpDir" 227 | dittoResult=$? 228 | #Verify ditto exited with 0 229 | if [ "$dittoResult" != 0 ]; then 230 | cleanup_and_exit 1 "Ditto/Unzip failed. Exiting." 231 | fi 232 | pkgInstallerPath=$(find "$tmpDir" -name "*.pkg") 233 | 234 | } 235 | 236 | function check_md5(){ 237 | # If an expectedMD5 was given, test against the actual installer and exit upon mismatch 238 | actualMD5=$(md5 -q "$pkgInstallerPath" 2>/dev/null) 239 | if [ -n "$expectedMD5" ] && [ "$actualMD5" != "$expectedMD5" ]; then 240 | cleanup_and_exit 1 "ERROR - MD5 mismatch. Exiting." 241 | fi 242 | 243 | 244 | } 245 | 246 | function verify_pkg() 247 | { 248 | # If an expectedTeamID was given, test against the actual installer and exit upon mismatch 249 | actualTeamID=$(spctl -a -vv -t install "$pkgInstallerPath" 2>&1 | awk -F '(' '/origin=/ {print $2 }' | tr -d ')' ) 250 | # If an TeamID was given, test against the actual installer and exit upon mismatch 251 | if [ -n "$expectedTeamID" ] && [ "$actualTeamID" != "$expectedTeamID" ]; then 252 | cleanup_and_exit 1 "ERROR - TeamID mismatch. Exiting." 253 | fi 254 | 255 | #Lets take an opportunity to just verify that the PKG we're installing actually exists 256 | if [ ! -e "$pkgInstallerPath" ]; then 257 | cleanup_and_exit 1 "ERROR - PKG does not exist at this location: $pkgInstallerPath" 258 | fi 259 | 260 | } 261 | 262 | function install_pkg() 263 | { 264 | #Run the pkg and capture output to variable in case of error 265 | installExitMessage=$( { installer -allowUntrusted -pkg "$pkgInstallerPath" -target / > "$tmpDir"/fail.txt; } 2>&1 ) 266 | installResult=$? 267 | 268 | #Verify install exited with 0 269 | if [ "$installResult" != 0 ]; then 270 | cleanup_and_exit 1 "Installation command failed: $installExitMessage" 271 | fi 272 | 273 | } 274 | 275 | ################################# 276 | # Validate and Process Input # 277 | ################################# 278 | 279 | # $1 - The first argument is the path to the PKG (either url or filepath). If no argument, fall back to script configuration. 280 | if [ "$1" = "" ]; then 281 | debug_message "No PKG defined in command-line arguments, defaulting to script configuration" 282 | else 283 | pathToPKG="${1}" 284 | fi 285 | 286 | # Look at the given path to PKG, and determine if its a local file path or a URL. 287 | if [[ ${pathToPKG:0:4} == "http" ]]; then 288 | # The path to the PKG appears to be a URL. 289 | pkgLocationType="url" 290 | elif [ -e "$pathToPKG" ]; then 291 | # The path to the PKG appears to exist on the local file system 292 | pkgLocationType="filepath" 293 | else 294 | #Some kind of invalid input, not starting with a / or with http. Exit with an error 295 | cleanup_and_exit 1 "Path to PKG appears to be invalid or undefined." 296 | fi 297 | 298 | # $2 - The second argument is either an MD5 or a TeamID. 299 | if [ "${2}" = "" ]; then 300 | debug_message "No Verification Value defined in command-line arguments, defaulting to script configuration" 301 | elif [ ${#2} = 10 ]; then 302 | #The second argument is 10 characters, which indicates a TeamID. 303 | expectedTeamID="${2}" 304 | elif [ ${#2} = 32 ]; then 305 | #The second argument is 10 characters, which indicates an MD5 hash 306 | expectedMD5="${2}" 307 | else 308 | #There appears to be something wrong with the validation input, exit with an error 309 | cleanup_and_exit 1 "TeamID or MD5 passed at command line appear to be invalid. Expecting 10 characters for TeamID or 32 for MD5." 310 | fi 311 | 312 | # $3 - The third argument is either an MD5 or a TeamID. 313 | if [ "${3}" = "" ]; then 314 | debug_message "Argument 3 is empty. Defaulting to script configuration" 315 | elif [ ${#3} = 10 ]; then 316 | #The second argument is 10 characters, which indicates a TeamID. 317 | expectedTeamID="${3}" 318 | elif [ ${#3} = 32 ]; then 319 | #The second argument is 10 characters, which indicates an MD5 hash 320 | expectedMD5="${3}" 321 | else 322 | #There appears to be something wrong with the validation input, exit with an error 323 | cleanup_and_exit 1 "TeamID or MD5 passed at command line appear to be invalid. Expecting 10 characters for TeamID or 32 for MD5." 324 | fi 325 | 326 | ########################## 327 | # Script Starts Here # 328 | ########################## 329 | 330 | #Trap will hopefully run our exit function even if the script is cancelled or interrupted 331 | trap cleanup_and_exit 1 2 3 6 332 | 333 | #Make sure we're running with root privileges 334 | verify_root_user 335 | 336 | #Print the preinstall Summary 337 | preinstall_summary_report 338 | 339 | # Check whether this package has already been successfully installed 340 | check_package_receipt 341 | 342 | #Create a temporary working directory 343 | tmpDir=$(mktemp -d /var/tmp/"$nameOfInstall".XXXXXX) 344 | 345 | # Don't let the computer sleep until we're done 346 | no_sleeping 347 | 348 | #Download happens here, if needed 349 | download_pkg 350 | 351 | #MD5 verification happens here 352 | check_md5 353 | 354 | # If the PKG is in a zip, unzip it 355 | if [ ! -z $pkgInZip ] && $pkgInZip; then 356 | unzip_the_download 357 | fi 358 | 359 | #TeamID verification happens here 360 | verify_pkg 361 | 362 | #If we haven't exited yet, then the PKG was verified and we can install 363 | install_pkg 364 | 365 | #If we still haven't exited, that means there have been no failures detected. Cleanup and exit 366 | cleanup_and_exit 0 "Success" 367 | -------------------------------------------------------------------------------- /seedChannelReport.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | #Trevor Sysock (@BigMacAdmin) Second Son Consulting Inc. 4 | 5 | #Verify running as root 6 | if [ $(id -u) != 0 ]; then 7 | echo "Script must be run as root" 8 | exit 1 9 | fi 10 | 11 | #Gather the current OS build information. Pipe to xargs is used to trim leading whitespace 12 | CURRENT_OS_BUILD=$(system_profiler SPSoftwareDataType | grep "System Version: " | xargs) 13 | 14 | #Gather information regarding what beta enrollment channel this device is in. 15 | BETA_CHECK=$(/System/Library/PrivateFrameworks/Seeding.framework/Resources/seedutil current) 16 | BETA_RESULT=$(echo "${BETA_CHECK}" |grep "Currently enrolled in: ") 17 | 18 | 19 | #Feedback/Report begins here 20 | echo -n "${CURRENT_OS_BUILD}" 21 | 22 | #Give a warning if the machine is part of a beta channel 23 | if [ "Currently enrolled in: (null)" = "${BETA_RESULT}" ]; then 24 | echo " - Not enrolled in a beta channel." 25 | else 26 | echo " - ***WARNING*** - THIS DEVICE IS ENROLLED IN A MACOS BETA CHANNEL ***WARNING***" 27 | echo "Beta Enrollment Details: " 28 | echo "${BETA_CHECK}" 29 | fi --------------------------------------------------------------------------------