Quantcast
Channel: rtrouton – Der Flounder
Viewing all 764 articles
Browse latest View live

Zsh history command doesn’t show all history entries by default

$
0
0

Starting with macOS Catalina, Apple’s default shell for the Terminal changed from bash to zsh. As part of that change, the behavior of the history command changed.

Bash:

Running the history command lists all history entries.

Zsh:

Running the history command lists only the 15 most recent history entries.

To see more history entries, you can pass a numerical value to the history command. However, the bash and zsh shells handle this differently also.

Bash:

history (number_goes_here): Shows the most recent entries as defined by the number.

For example, the command shown below will show the fifteen most recent entries:

history 15

Zsh:

history (number_goes_here): Shows all entries which follow number_goes_here.

For example, the following command will show all history entries after history entry #1 (which will include all history entries):

history 1

history -(number_goes_here): Shows the most recent entries as defined by the number.

For example, the command shown below will show the fifteen most recent entries:

history -15

For those interested in why this behavior is different, I recommend reading the zshbuiltins manpage’s section on the fc command. This can be accessed by running the following command:

man zshbuiltins

The reason is that in the zsh shell, the history command’s mechanism is using the following built-in function:

fc

Screen Shot 2022 01 29 at 9 58 36 PM

For my own needs, I wanted to recreate bash‘s default behavior for the history command in the zsh shell. The way I chose to do this was to add the following line to the .zshrc file in my home folder.


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


alias history='history 1'
view raw

.zshrc

hosted with ❤ by GitHub

Screen Shot 2022 01 29 at 8 50 22 PM

The .zshrc file is the configuration file for the zsh shell and is used to customize the zsh shell’s behavior. Adding this line to the .zshrc file will run the following command whenever the history command is invoked:

history 1

The downside to this approach is that it interferes with the original functionality of the history command. An alternative approach would be to add the following line to the .zshrc file:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


alias fullhistory='history 1'
view raw

.zshrc

hosted with ❤ by GitHub

Screen Shot 2022 01 29 at 9 11 05 PM

Now all history entries will be displayed when the following command is entered:

fullhistory


Querying an API for AutoPkg download URLs

$
0
0

As part of working on a new AutoPkg download recipe today, I very quickly got stuck on a problem. The app in question is Poly’s Lens software and its download page uses JavaScript to provide the download URL for the latest version of the Lens software. While this may have benefits for the vendor, this means I can’t scrape the page for the download URL’s address using AutoPkg.

Discussing the issue in the #autopkg channel of the MacAdmins Slack, folks started poking around the Lens app and discovered that it was using the Squirrel framework to provide software update functionality to the app. Assuming that meant that the app would phone home for updates, ahousseini was kind enough to monitor the app’s HTTP and HTTPS traffic using CharlesProxy. Shortly thereafter, he reported seeing Lens send the following API request using curl:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


curl \
-H 'Host: api.silica-prod01.io.lens.poly.com' \
-H 'accept: application/json, text/javascript, */*; q=0.01' \
-H 'content-type: application/json' \
-H 'origin: https://www.poly.com' \
-H 'apollographql-client-name: poly.com-website' \
-H 'accept-language: en-GB,en;q=0.9' \
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Safari/605.1.15' \
-H 'referer: https://www.poly.com/' –data-binary '{"query":"\n query {\n availableProductSoftwareByPid(pid:\"lens-desktop-mac\") {\n name\n version\n publishDate\n productBuild {\n archiveUrl\n }\n }\n }"}' \
–compressed 'https://api.silica-prod01.io.lens.poly.com/graphql'
view raw

gistfile1.txt

hosted with ❤ by GitHub

This HTTPS traffic was Lens sending an API request to see if it was running the latest version of the software. The relevant parts from our perspective were the items shown below:

This told us what format we should expect API output to be (in this case, JSON):


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


-H 'content-type: application/json'
view raw

gistfile1.txt

hosted with ❤ by GitHub

This told us the query which was being sent to the API endpoint:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


–data-binary '{"query":"\n query {\n availableProductSoftwareByPid(pid:\"lens-desktop-mac\") {\n name\n version\n publishDate\n productBuild {\n archiveUrl\n }\n }\n }"}'
view raw

gistfile1.txt

hosted with ❤ by GitHub

This told us the API endpoint:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


https://api.silica-prod01.io.lens.poly.com/graphql
view raw

gistfile1.txt

hosted with ❤ by GitHub

Putting this information together, the following curl command gets a response from the API endpoint:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


curl 'https://api.silica-prod01.io.lens.poly.com/graphql' -H 'content-type: application/json' –data-binary '{"query":"\n query {\n availableProductSoftwareByPid(pid:\"lens-desktop-mac\") {\n name\n version\n publishDate\n productBuild {\n archiveUrl\n }\n }\n }"}'
view raw

gistfile1.txt

hosted with ❤ by GitHub

The API response looks similar to this:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


{"data":{"availableProductSoftwareByPid":{"name":"Poly Lens Mac – 1.1.11","version":"1.1.11","publishDate":"2022-02-02T17:01:41.503Z","productBuild":{"archiveUrl":"https://swupdate.lens.poly.com/lens-desktop-mac/1.1.11/1.1.11/PolyLens-1.1.11.dmg"}}}}
view raw

gistfile1.txt

hosted with ❤ by GitHub

Part of the API response’s output includes the download URL for the latest version:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


https://swupdate.lens.poly.com/lens-desktop-mac/1.1.11/1.1.11/PolyLens-1.1.11.dmg
view raw

gistfile1.txt

hosted with ❤ by GitHub

Now that we have this information, how to use it with AutoPkg? For more details, please see below the jump:

You can use AutoPkg’s URLTextSearcher processor for this purpose. The URLTextSearcher processor is designed to use curl to download information from a URL and then perform a regular expression match on the returned information. Because the processor is using curl, one of the processor’s options is to include curl options using the curl_opts input option, to include those options when performing the download request using curl.

The processor also includes a request_headers input option, which allows headers to be included with the download request.

Between being able to send headers and configure curl options, this meant that I had everything needed to query the API. The last part was being able to parse the API endpoint’s response to get the URL which was needed. For that, the re_pattern input option allowed a Python regular expression to parse the output for what was needed.

In an AutoPkg .download recipe, configuring the URLTextSearcher processor like this works to run the desired API call:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<dict>
<key>Arguments</key>
<dict>
<key>curl_opts</key>
<array>
<string>–data-binary</string>
<string>{"query":"\n query {\n availableProductSoftwareByPid(pid:\"lens-desktop-mac\") {\n name\n version\n publishDate\n productBuild {\n archiveUrl\n }\n }\n }"}</string>
</array>
<key>re_pattern</key>
<string>https://swupdate\.lens\.poly\.com/lens-desktop-mac/.*?/.*?/PolyLens-.*?.dmg</string>
<key>request_headers</key>
<dict>
<key>content-type</key>
<string>application/json</string>
</dict>
<key>url</key>
<string>https://api.silica-prod01.io.lens.poly.com/graphql</string&gt;
</dict>
<key>Processor</key>
<string>URLTextSearcher</string>
</dict>
view raw

gistfile1.txt

hosted with ❤ by GitHub

When AutoPkg runs the recipe in verbose mode, you should be able to see the URLTextSearcher processor do the following:

  1. Run the API call
  2. Parse the output
  3. Use the designated regular expression to return the desired download URL as output from the processor.

Screen Shot 2022 02 02 at 7 36 29 PM

From there, other AutoPkg processors (in this case the URLDownloader processor) can use the output from the URLTextSearcher processor to read the download URL from the output and then use it to download a disk image containing the latest Poly Lens app.

Screen Shot 2022 02 02 at 7 36 30 PM

For the full verbose output, please see below:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


username@computername ~ % autopkg run PolyLens.pkg -vvv
Processing PolyLens.pkg…
{'AUTOPKG_VERSION': '2.3.1',
'CONTENT_TYPE_HEADER': 'application/json',
'DATA_BINARY_CONTENT': '{"query":"\\n query {\\n '
'availableProductSoftwareByPid(pid:\\"lens-desktop-mac\\") '
'{\\n name\\n '
'version\\n publishDate\\n '
'productBuild {\\n '
'archiveUrl\\n }\\n '
'}\\n }"}',
'GIT_PATH': '/Applications/Xcode.app/Contents/Developer/usr/bin/git',
'NAME': 'Poly Lens',
'PARENT_RECIPES': ['/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.username-recipes/PolyLens/PolyLens.download.recipe'],
'RECIPE_CACHE_DIR': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens',
'RECIPE_DIR': '/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.username-recipes/PolyLens',
'RECIPE_OVERRIDE_DIRS': ['~/Library/AutoPkg/RecipeOverrides'],
'RECIPE_PATH': '/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.username-recipes/PolyLens/PolyLens.pkg.recipe',
'RECIPE_REPOS': {'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.andrewvalentine-recipes': {'URL': 'https://github.com/autopkg/andrewvalentine-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.apettinen-recipes': {'URL': 'https://github.com/autopkg/apettinen-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.arubdesu-recipes': {'URL': 'https://github.com/autopkg/arubdesu-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.bkerns-recipes': {'URL': 'https://github.com/autopkg/bkerns-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.cgerke-recipes': {'URL': 'https://github.com/autopkg/cgerke-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.dataJAR-recipes': {'URL': 'https://github.com/autopkg/dataJAR-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.eholtam-recipes': {'URL': 'https://github.com/autopkg/eholtam-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.foigus-recipes': {'URL': 'https://github.com/autopkg/foigus-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.gerardkok-recipes': {'URL': 'https://github.com/autopkg/gerardkok-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.golbiga-recipes': {'URL': 'https://github.com/autopkg/golbiga-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.grahamgilbert-recipes': {'URL': 'https://github.com/autopkg/grahamgilbert-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.gregneagle-recipes': {'URL': 'https://github.com/autopkg/gregneagle-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.hansen-m-recipes': {'URL': 'https://github.com/autopkg/hansen-m-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.hjuutilainen-recipes': {'URL': 'https://github.com/autopkg/hjuutilainen-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.homebysix-recipes': {'URL': 'https://github.com/autopkg/homebysix-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.jaharmi-recipes': {'URL': 'https://github.com/autopkg/jaharmi-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.jleggat-recipes': {'URL': 'https://github.com/autopkg/jleggat-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.jps3-recipes': {'URL': 'https://github.com/autopkg/jps3-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.justinrummel-recipes': {'URL': 'https://github.com/autopkg/justinrummel-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.killahquam-recipes': {'URL': 'https://github.com/autopkg/killahquam-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.recipes': {'URL': 'https://github.com/autopkg/recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.username-recipes': {'URL': 'https://github.com/autopkg/username-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.scriptingosx-recipes': {'URL': 'https://github.com/autopkg/scriptingosx-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.sheagcraig-recipes': {'URL': 'https://github.com/autopkg/sheagcraig-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.smithjw-recipes': {'URL': 'https://github.com/autopkg/smithjw-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.tbridge-recipes': {'URL': 'https://github.com/autopkg/tbridge-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.facebook.Recipes-for-AutoPkg': {'URL': 'https://github.com/facebook/Recipes-for-AutoPkg&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.rtrouton.autopkg_recipes': {'URL': 'https://github.com/username/autopkg_recipes&#39;}},
'RECIPE_SEARCH_DIRS': ['.',
'~/Library/AutoPkg/Recipes',
'/Library/AutoPkg/Recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.hjuutilainen-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.justinrummel-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.jaharmi-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.sheagcraig-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.username-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.golbiga-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.jps3-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.jleggat-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.hansen-m-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.gerardkok-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.andrewvalentine-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.eholtam-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.homebysix-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.grahamgilbert-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.arubdesu-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.scriptingosx-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.tbridge-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.cgerke-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.foigus-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.gregneagle-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.bkerns-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.apettinen-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.smithjw-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.dataJAR-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.killahquam-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.rtrouton.autopkg_recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.facebook.Recipes-for-AutoPkg',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.username-recipes/PolyLens'],
'SEARCH_PATTERN': 'https://swupdate\\.lens\\.poly\\.com/lens-desktop-mac/.*?/.*?/PolyLens-.*?.dmg',
'SOFTWARETITLE': 'Lens',
'VENDOR': 'Poly',
'verbose': 3}
URLTextSearcher
{'Input': {'curl_opts': ['–data-binary',
'{"query":"\\n query {\\n '
'availableProductSoftwareByPid(pid:\\"lens-desktop-mac\\") '
'{\\n name\\n '
'version\\n publishDate\\n '
'productBuild {\\n '
'archiveUrl\\n }\\n '
'}\\n }"}'],
're_pattern': 'https://swupdate\\.lens\\.poly\\.com/lens-desktop-mac/.*?/.*?/PolyLens-.*?.dmg',
'request_headers': {'content-type': 'application/json'},
'url': 'https://api.silica-prod01.io.lens.poly.com/graphql&#39;}}
URLTextSearcher: No value supplied for result_output_var_name, setting default value of: match
URLTextSearcher: Found matching text (match): https://swupdate.lens.poly.com/lens-desktop-mac/1.1.11/1.1.11/PolyLens-1.1.11.dmg
{'Output': {'match': 'https://swupdate.lens.poly.com/lens-desktop-mac/1.1.11/1.1.11/PolyLens-1.1.11.dmg&#39;}}
URLDownloader
{'Input': {'curl_opts': [],
'request_headers': {'content-type': 'application/json'},
'url': 'https://swupdate.lens.poly.com/lens-desktop-mac/1.1.11/1.1.11/PolyLens-1.1.11.dmg&#39;}}
URLDownloader: No value supplied for prefetch_filename, setting default value of: False
URLDownloader: No value supplied for CHECK_FILESIZE_ONLY, setting default value of: False
URLDownloader: Storing new Last-Modified header: Wed, 02 Feb 2022 12:33:28 GMT
URLDownloader: Storing new ETag header: "0x8D9E64836F9164E"
URLDownloader: Downloaded /Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/downloads/PolyLens-1.1.11.dmg
{'Output': {'download_changed': True,
'etag': '"0x8D9E64836F9164E"',
'last_modified': 'Wed, 02 Feb 2022 12:33:28 GMT',
'pathname': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/downloads/PolyLens-1.1.11.dmg',
'url_downloader_summary_result': {'data': {'download_path': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/downloads/PolyLens-1.1.11.dmg'},
'summary_text': 'The following '
'new items were '
'downloaded:'}}}
PkgRootCreator
{'Input': {'pkgdirs': {'Applications': '0775'},
'pkgroot': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/Poly '
'Lens'}}
PkgRootCreator: Created /Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/Poly Lens
PkgRootCreator: Creating Applications
PkgRootCreator: Created /Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/Poly Lens/Applications
{'Output': {}}
Copier
{'Input': {'destination_path': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/Poly '
'Lens/Applications/Poly Lens.app',
'source_path': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/downloads/PolyLens-1.1.11.dmg/Poly '
'Lens.app'}}
Copier: Parsed dmg results: dmg_path: /Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/downloads/PolyLens-1.1.11.dmg, dmg: .dmg/, dmg_source_path: Poly Lens.app
Copier: Mounted disk image /Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/downloads/PolyLens-1.1.11.dmg
Copier: Copied /private/tmp/dmg.kunZU8/Poly Lens.app to /Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/Poly Lens/Applications/Poly Lens.app
{'Output': {}}
Versioner
{'Input': {'input_plist_path': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/Poly '
'Lens/Applications/Poly '
'Lens.app/Contents/Info.plist',
'plist_version_key': 'CFBundleShortVersionString'}}
Versioner: No value supplied for skip_single_root_dir, setting default value of: False
Versioner: Found version 1.1.11 in file /Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/Poly Lens/Applications/Poly Lens.app/Contents/Info.plist
{'Output': {'version': '1.1.11'}}
PkgCreator
{'Input': {'pkg_request': {'chown': [{'group': 'wheel',
'mode': '0755',
'path': 'Applications',
'user': 'root'}],
'id': 'com.poly.lens.client.app',
'options': 'purge_ds_store',
'pkgname': 'Poly_Lens_1.1.11',
'version': '1.1.11'}}}
PkgCreator: Connecting
PkgCreator: Sending packaging request
PkgCreator: Disconnecting
PkgCreator: Failed to close socket: [Errno 9] Bad file descriptor
{'Output': {'new_package_request': True,
'pkg_creator_summary_result': {'data': {'identifier': 'com.poly.lens.client.app',
'pkg_path': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/Poly_Lens_1.1.11.pkg',
'version': '1.1.11'},
'report_fields': ['identifier',
'version',
'pkg_path'],
'summary_text': 'The following '
'packages were '
'built:'},
'pkg_path': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/Poly_Lens_1.1.11.pkg'}}
{'AUTOPKG_VERSION': '2.3.1',
'CHECK_FILESIZE_ONLY': False,
'CONTENT_TYPE_HEADER': 'application/json',
'DATA_BINARY_CONTENT': '{"query":"\\n query {\\n '
'availableProductSoftwareByPid(pid:\\"lens-desktop-mac\\") '
'{\\n name\\n '
'version\\n publishDate\\n '
'productBuild {\\n '
'archiveUrl\\n }\\n '
'}\\n }"}',
'GIT_PATH': '/Applications/Xcode.app/Contents/Developer/usr/bin/git',
'NAME': 'Poly Lens',
'PARENT_RECIPES': ['/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.username-recipes/PolyLens/PolyLens.download.recipe'],
'RECIPE_CACHE_DIR': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens',
'RECIPE_DIR': '/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.username-recipes/PolyLens',
'RECIPE_OVERRIDE_DIRS': ['~/Library/AutoPkg/RecipeOverrides'],
'RECIPE_PATH': '/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.username-recipes/PolyLens/PolyLens.pkg.recipe',
'RECIPE_REPOS': {'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.andrewvalentine-recipes': {'URL': 'https://github.com/autopkg/andrewvalentine-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.apettinen-recipes': {'URL': 'https://github.com/autopkg/apettinen-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.arubdesu-recipes': {'URL': 'https://github.com/autopkg/arubdesu-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.bkerns-recipes': {'URL': 'https://github.com/autopkg/bkerns-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.cgerke-recipes': {'URL': 'https://github.com/autopkg/cgerke-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.dataJAR-recipes': {'URL': 'https://github.com/autopkg/dataJAR-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.eholtam-recipes': {'URL': 'https://github.com/autopkg/eholtam-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.foigus-recipes': {'URL': 'https://github.com/autopkg/foigus-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.gerardkok-recipes': {'URL': 'https://github.com/autopkg/gerardkok-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.golbiga-recipes': {'URL': 'https://github.com/autopkg/golbiga-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.grahamgilbert-recipes': {'URL': 'https://github.com/autopkg/grahamgilbert-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.gregneagle-recipes': {'URL': 'https://github.com/autopkg/gregneagle-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.hansen-m-recipes': {'URL': 'https://github.com/autopkg/hansen-m-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.hjuutilainen-recipes': {'URL': 'https://github.com/autopkg/hjuutilainen-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.homebysix-recipes': {'URL': 'https://github.com/autopkg/homebysix-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.jaharmi-recipes': {'URL': 'https://github.com/autopkg/jaharmi-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.jleggat-recipes': {'URL': 'https://github.com/autopkg/jleggat-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.jps3-recipes': {'URL': 'https://github.com/autopkg/jps3-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.justinrummel-recipes': {'URL': 'https://github.com/autopkg/justinrummel-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.killahquam-recipes': {'URL': 'https://github.com/autopkg/killahquam-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.recipes': {'URL': 'https://github.com/autopkg/recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.username-recipes': {'URL': 'https://github.com/autopkg/username-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.scriptingosx-recipes': {'URL': 'https://github.com/autopkg/scriptingosx-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.sheagcraig-recipes': {'URL': 'https://github.com/autopkg/sheagcraig-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.smithjw-recipes': {'URL': 'https://github.com/autopkg/smithjw-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.tbridge-recipes': {'URL': 'https://github.com/autopkg/tbridge-recipes&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.facebook.Recipes-for-AutoPkg': {'URL': 'https://github.com/facebook/Recipes-for-AutoPkg&#39;},
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.rtrouton.autopkg_recipes': {'URL': 'https://github.com/username/autopkg_recipes&#39;}},
'RECIPE_SEARCH_DIRS': ['.',
'~/Library/AutoPkg/Recipes',
'/Library/AutoPkg/Recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.hjuutilainen-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.justinrummel-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.jaharmi-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.sheagcraig-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.username-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.golbiga-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.jps3-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.jleggat-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.hansen-m-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.gerardkok-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.andrewvalentine-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.eholtam-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.homebysix-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.grahamgilbert-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.arubdesu-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.scriptingosx-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.tbridge-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.cgerke-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.foigus-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.gregneagle-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.bkerns-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.apettinen-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.smithjw-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.dataJAR-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.killahquam-recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.rtrouton.autopkg_recipes',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.facebook.Recipes-for-AutoPkg',
'/Users/username/Library/AutoPkg/RecipeRepos/com.github.autopkg.username-recipes/PolyLens'],
'SEARCH_PATTERN': 'https://swupdate\\.lens\\.poly\\.com/lens-desktop-mac/.*?/.*?/PolyLens-.*?.dmg',
'SOFTWARETITLE': 'Lens',
'VENDOR': 'Poly',
'curl_opts': [],
'destination_path': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/Poly '
'Lens/Applications/Poly Lens.app',
'download_changed': True,
'etag': '"0x8D9E64836F9164E"',
'input_plist_path': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/Poly '
'Lens/Applications/Poly Lens.app/Contents/Info.plist',
'last_modified': 'Wed, 02 Feb 2022 12:33:28 GMT',
'match': 'https://swupdate.lens.poly.com/lens-desktop-mac/1.1.11/1.1.11/PolyLens-1.1.11.dmg&#39;,
'new_package_request': True,
'pathname': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/downloads/PolyLens-1.1.11.dmg',
'pkg_creator_summary_result': {'data': {'identifier': 'com.poly.lens.client.app',
'pkg_path': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/Poly_Lens_1.1.11.pkg',
'version': '1.1.11'},
'report_fields': ['identifier',
'version',
'pkg_path'],
'summary_text': 'The following packages were '
'built:'},
'pkg_path': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/Poly_Lens_1.1.11.pkg',
'pkg_request': {'chown': [{'group': 'wheel',
'mode': '0755',
'path': 'Applications',
'user': 'root'}],
'id': 'com.poly.lens.client.app',
'infofile': '',
'options': 'purge_ds_store',
'pkgdir': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens',
'pkgname': 'Poly_Lens_1.1.11',
'pkgroot': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/Poly '
'Lens',
'pkgtype': 'flat',
'resources': '',
'scripts': '',
'version': '1.1.11'},
'pkgdirs': {'Applications': '0775'},
'pkgroot': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/Poly '
'Lens',
'plist_version_key': 'CFBundleShortVersionString',
'prefetch_filename': False,
'purge_destination': True,
're_pattern': 'https://swupdate\\.lens\\.poly\\.com/lens-desktop-mac/.*?/.*?/PolyLens-.*?.dmg',
'request_headers': {'content-type': 'application/json'},
'result_output_var_name': 'match',
'skip_single_root_dir': False,
'source_path': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/downloads/PolyLens-1.1.11.dmg/Poly '
'Lens.app',
'url': 'https://swupdate.lens.poly.com/lens-desktop-mac/1.1.11/1.1.11/PolyLens-1.1.11.dmg&#39;,
'url_downloader_summary_result': {'data': {'download_path': '/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/downloads/PolyLens-1.1.11.dmg'},
'summary_text': 'The following new items '
'were downloaded:'},
'verbose': 3,
'version': '1.1.11'}
Receipt written to /Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/receipts/PolyLens-receipt-20220202-193052.plist
The following new items were downloaded:
Download Path
————-
/Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/downloads/PolyLens-1.1.11.dmg
The following packages were built:
Identifier Version Pkg Path
———- ——- ——–
com.poly.lens.client.app 1.1.11 /Users/username/Library/AutoPkg/Cache/com.github.rtrouton.pkg.polylens/Poly_Lens_1.1.11.pkg
username@computername ~ %
view raw

gistfile1.txt

hosted with ❤ by GitHub

For reference, I’ve posted AutoPkg recipes for Poly Lens which use the technique I’ve discussed in this post:

https://github.com/autopkg/rtrouton-recipes/tree/master/PolyLens

autopkg-conductor updated to support both JamfUploaderSlacker and Slacker AutoPkg processors

$
0
0

As part of my preparations for Jamf’s planned authentication changes to the Classic API, I’ve been working more with the JamfUploader AutoPkg processors for Jamf Upload. These processors have emerged as a successor to JSSImporter, the original tool available to upload installer packages and other components to Jamf Pro using AutoPkg.

As part of my work with Jamf Upload, I’ve also updated my autopkg-conductor script to allow the use of either Jamf Upload’s JamfUploaderSlacker AutoPkg processor or JSSImporter’s Slacker AutoPkg processors. For more details, please see below the jump.

JamfUploaderSlacker and Slacker both allow uploading information to a Slack channel using a webhook. The message which appears in Slack should look similar to what is shown below:

JamfUploaderSlacker

Screen Shot 2022 02 11 at 4 54 22 PM

Slacker

Screen Shot 2022 02 11 at 5 12 12 PM

To accommodate using either the JamfUploaderSlacker or Slacker processor, I’ve added a new slack_autopkg_processor variable to autopkg-conductor. If this variable is set correctly with the values specified in the script, it’ll enable autopkg-conductor to use the correct processor when reporting to a Slack channel.

Screen Shot 2022 02 11 at 5 25 41 PM

If the slack_autopkg_processor variable is set, but isn’t one of the two expected values, the use of the processors is bypassed. Instead, all logged output would be sent to Slack if a Slack webhook is set up.

Screen Shot 2018 07 05 at 9 14 08 PM

Another change to autopkg-conductor is to error reporting. In the previous version of autopkg-conductor, the error log was sent to Slack even if no errors were detected.

Screen Shot 2022 02 11 at 5 28 57 PM

This behavior has been changed. If no errors have been detected, the error log will no longer be sent to Slack. Instead, the information that the error log was empty will be logged to the logs stored on the Mac which is running autopkg-conductor.

The autopkg-conductor script is available below. It’s also available from GitHub using the following link:

https://github.com/rtrouton/autopkg-conductor


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


#!/bin/bash
# AutoPkg automation script
# Adjust the following variables for your particular configuration.
#
# autopkg_user_account – This should be the user account you're running AutoPkg in.
# autopkg_user_account_home – This should be the home folder location of the AutoPkg user account
#
# Note: The home folder location is currently set to be automatically discovered
# using the autopkg_user_account variable.
#
# recipe_list – This is the location of the plain text file being used to store
# your list of AutoPkg recipes. For more information about this list, please see
# the link below:
#
# https://github.com/autopkg/autopkg/wiki/Running-Multiple-Recipes
#
# log_location – This should be the location and name of the AutoPkg run logs.
#
# Note: The location is currently set to be automatically discovered
# using the autopkg_user_account_home variable.
autopkg_user_account="username_goes_here"
autopkg_user_account_home=$(/usr/bin/dscl . -read /Users/"$autopkg_user_account" NFSHomeDirectory | awk '{print $2}')
recipe_list="/path/to/recipe_list.txt"
log_location="$autopkg_user_account_home/Library/Logs/autopkg-run-for-$(date +%Y-%m-%d-%H%M%S).log"
# If you're using JSSImporter or Jamf Upload, the URL of your Jamf Pro server should be populated
# into the jamfpro_server variable automatically.
#
# If you're not using JSSImporter or Jamf Upload, this variable will return nothing and that's OK.
jamfpro_server=$(/usr/bin/defaults read "$autopkg_user_account_home"/Library/Preferences/com.github.autopkg JSS_URL)
# Optional variables
# This script supports using either Jamf Upload's JamfUploaderSlacker or JSSImporter's Slacker processors
# JamfUploaderSlacker – used with Jamf Upload
#
# To use the JamfUploaderSlacker post-processor, you'll need to use add Graham Pugh's
# Autopkg repo by running the command below:
#
# autopkg repo-add grahampugh-recipes
#
# The slack_post_processor variable should look like this:
# slack_post_processor="com.github.grahampugh.jamf-upload.processors/JamfUploaderSlacker"
#
# Slacker – used with JSSImporter
#
# To use the Slacker post-processor, you'll need to use either Graham Pugh's or my
# fork of Graham's. For information on Graham's, please see the following post:
#
# http://grahampugh.github.io/2017/12/22/slack-for-autopkg-jssimporter.html
#
# To use mine, please add my AutoPkg repo by running the following command:
#
# autopkg repo-add rtrouton-recipes
#
# If using Graham's, the slack_post_processor variable should look like this:
# slack_post_processor="com.github.grahampugh.recipes.postprocessors/Slacker"
#
# If using mine, the slack_post_processor variable should look like this:
# slack_post_processor="com.github.rtrouton.recipes.postprocessors/Slacker"
slack_post_processor=""
# The key used by the JamfUploaderSlacker and Slacker AutoPkg processors is slightly different
# so the right one needs to be used when running AutoPkg.
#
# JamfUploaderSlacker: slack_webhook_url
#
# Slacker: webhook_url
#
# Setting the slack_autopkg_processor variable will enable the script to use the correct key for the processor.
#
# If using JamfUploaderSlacker, the slack_autopkg_processor processor should be set as shown below:
#
# slack_autopkg_processor="JamfUploaderSlacker"
#
# If using Slacker, the slack_autopkg_processor processor should be set as shown below:
#
# slack_autopkg_processor="Slacker"
slack_autopkg_processor=""
# If you're sending the results of your AutoPkg run to Slack, you'll need to set up
# a Slack webhook to receive the information being sent by the script.
# If you need help with configuring a Slack webhook, please see the links below:
#
# https://api.slack.com/incoming-webhooks
# https://get.slack.help/hc/en-us/articles/115005265063-Incoming-WebHooks-for-Slack
#
# Once a Slack webhook is available, the slack_webhook variable should look similar
# to this:
# slack_webhook="https://hooks.slack.com/services/XXXXXXXXX/YYYYYYYYY/ZZZZZZZZZZ&quot;
slack_webhook=""
# don't change anything below this line
# Set script exit status
exit_error=0
# Define logger behavior
ScriptLogging(){
DATE=$(date +%Y-%m-%d\ %H:%M:%S)
LOG="$log_location"
echo "$DATE" " $1" >> $LOG
}
# Function for sending multi-line output to a Slack webhook. Original script from here:
#
# http://blog.getpostman.com/2015/12/23/stream-any-log-file-to-slack-using-curl/
SendToSlack(){
cat "$1" | while read LINE; do
(echo "$LINE" | grep -e "$3") && curl -X POST –silent –data-urlencode "payload={\"text\": \"$(echo $LINE | sed "s/\"/'/g")\"}" "$2";
done
}
# If the AutoPkg run's log file is not available, create it
if [[ ! -r "$log_location" ]]; then
touch "$log_location"
fi
# If the AutoPkg recipe list is missing or unreadable, stop the script with an error.
if [[ ! -r "$recipe_list" ]]; then
ScriptLogging "Error Detected. Unable to start AutoPkg run."
echo "" > /tmp/autopkg_error.out
if [[ "$jamfpro_server" = "" ]]; then
echo "AutoPkg run failed" >> /tmp/autopkg_error.out
else
echo "AutoPkg run for $jamfpro_server failed" >> /tmp/autopkg_error.out
fi
echo "$recipe_list is missing or unreadable. Fix immediately." >> /tmp/autopkg_error.out
echo "" > /tmp/autopkg.out
# If a Slack webhook is configured, send the error log to Slack.
if [[ ! -z "$slack_webhook" ]]; then
SendToSlack /tmp/autopkg_error.out ${slack_webhook}
fi
cat /tmp/autopkg_error.out >> "$log_location"
ScriptLogging "Finished AutoPkg run"
exit_error=1
fi
# If the the AutoPkg recipe list is readable and AutoPkg is installed,
# run the recipes stored in the recipe list.
if [[ -x /usr/local/bin/autopkg ]] && [[ -r "$recipe_list" ]]; then
ScriptLogging "AutoPkg installed at $(which autopkg)"
ScriptLogging "Recipe list located at $recipe_list and is readable."
echo "" > /tmp/autopkg.out
if [[ "$jamfpro_server" = "" ]]; then
echo "Starting AutoPkg run" >> /tmp/autopkg_error.out
else
echo "Starting AutoPkg run for $jamfpro_server" >> /tmp/autopkg.out
fi
echo "" >> /tmp/autopkg.out
echo "" > /tmp/autopkg_error.out
echo "Error log for AutoPkg run" >> /tmp/autopkg_error.out
echo "" >> /tmp/autopkg_error.out
/usr/local/bin/autopkg repo-update all 2>&1 >> /tmp/autopkg.out 2>>/tmp/autopkg_error.out
cat /tmp/autopkg.out >> "$log_location" && cat /tmp/autopkg_error.out >> "$log_location"
if [[ ! -z "$slack_webhook" ]]; then
if [[ ! -z "$slack_post_processor" ]] && [[ ! -z "$slack_autopkg_processor" ]]; then
if [[ ${slack_autopkg_processor} = "Slacker" ]] || [[ ${slack_autopkg_processor} = "JamfUploaderSlacker" ]]; then
# If both a post-processor to post to Slack and a Slack webhook are configured, the JSSImporter
# and Jamf Upload recipes should have their outputs posted to Slack using the post-processor, while
# all other standard output should go to /tmp/autopkg.out. All standard error output
# should go to /tmp/autopkg_error.out
if [[ ${slack_autopkg_processor} = "Slacker" ]]; then
slack_autopkg_processor_key="webhook_url"
elif [[ ${slack_autopkg_processor} = "JamfUploaderSlacker" ]]; then
slack_autopkg_processor_key="slack_webhook_url"
fi
/usr/local/bin/autopkg run –recipe-list=${recipe_list} –post=${slack_post_processor} –key ${slack_autopkg_processor_key}=${slack_webhook} >> /tmp/autopkg.out 2>>/tmp/autopkg_error.out
else
# If for some reason the slack_autopkg_processor variable is configured with an unknown value,
# neither processor is called and all standard output should go to /tmp/autopkg.out.
# All standard error output should go to /tmp/autopkg_error.out.
/usr/local/bin/autopkg run –recipe-list=${recipe_list} >> /tmp/autopkg.out 2>>/tmp/autopkg_error.out
fi
else
# If only using a Slack webhook, all standard output should go to /tmp/autopkg.out.
# All standard error output should go to /tmp/autopkg_error.out.
/usr/local/bin/autopkg run –recipe-list=${recipe_list} >> /tmp/autopkg.out 2>>/tmp/autopkg_error.out
fi
else
# If a Slack webhook is not configured, all standard output should go to /tmp/autopkg.out.
# All standard error output should go to /tmp/autopkg_error.out.
/usr/local/bin/autopkg run –recipe-list="$recipe_list" >> /tmp/autopkg.out 2>>/tmp/autopkg_error.out
fi
if [[ "$jamfpro_server" = "" ]]; then
echo "Finished with AutoPkg run" >> /tmp/autopkg.out
else
echo "Finished with AutoPkg run for $jamfpro_server" >> /tmp/autopkg.out
fi
echo "" >> /tmp/autopkg.out && echo "" >> /tmp/autopkg_error.out
cat /tmp/autopkg.out >> "$log_location"
cat /tmp/autopkg_error.out >> "$log_location"
ScriptLogging "Finished AutoPkg run"
echo "" >> /tmp/autopkg_error.out
echo "End of error log for AutoPkg run" >> /tmp/autopkg_error.out
echo "" >> /tmp/autopkg_error.out
if [[ -z "$slack_post_processor" ]] && [[ ! -z "$slack_webhook" ]]; then
# If the AutoPkg post-processor for posting to Slack is not
# configured but we do have a Slack webhook set up, all
# standard output should be sent to Slack.
ScriptLogging "Sending AutoPkg output log to Slack"
SendToSlack /tmp/autopkg.out ${slack_webhook}
ScriptLogging "Sent AutoPkg output log to $slack_webhook."
fi
if [[ ! -z "$slack_post_processor" ]] && [[ ! -z "$slack_webhook" ]] && [[ ${slack_autopkg_processor} != "Slacker" ]] && [[ ${slack_autopkg_processor} != "JamfUploaderSlacker" ]]; then
# If the AutoPkg post-processor for posting to Slack is
# misconfigured but we do have a Slack webhook set up,
# all standard output should be sent to Slack.
ScriptLogging "Sending AutoPkg output log to Slack"
SendToSlack /tmp/autopkg.out ${slack_webhook}
ScriptLogging "Sent AutoPkg output log to $slack_webhook."
fi
if [[ ! -z "$slack_webhook" ]]; then
# If using a Slack webhook, at the end of the AutoPkg run all standard
# error output logged to /tmp/autopkg_error.out should be output to Slack,
# using the SendToSlack function.
if [[ $(wc -l </tmp/autopkg_error.out) -gt 7 ]]; then
ScriptLogging "Sending AutoPkg error log to Slack"
SendToSlack /tmp/autopkg_error.out ${slack_webhook}
ScriptLogging "Sent autopkg log to $slack_webhook. Ending run."
else
ScriptLogging "Error log was empty. Nothing to send to Slack."
fi
fi
fi
exit "$exit_error"

Using AutoPkg to get the latest Jamf Protect installer and uninstaller from your Jamf Protect tenant

$
0
0

Jamf has enabled a new feature on Jamf Protect tenants, where you can generate a download URL for the latest Jamf Protect client installer and uninstaller. These download URLs do not require authentication, but a security identifier unique to the Jamf Protect tenant needs to be included as part of the download URL:

Screen Shot 2022 02 17 at 4 47 20 PM

Once generated, the download links are formatted similar to this:

Installer:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


curl "https://jamf.protect.tenant.here/installer.pkg?security_token_goes_here&quot; -o installer.pkg
view raw

gistfile1.txt

hosted with ❤ by GitHub

Screen Shot 2022 02 17 at 4 49 33 PM

 

Uninstaller:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


curl "https://jamf.protect.tenant.here/uninstaller.pkg?security_token_goes_here&quot; -o uninstaller.pkg
view raw

gistfile1.txt

hosted with ❤ by GitHub

Screen Shot 2022 02 17 at 4 51 30 PM

 

For example, if the Jamf Protect tenant and security identifier were as shown below, the curl commands would look like this:

  • Jamf Protect tenant: companyname.protect.jamfcloud.com
  • Security token: c1f0d1cb-8ddc-4f36-9578-58a7388053d5

Installer:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


curl "https://companyname.protect.jamfcloud.com/installer.pkg?c1f0d1cb-8ddc-4f36-9578-58a7388053d5&quot; -o installer.pkg
view raw

gistfile1.txt

hosted with ❤ by GitHub

Uninstaller:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


curl "https://companyname.protect.jamfcloud.com/uninstaller.pkg?c1f0d1cb-8ddc-4f36-9578-58a7388053d5&quot; -o uninstaller.pkg
view raw

gistfile1.txt

hosted with ❤ by GitHub

Since the Jamf Protect installer and uninstaller can be downloaded from your Jamf Protect tenant, this means that it’s now possible to use AutoPkg to get the latest Jamf Protect client installer and uninstaller as soon as they are available from your Jamf Protect tenant. For more details, please see below the jump.

To help facilitate this, I’ve written a set of Jamf Protect AutoPkg recipes.


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


username@computername ~ % autopkg search JamfProtect | grep rtrouton-recipes
JamfProtect.uninstaller.pkg.recipe rtrouton-recipes JamfProtect/JamfProtect.uninstaller.pkg.recipe
JamfProtect.installer.pkg.recipe rtrouton-recipes JamfProtect/JamfProtect.installer.pkg.recipe
JamfProtect.uninstaller.download.recipe rtrouton-recipes JamfProtect/JamfProtect.uninstaller.download.recipe
JamfProtect.installer.download.recipe rtrouton-recipes JamfProtect/JamfProtect.installer.download.recipe
JamfProtectUninstaller.jamf.recipe rtrouton-recipes Jamf_Upload/JamfProtectUninstaller.jamf.recipe
JamfProtectInstaller.jamf.recipe rtrouton-recipes Jamf_Upload/JamfProtectInstaller.jamf.recipe
JamfProtectUninstaller.jss.recipe rtrouton-recipes JSS/JamfProtectUninstaller.jss.recipe
JamfProtectInstaller.jss.recipe rtrouton-recipes JSS/JamfProtectInstaller.jss.recipe
username@computername ~ %
view raw

gistfile1.txt

hosted with ❤ by GitHub

These download URLs are tenant-specific and not public, so you will need to create a recipe override and enter the URL and security identifier Jamf provides into the DOWNLOAD_URL and DOWNLOAD_UUID values of the override.


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
<plist version="1.0">
<dict>
<key>Identifier</key>
<string>local.download.uninstaller.JamfProtect</string>
<key>Input</key>
<dict>
<key>DOWNLOAD_FILENAME</key>
<string>Jamf_Protect_Uninstaller.pkg</string>
<key>DOWNLOAD_URL</key>
<string>Put_Jamf_Protect_Uninstaller_download_URL_into_AutoPkg_recipe_override</string>
<key>DOWNLOAD_UUID</key>
<string>Put_Jamf_Protect_Uninstaller_download_UUID_into_AutoPkg_recipe_override</string>
<key>NAME</key>
<string>Jamf Protect</string>
</dict>
<key>ParentRecipe</key>
<string>com.github.rtrouton.download.uninstaller.jamfprotect</string>
<key>ParentRecipeTrustInfo</key>
<dict>
<key>non_core_processors</key>
<dict/>
<key>parent_recipes</key>
<dict>
<key>com.github.rtrouton.download.uninstaller.jamfprotect</key>
<dict>
<key>git_hash</key>
<string>8bd26bbb1e8f6ca4df6de22a4b3e73787d646ce6</string>
<key>path</key>
<string>~/Library/AutoPkg/RecipeRepos/com.github.rtrouton.autopkg_recipes/JamfProtect/JamfProtect.uninstaller.download.recipe</string>
<key>sha256_hash</key>
<string>9906e603feb50b6d249811bad668dbf358aff7baa93f4e33e2e475048a0c7eb5</string>
</dict>
</dict>
</dict>
</dict>
</plist>
view raw

gistfile1.txt

hosted with ❤ by GitHub

For example, if the Jamf Protect tenant and security identifier were as shown below, the override would look like this:

  • Jamf Protect tenant: companyname.protect.jamfcloud.com
  • Security token: c1f0d1cb-8ddc-4f36-9578-58a7388053d5


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
<plist version="1.0">
<dict>
<key>Identifier</key>
<string>local.download.uninstaller.JamfProtect</string>
<key>Input</key>
<dict>
<key>DOWNLOAD_FILENAME</key>
<string>Jamf_Protect_Uninstaller.pkg</string>
<key>DOWNLOAD_URL</key>
<string>https://companyname.protect.jamfcloud.com/installer.pkg</string>
<key>DOWNLOAD_UUID</key>
<string>c1f0d1cb-8ddc-4f36-9578-58a7388053d5</string>
<key>NAME</key>
<string>Jamf Protect</string>
</dict>
<key>ParentRecipe</key>
<string>com.github.rtrouton.download.uninstaller.jamfprotect</string>
<key>ParentRecipeTrustInfo</key>
<dict>
<key>non_core_processors</key>
<dict/>
<key>parent_recipes</key>
<dict>
<key>com.github.rtrouton.download.uninstaller.jamfprotect</key>
<dict>
<key>git_hash</key>
<string>8bd26bbb1e8f6ca4df6de22a4b3e73787d646ce6</string>
<key>path</key>
<string>~/Library/AutoPkg/RecipeRepos/com.github.rtrouton.autopkg_recipes/JamfProtect/JamfProtect.uninstaller.download.recipe</string>
<key>sha256_hash</key>
<string>9906e603feb50b6d249811bad668dbf358aff7baa93f4e33e2e475048a0c7eb5</string>
</dict>
</dict>
</dict>
</dict>
</plist>

Jamf Pro Server software no longer supported on macOS as of Jamf Pro 10.37.0

$
0
0

To follow up on my earlier posts on the Jamf Pro Server Installer for macOS being retired, Jamf has added the following to the Deprecations and Removals section of the Jamf Pro 10.36.0 release notes:

Support Ending for Hosting Jamf Pro Server on macOS—Starting with the release of Jamf Pro 10.37.0, hosting the Jamf Pro server on macOS will no longer be supported. Mac computers with Apple silicon are not supported by the Jamf Pro Installer for macOS. In addition, the Jamf Pro Installer for macOS will not be available to download. The Jamf Pro utilities that were included in the Jamf Pro Installer for macOS—Composer, Jamf Admin, Jamf Recon, and Jamf Remote—will be made available as a separate download.

If you want to migrate your Jamf Pro server from macOS to Jamf Cloud, contact Jamf Support. If you want to keep your server on premise, you can migrate your Jamf Pro server to one of the following servers: Red Hat Enterprise Linux, Ubuntu, or Windows. For more information, see the Migrating to Another Server article.

Screen Shot 2022 02 21 at 9 28 09 AM

For those folks who are running on-premise Jamf Pro servers on Macs, I strongly recommend contacting Jamf Support right now and plan a migration if you haven’t already. As of February 21st, 2022, Jamf’s published support for running Jamf Pro includes the following OS, database and Java versions:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


Recommended Configuration:
Operating Systems:
Windows Server 2019
Ubuntu Server 20.04 LTS
Red Hat Enterprise Linux 7.x
Database software versions:
MySQL 8.0.27 – InnoDB
Amazon Aurora (MySQL 5.7 compatible)
MySQL 5.7.36 or later – InnoDB
Java version:
OpenJDK 11
Minimum Supported:
Operating Systems:
Windows Server 2016
Windows Server 2012 R2
Ubuntu Server 18.04 LTS
macOS 10.15 (Support for the Jamf Pro Installer for macOS and hosting Jamf Pro server on macOS will be discontinued with the release of Jamf Pro 10.37.0.)
macOS 10.14 (Support for the Jamf Pro Installer for macOS and hosting Jamf Pro server on macOS will be discontinued with the release of Jamf Pro 10.37.0.)
Database software versions:
MySQL 5.7.36 – InnoDB
MySQL 5.7.8 on Amazon RDS – InnoDB
Java version:
Oracle Java 11
view raw

gistfile1.txt

hosted with ❤ by GitHub

Using custom variables in an AutoPkg recipe to set version information

$
0
0

As part of a recent task to build an AutoPkg recipe which creates an installer package for a screen saver, I ran into an issue. The vendor, for reasons that no doubt make sense to them, split the version information for the screen saver across two separate keys:

  • Major part of the version number: Stored in the CFBundleShortVersionString key of the screen saver’s Info.plist file
  • Minor part of the version number: Stored in the CFBundleVersion key of the screen saver’s Info.plist file

What this meant is that for version 1.4 of the screen saver, the version information was stored as follows:

  • CFBundleShortVersionString key: 1
  • CFBundleVersion key: 4

Getting this information was not the problem. AutoPkg includes a PlistReader processor which allows multiple values to be read from one plist file, so I used it as shown below to read the CFBundleShortVersionString key’s and the CFBundleVersion key’s values and store them in the following variables:

  • CFBundleVersion key: minor_version
  • CFBundleShortVersionString: major_version


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<dict>
<key>Arguments</key>
<dict>
<key>info_path</key>
<string>%pathname%/Carousel Cloud.saver/Contents/Info.plist</string>
<key>plist_keys</key>
<dict>
<key>CFBundleVersion</key>
<string>minor_version</string>
<key>CFBundleShortVersionString</key>
<string>major_version</string>
</dict>
</dict>
<key>Processor</key>
<string>PlistReader</string>
</dict>
view raw

gistfile1.txt

hosted with ❤ by GitHub

So now I had the version info (in separate pieces) and now I needed to put them together. The problem I was seeing was that my usual solution, AutoPkg’s Versioner processor is set up to read one value from a plist file. I had two values and neither were in a plist file.

Fortunately, there are multiple ways to solve this problem. The first I thought of was to build a new plist as part of the recipe’s run and put the version information in. The workflow works like this:

1. Use the PlistReader processor to read the desired information.
2. Use the FileCreator processor processor to create a new plist file with the version information formatted as needed.
3. Use the PlistReader processor to read the version information out of the newly-created plist file.


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<dict>
<key>Arguments</key>
<dict>
<key>info_path</key>
<string>%pathname%/Carousel Cloud.saver/Contents/Info.plist</string>
<key>plist_keys</key>
<dict>
<key>CFBundleVersion</key>
<string>minor_version</string>
<key>CFBundleShortVersionString</key>
<string>major_version</string>
</dict>
</dict>
<key>Processor</key>
<string>PlistReader</string>
</dict>
<dict>
<key>Processor</key>
<string>FileCreator</string>
<key>Arguments</key>
<dict>
<key>file_path</key>
<string>%RECIPE_CACHE_DIR%/com.companyname.carouselcloudscreensaver.plist</string>
<key>file_mode</key>
<string>0755</string>
<key>file_content</key>
<string>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
&lt;key&gt;complete_version&lt;/key&gt;
&lt;string&gt;%major_version%.%minor_version%&lt;/string&gt;
&lt;/dict&gt;
&lt;/plist&gt;
</string>
</dict>
</dict>
<dict>
<key>Arguments</key>
<dict>
<key>info_path</key>
<string>%RECIPE_CACHE_DIR%/com.companyname.carouselcloudscreensaver.plist</string>
<key>plist_keys</key>
<dict>
<key>complete_version</key>
<string>version</string>
</dict>
</dict>
<key>Processor</key>
<string>PlistReader</string>
</dict>
view raw

gistfile1.txt

hosted with ❤ by GitHub

This approach works, but now you have a plist file to clean up later. Another approach is to use custom variable assigning as part of another AutoPkg processor’s run. In this case, you’re using an AutoPkg processor and adding a separate argument which is probably unrelated to the other work the processor is doing, but does the value assignment work you couldn’t accomplish otherwise.

A pretty safe processor to use for this is the EndOfCheckPhase processor. The reason is that by itself, the EndOfCheckPhase processor takes no actions. Instead, it’s used as a marker in AutoPkg recipes to tell AutoPkg to stop checking for new information as part of a recipe’s run. However, even though the EndOfCheckPhase processor doesn’t take actions and doesn’t by default include Arguments values, AutoPkg will still process Arguments values if they’re defined for the EndOfCheckPhase processor. That allows custom variables to be set with values that you couldn’t otherwise set and pass them to AutoPkg. The workflow in this case looks like this:

1. Add the EndOfCheckPhase processor to the very end of the recipe.
2. Perform the desired variable assignment as an Arguments value

The reason to add it to the end is to make sure that all of the other tasks the recipe is performing are completed by the time this processor runs.

In this case, I used this method with the the EndOfCheckPhase processor in the screen saver’s .download recipe to assign the version variable to use the values of the major_version and minor_version variables, separated by a period.


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<dict>
<key>Processor</key>
<string>EndOfCheckPhase</string>
<key>Arguments</key>
<dict>
<key>version</key>
<string>%major_version%.%minor_version%</string>
</dict>
</dict>
view raw

gistfile1.txt

hosted with ❤ by GitHub

The result for the latest version of the screen saver software is that the version variable is assigned the following value:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


'version': '1.4'
view raw

gistfile1.txt

hosted with ❤ by GitHub

I’ve posted the recipes which use this technique for setting version information to GitHub. They’re available via the link below:

https://github.com/autopkg/rtrouton-recipes/tree/master/CarouselCloudScreenSaver

Using macOS installer disk images to boot VMware Fusion virtual machines to macOS Recovery

$
0
0

Booting a VMware Fusion virtual machine to the macOS Recovery environment can be challenging, as Fusion uses Command-R as a keyboard shortcut for restoring snapshots.

Screen Shot 2022 03 09 at 5 05 19 PM

This is the same keyboard shortcut as booting to macOS Recovery for Intel Macs so if you’re not very fast, or you don’t have the virtual machine window selected correctly, you may be looking at an unwanted request to restore a snapshot instead of macOS Recovery.

Fortunately, there’s a workaround for this behavior which will reliably get you into macOS Recovery. For more details, please see below the jump.

This method relies on VMware Fusion being able to boot a virtual machine from a disk image. So your first step is to create a disk image of the macOS installer for the OS version you want.

You can create this disk image using a tool I’ve written:

https://github.com/rtrouton/create_macos_vm_install_dmg

Once you have the disk image built, use the procedure below to connect the disk image to the virtual machine and boot from it.

1. If necessary, add a CD/DVD to your virtual machine.

2. Connect the disk image of the macOS installer to the virtual machine’s CD/DVD drive.

Screen Shot 2022 03 09 at 6 51 08 PM

3. Under the Virtual Machine menu, select Power on to Firmware.

Screen Shot 2022 03 09 at 4 52 46 PM

4. Once booted to the Boot Manager screen, use the arrow keys on your keyboard to select the CDROM option.

Screen Shot 2022 03 09 at 4 46 39 PM

5. Hit the Return key on your keyboard.

The virtual machine should now boot to the macOS installer’s Recovery environment.

Screen Shot 2022 03 09 at 6 55 18 PM

Note: This Recovery environment is separate from the Recovery on your virtual machine’s regular boot drive, but as long as the OS versions match between the VM and the disk image, it shouldn’t matter which disk’s Recovery environment that you’re actually in.

Please see below for what the process of booting from the Boot Manager to the macOS installer’s Recovery environment should look like.

profiles command includes client-side rate limitation for certain functions on macOS 12.3

$
0
0

One of the changes brought with macOS 12.3 is that the profiles command line tool now includes a rate limiter for some of its functions:

profiles show

Screen Shot 2022 03 22 at 3 55 30 PM

profiles validate

Screen Shot 2022 03 22 at 3 55 47 PM

In both cases, running these functions may be limited to once every 23 hours.

For those familiar with rate limitation on the server side, where a server may choose to limit how many calls can be received in a set period from a client, this rate limitation is similar but is set and managed entirely on the client side. This means that there is no bypassing the profiles command’s rate limitation in this case for the Mac in question.

One way this may appear is on Macs which are part of the Automated Device Enrollment program, where the Mac can show its enrollment status by running the following command:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


profiles show -type enrollment
view raw

gistfile1.txt

hosted with ❤ by GitHub

In the event that this command errors, the profiles command will block further attempts to display this information for the next 23 hours. In this situation, you may see output like that shown below:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


username@computername ~ % sudo profiles show -type enrollment
Password:
Device Enrollment configuration:
(null)
username@computername ~ % sudo profiles show -type enrollment
Error fetching Device Enrollment configuration – Request too soon. Try again later.
view raw

gistfile1.txt

hosted with ❤ by GitHub

At this time, I don’t know where the information which tracks this 23 hour limitation is stored, but I did confirm that it is stored somewhere in the writable portion of the Mac’s boot drive. Wiping the Mac’s boot drive, via a disk wipe and OS reinstall or via Erase All Contents and Settings, will remove whatever is tracking and enforcing the 23 hour limitation.

Update – 4-22-2022:

It looks like the file which tracks this information is stored in the following location:

/private/var/db/ConfigurationProfiles/Settings/.profilesFetchTimerCheck

This file is protected by SIP. Thanks to zolotkey in the comments!

Also, in the original version of this post, I had made a mistake and conflated the functions of the following commands:

  • profiles renew -type enrollment
  • profiles show -type enrollment

The profiles renew -type enrollment command can be used to enroll or re-enroll a Mac which is part of the Automated Device Enrollment program with the MDM server that ADE associates the Mac with. To the best of my knowledge, the renew function of the profiles command does not have a client side rate limitation on macOS 12.3. Thanks also to Richard in the comments for catching my mistake and letting me know about it.


Simple Package Creator 1.5 now available

$
0
0

Simple Package Creator.app, an Automator application that will allow the selection of a self-contained application and creates an installer package that enables the installation of the application with pre-set permissions into /Applications, has been updated to version 1.5.

The functionality and operations of the app have not changed from Simple Package Creator 1.4. The main change is that Simple Package Creator.app is now a Universal app, allowing it to run natively on both Intel and Apple Silicon Macs.

Simple Package Creator 1.5, along with all components and scripts, are available on GitHub via the link below:

https://github.com/rtrouton/Simple-Package-Creator

Payload-Free Package Creator 2.4 now available

$
0
0

Payload-Free Package Creator.app, an Automator application that allows the selection of an existing script and then create a payload-free package that runs the selected script, has been updated to version 2.4.

The functionality and operations of the app have not changed from Payload-Free Package Creator 2.3. The main change is that Payload-Free Package Creator.app is now a Universal app, allowing it to run natively on both Intel and Apple Silicon Macs.

Payload-Free Package Creator 2.4, along with all components and scripts, are available on GitHub via the link below:

https://github.com/rtrouton/Payload-Free-Package-Creator

Building a Privileges installer package using AutoPkg

$
0
0

In working with folks who want to build installer packages to install the Privileges app, I’ve noticed that a number of them have experienced problems with manually building an installer package for Privileges which correctly installs the Privileges app’s helper tool.

The result of an installer which does not install the helper tool correctly is that when a user requests administrator privileges using the Privileges app, the app prompts them to install the helper tool. This requires administrative rights, which sets up a chicken and egg situation where admin privileges are being required to get admin privileges.

Screen Shot 2022 04 20 at 3 45 38 PM

Fortunately, there is an automated method for building the installer package which (so far) has worked correctly in each case I’m familiar with. There are AutoPkg recipes available for creating a Privileges installer package and AutoPkg is able to build a correctly working Privileges installer package.


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


computername:~ username$ autopkg search com.github.rtrouton.Privileges
Name Repo Path
—- —- —-
Privileges.munki.recipe apfelwerk-recipes Privileges/Privileges.munki.recipe
Privileges.install.recipe rtrouton-recipes Privileges/Privileges.install.recipe
Privileges.munki.recipe rtrouton-recipes Privileges/Privileges.munki.recipe
Privileges.jss.recipe rtrouton-recipes JSS/Privileges.jss.recipe
Privileges.pkg.recipe rtrouton-recipes Privileges/Privileges.pkg.recipe
Privileges.download.recipe rtrouton-recipes Privileges/Privileges.download.recipe
To add a new recipe repo, use 'autopkg repo-add <repo name>'
computername:~ username$
view raw

gistfile1.txt

hosted with ❤ by GitHub

For more details, please see below the jump.

For those not familiar with using AutoPkg, please follow the process below to build a working Privileges installer package:

Note: If you do not want to install AutoPkg on your own Mac, AutoPkg also runs fine in a macOS virtual machine.

1. If Git is not already installed, install Git.

Note: Git must be installed before installing AutoPkg because AutoPkg uses Git for many of AutoPkg’s functions.

Git is included with Xcode or the Xcode Command Line Tools, so installing either Xcode or the Xcode Command Line Tools will also install the necessary Git support.

2. Download the latest AutoPkg installer from https://autopkg.github.io/autopkg

Screen Shot 2022 04 20 at 3 02 36 PM

 

3. Install AutoPkg.

Screen Shot 2022 04 20 at 3 28 03 PM

Screen Shot 2022 04 20 at 3 28 18 PM

4. Open Terminal and run the following command:

autopkg repo-add rtrouton-recipes

Screen Shot 2022 04 20 at 3 38 58 PM

 

5. Once the repo has been added, run the following command to create an AutoPkg override of the AutoPkg recipe which creates the installer package:

autopkg make-override com.github.rtrouton.pkg.privileges

Screen Shot 2022 04 20 at 3 39 41 PM

 

6. An AutoPkg override file should be created with the following recipe identifier:

local.pkg.Privileges

You can verify this by opening the override file in a text editor and looking for the Identifier key.

Screen Shot 2022 04 20 at 3 40 14 PM

 

7. Once the override file has been created, run the following command to create a Privileges installer package:

autopkg run local.pkg.Privileges

Screen Shot 2022 04 20 at 3 40 55 PM

 

You should then see output similar to this:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


username@computername ~ % autopkg run local.pkg.Privileges
Processing local.pkg.Privileges…
The following new items were downloaded:
Download Path
————-
/Users/username/Library/AutoPkg/Cache/local.pkg.Privileges/downloads/Privileges-1.5.2.zip
The following packages were built:
Identifier Version Pkg Path
———- ——- ——–
com.sap.privileges 1.5.2 /Users/username/Library/AutoPkg/Cache/local.pkg.Privileges/Privileges-1.5.2.pkg
username@computername ~ %
view raw

gistfile1.txt

hosted with ❤ by GitHub

The newly-created Privileges installer package should be stored be in ~/Library/AutoPkg/Cache/local.pkg.Privileges.

Screen Shot 2022 04 20 at 3 42 00 PM

 

8. Repeat process as needed for each new version of Privileges.

Apple discontinues macOS Server

$
0
0

After a long run, first beginning with Mac OS X Server 1.0 in 1999, Apple has announced the end of macOS Server as of April 21, 2022. The final version is macOS Server 5.12.2, which runs on macOS Monterey.

Screen Shot 2022 04 21 at 1 46 23 PM

macOS Server 5.12.2 has shed many of the features once supported by macOS Server. As of 5.12.2, the following two services are supported:

Both services are not currently available outside of macOS Server, so Apple discontinuing macOS Server also means the end of the line for Apple’s Open Directory directory service and Apple’s Profile Manager MDM service.

For current customers who have purchased macOS Server, macOS Server 5.12.2 remains available in the App Store.

Screen Shot 2022 04 21 at 1 42 03 PM

Discussing standard versus admin rights, hosted by Kandji

Safari 15.5 embedded content slow to load

$
0
0

As part of the release of Safari 15.5, there seems to be an issue with Safari being able to load embedded content on some websites. One example is the US State Department’s site for reporting a lost or stolen passport:

https://travel.state.gov/content/travel/en/passports/have-passport/lost-stolen.html

This site has embedded content and Safari is very slow to load that site. The behavior seems to be tied to the Hide IP address from trackers setting in Safari’s privacy settings:

Screen Shot 2022 05 18 at 4 09 53 PM

 

With that setting enabled, slow website loading:

With that setting disabled, normal website loading:

Using AutoPkg to build a Cisco AnyConnect installer

$
0
0

HCS Technology Group posted a white paper recently, showing how to deploy Cisco AnyConnect using Jamf Pro. As part of that documentation, HCS described how to create an installer choices XML file and then use it to create a custom Cisco AnyConnect installer package.

It’s possible to replicate this packaging workflow, including generating an installer choices XML file, using AutoPkg. For more details, please see below the jump.

In this example, there are going to be multiple AutoPkg recipes and support files referenced:

  • CiscoAnyConnect.download.recipe – Download recipe for the vendor-supplied Cisco AnyConnect disk image with the vendor-supplied installer package stored inside.
  • CiscoAnyConnect.pkg.recipe – Package recipe for Cisco AnyConnect, which generates an installer choices XML file and wraps both the installer choices XML file and the vendor-supplied installer package inside a separate installer package generated by AutoPkg
  • Example.xml – Sample VPN profile for Cisco AnyConnect’s VPN module
  • Cisco AnyConnect package recipe override – This is the AutoPkg recipe override where you’re defining how the installer choices file is configured and other information being supplied to the Cisco AnyConnect installer by the AutoPkg package creation process.

Important information:

A. You absolutely must create an AutoPkg override to work with these recipes. The download location, configuration for the installer choices XML file and other settings are not included in the AutoPkg recipes themselves and must be defined in the override.

B. The example recipes as written include the following assumptions:

  • You’re using the Cisco AnyConnect Umbrella module.
  • You’re adding the necessary configuration information for the Cisco AnyConnect Umbrella module to the AutoPkg recipe override.
  • You may be using the Cisco AnyConnect VPN module.

C. The Cisco AnyConnect disk image does not have a set address for downloading it, so you will need to do one of the following:

  • Download the disk image from Cisco and host it yourself somewhere.
  • Change the download URL in the AutoPkg recipe override to match wherever you can currently download the Cisco AnyConnect disk image from.

D. To configure the installer choices XML file, you must designate what modules you want to include using ones and zeros in the AutoPkg override. By default, the .pkg recipe is configured to install all modules:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<key>CHOICE_DART</key>
<string>1</string>
<key>CHOICE_FIREAMP</key>
<string>1</string>
<key>CHOICE_ISEPOSTURE</key>
<string>1</string>
<key>CHOICE_NVM</key>
<string>1</string>
<key>CHOICE_POSTURE</key>
<string>1</string>
<key>CHOICE_UMBRELLA</key>
<string>1</string>
<key>CHOICE_VPN</key>
<string>1</string>
<key>CHOICE_WEBSECURITY</key>
<string>1</string>
view raw

gistfile1.txt

hosted with ❤ by GitHub

To change this, change one to zero for the modules you don’t want to install. For example, the configuration below will configure the AnyConnect installer to only install the AnyConnect Umbrella module:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<key>CHOICE_DART</key>
<string>0</string>
<key>CHOICE_FIREAMP</key>
<string>0</string>
<key>CHOICE_ISEPOSTURE</key>
<string>0</string>
<key>CHOICE_NVM</key>
<string>0</string>
<key>CHOICE_POSTURE</key>
<string>0</string>
<key>CHOICE_UMBRELLA</key>
<string>1</string>
<key>CHOICE_VPN</key>
<string>0</string>
<key>CHOICE_WEBSECURITY</key>
<string>0</string>
view raw

gistfile1.txt

hosted with ❤ by GitHub

E. If you do not want to have the VPN module installed or enabled, you will need to set the CHOICE_VPN and DISABLE_VPN settings in the recipe override. Please see below for an example:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<key>CHOICE_VPN</key>
<string>0</string>
<key>CHOICE_WEBSECURITY</key>
<string>0</string>
<key>CONTENT_XML</key>
<string>Put_escaped_XML_profile_text_into_AutoPkg_recipe_override</string>
<key>DISABLE_CUSTOMER_EXPERIENCE_FEEDBACK</key>
<string>false</string>
<key>DISABLE_VPN</key>
<string>true</string>
view raw

gistfile1.txt

hosted with ❤ by GitHub

In this example, the CHOICE_VPN setting is set to zero and the DISABLE_VPN setting is set to true.

F. These recipes allow you to hide the Cisco-provided AnyConnect installers, so that your users will not be able to see them in the Finder. (They will still be visible via the Terminal.) Like the installer choices selection, this can be set using ones and zeros in the AutoPkg override.

To hide, set the HIDE_UNINSTALLERS setting to one:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<key>HIDE_UNINSTALLERS</key>
<string>1</string>
view raw

gistfile1.txt

hosted with ❤ by GitHub

To not hide the uninstallers, set the HIDE_UNINSTALLERS setting to zero:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<key>HIDE_UNINSTALLERS</key>
<string>0</string>
view raw

gistfile1.txt

hosted with ❤ by GitHub

G. It’s possible to disable the customer feedback functionality through the installer. To set this to be disabled, set the DISABLE_CUSTOMER_EXPERIENCE_FEEDBACK setting to true.


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<key>DISABLE_CUSTOMER_EXPERIENCE_FEEDBACK</key>
<string>true</string>
view raw

gistfile1.txt

hosted with ❤ by GitHub

To leave the customer feedback functionality enabled, set the DISABLE_CUSTOMER_EXPERIENCE_FEEDBACK setting to false.


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<key>DISABLE_CUSTOMER_EXPERIENCE_FEEDBACK</key>
<string>false</string>
view raw

gistfile1.txt

hosted with ❤ by GitHub

Please see below for the example .download and .pkg recipes, example VPN XML file and example .pkg recipe override:

Download recipe:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
<plist version="1.0">
<dict>
<key>Description</key>
<string>Downloads a Cisco AnyConnect package from a specified URL.</string>
<key>Identifier</key>
<string>com.company.download.CiscoAnyConnect</string>
<key>Input</key>
<dict>
<key>NAME</key>
<string>Cisco AnyConnect Secure Mobility Client</string>
<key>VENDOR</key>
<string>Cisco</string>
<key>DOWNLOAD_URL</key>
<string>Put_download_URL_into_AutoPkg_recipe_override</string>
</dict>
<key>MinimumVersion</key>
<string>1.0.0</string>
<key>Process</key>
<array>
<dict>
<key>Arguments</key>
<dict>
<key>predicate</key>
<string>DOWNLOAD_URL == "Put_download_URL_into_AutoPkg_recipe_override"</string>
</dict>
<key>Processor</key>
<string>StopProcessingIf</string>
</dict>
<dict>
<key>Processor</key>
<string>URLDownloader</string>
<key>Arguments</key>
<dict>
<key>url</key>
<string>%DOWNLOAD_URL%</string>
<key>request_headers</key>
<dict>
<key>user-agent</key>
<string>%DOWNLOAD_USERAGENT%</string>
<key>referer</key>
<string>%DOWNLOAD_REFERER%</string>
</dict>
</dict>
</dict>
<dict>
<key>Processor</key>
<string>FlatPkgUnpacker</string>
<key>Arguments</key>
<dict>
<key>flat_pkg_path</key>
<string>%pathname%/AnyConnect.pkg</string>
<key>destination_path</key>
<string>%RECIPE_CACHE_DIR%/%VENDOR%/unpack</string>
<key>purge_destination</key>
<true/>
</dict>
</dict>
<dict>
<key>Processor</key>
<string>PkgPayloadUnpacker</string>
<key>Arguments</key>
<dict>
<key>pkg_payload_path</key>
<string>%RECIPE_CACHE_DIR%/%VENDOR%/unpack/vpn_module.pkg/Payload</string>
<key>destination_path</key>
<string>%RECIPE_CACHE_DIR%/%VENDOR%/vpn_module_payload</string>
<key>purge_destination</key>
<true/>
</dict>
</dict>
<dict>
<key>Processor</key>
<string>Versioner</string>
<key>Arguments</key>
<dict>
<key>input_plist_path</key>
<string>%RECIPE_CACHE_DIR%/%VENDOR%/vpn_module_payload/Applications/Cisco/Cisco AnyConnect Secure Mobility Client.app/Contents/Info.plist</string>
<key>plist_version_key</key>
<string>CFBundleShortVersionString</string>
</dict>
</dict>
<dict>
<key>Processor</key>
<string>EndOfCheckPhase</string>
</dict>
</array>
</dict>
</plist>

Package recipe:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
<plist version="1.0">
<dict>
<key>Comments</key>
<string>Based on https://github.com/autopkg/grahampugh-recipes/blob/master/CiscoAnyConnect/CiscoAnyConnect.pkg.recipe
Wraps the vendor package so that it can be run with Choice Changes XML.
Requires a configuration xml profile (VPN_XML) which should be added to the RECIPE_OVERRIDE_DIR before running the recipe. An example is provided named example.xml.
If you need more packages installing, you should make a copy of this recipe and edit the ChoicesXMLGenerator choices list. This isn't overridable. Don't forget to change the Identifier if you do this.
</string>
<key>Description</key>
<string>Creates a Cisco AnyConnect VPN-only package.</string>
<key>Identifier</key>
<string>com.company.pkg.CiscoAnyConnect</string>
<key>ParentRecipe</key>
<string>com.company.download.CiscoAnyConnect</string>
<key>Input</key>
<dict>
<key>NAME</key>
<string>Cisco AnyConnect Secure Mobility Client</string>
<key>VPN_XML</key>
<string>example.xml</string>
<key>CONTENT_XML</key>
<string>Put_escaped_XML_profile_text_into_AutoPkg_recipe_override
</string>
<key>UMBRELLA_ORGANIZATION_ID</key>
<string>Put_text_into_AutoPkg_recipe_override</string>
<key>UMBRELLA_FINGERPRINT</key>
<string>Put_text_into_AutoPkg_recipe_override</string>
<key>UMBRELLA_USER_ID</key>
<string>Put_text_into_AutoPkg_recipe_override</string>
<key>CHOICE_VPN</key>
<string>1</string>
<key>CHOICE_WEBSECURITY</key>
<string>1</string>
<key>CHOICE_FIREAMP</key>
<string>1</string>
<key>CHOICE_DART</key>
<string>1</string>
<key>CHOICE_POSTURE</key>
<string>1</string>
<key>CHOICE_ISEPOSTURE</key>
<string>1</string>
<key>CHOICE_NVM</key>
<string>1</string>
<key>CHOICE_UMBRELLA</key>
<string>1</string>
<key>DISABLE_VPN</key>
<string>false</string>
<key>DISABLE_CUSTOMER_EXPERIENCE_FEEDBACK</key>
<string>false</string>
<key>HIDE_UNINSTALLERS</key>
<string>1</string>
<key>SOFTWARETITLE</key>
<string>AnyConnectSecureMobilityClient</string>
<key>SOFTWARETITLE1</key>
<string>AnyConnect</string>
<key>SOFTWARETITLE2</key>
<string>Secure</string>
<key>SOFTWARETITLE3</key>
<string>Mobility</string>
<key>SOFTWARETITLE4</key>
<string>Client</string>
<key>PKGID</key>
<string>com.cisco.anyconnect</string>
</dict>
<key>MinimumVersion</key>
<string>1.0.0</string>
<key>Process</key>
<array>
<dict>
<key>Arguments</key>
<dict>
<key>pkgdirs</key>
<dict>
<key>Profiles</key>
<string>0755</string>
<key>Profiles/ampenabler</key>
<string>0755</string>
<key>Profiles/feedback</key>
<string>0755</string>
<key>Profiles/iseposture</key>
<string>0755</string>
<key>Profiles/nvm</key>
<string>0755</string>
<key>Profiles/umbrella</key>
<string>0755</string>
<key>Profiles/vpn</key>
<string>0755</string>
<key>Profiles/websecurity</key>
<string>0755</string>
</dict>
<key>pkgroot</key>
<string>%RECIPE_CACHE_DIR%/Scripts</string>
</dict>
<key>Processor</key>
<string>PkgRootCreator</string>
</dict>
<dict>
<key>Arguments</key>
<dict>
<key>pkgdirs</key>
<dict>
</dict>
<key>pkgroot</key>
<string>%RECIPE_CACHE_DIR%/pkgroot</string>
</dict>
<key>Processor</key>
<string>PkgRootCreator</string>
</dict>
<dict>
<key>Arguments</key>
<dict>
<key>pkg_path</key>
<string>%RECIPE_CACHE_DIR%/Scripts/AnyConnect.pkg</string>
<key>source_pkg</key>
<string>%pathname%/AnyConnect.pkg</string>
</dict>
<key>Processor</key>
<string>PkgCopier</string>
</dict>
<dict>
<key>Arguments</key>
<dict>
<key>file_content</key>
<string>%CONTENT_XML%</string>
<key>file_mode</key>
<string>0644</string>
<key>file_path</key>
<string>%RECIPE_CACHE_DIR%/Scripts/Profiles/vpn/%VPN_XML%</string>
</dict>
<key>Processor</key>
<string>FileCreator</string>
</dict>
<dict>
<key>Arguments</key>
<dict>
<key>file_content</key>
<string>{
&quot;organizationId&quot; : &quot;%UMBRELLA_ORGANIZATION_ID%&quot;,
&quot;fingerprint&quot; : &quot;%UMBRELLA_FINGERPRINT%&quot;,
&quot;userId&quot; : &quot;%UMBRELLA_USER_ID%&quot;
}
</string>
<key>file_mode</key>
<string>0644</string>
<key>file_path</key>
<string>%RECIPE_CACHE_DIR%/Scripts/Profiles/umbrella/OrgInfo.json</string>
</dict>
<key>Processor</key>
<string>FileCreator</string>
</dict>
<dict>
<key>Arguments</key>
<dict>
<key>file_content</key>
<string>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;
&lt;plist version=&quot;1.0&quot;&gt;
&lt;array&gt;
&lt;dict&gt;
&lt;key&gt;attributeSetting&lt;/key&gt;
&lt;integer&gt;%CHOICE_VPN%&lt;/integer&gt;
&lt;key&gt;choiceAttribute&lt;/key&gt;
&lt;string&gt;selected&lt;/string&gt;
&lt;key&gt;choiceIdentifier&lt;/key&gt;
&lt;string&gt;choice_vpn&lt;/string&gt;
&lt;/dict&gt;
&lt;dict&gt;
&lt;key&gt;attributeSetting&lt;/key&gt;
&lt;integer&gt;%CHOICE_WEBSECURITY%&lt;/integer&gt;
&lt;key&gt;choiceAttribute&lt;/key&gt;
&lt;string&gt;selected&lt;/string&gt;
&lt;key&gt;choiceIdentifier&lt;/key&gt;
&lt;string&gt;choice_websecurity&lt;/string&gt;
&lt;/dict&gt;
&lt;dict&gt;
&lt;key&gt;attributeSetting&lt;/key&gt;
&lt;integer&gt;%CHOICE_FIREAMP%&lt;/integer&gt;
&lt;key&gt;choiceAttribute&lt;/key&gt;
&lt;string&gt;selected&lt;/string&gt;
&lt;key&gt;choiceIdentifier&lt;/key&gt;
&lt;string&gt;choice_fireamp&lt;/string&gt;
&lt;/dict&gt;
&lt;dict&gt;
&lt;key&gt;attributeSetting&lt;/key&gt;
&lt;integer&gt;%CHOICE_DART%&lt;/integer&gt;
&lt;key&gt;choiceAttribute&lt;/key&gt;
&lt;string&gt;selected&lt;/string&gt;
&lt;key&gt;choiceIdentifier&lt;/key&gt;
&lt;string&gt;choice_dart&lt;/string&gt;
&lt;/dict&gt;
&lt;dict&gt;
&lt;key&gt;attributeSetting&lt;/key&gt;
&lt;integer&gt;%CHOICE_POSTURE%&lt;/integer&gt;
&lt;key&gt;choiceAttribute&lt;/key&gt;
&lt;string&gt;selected&lt;/string&gt;
&lt;key&gt;choiceIdentifier&lt;/key&gt;
&lt;string&gt;choice_posture&lt;/string&gt;
&lt;/dict&gt;
&lt;dict&gt;
&lt;key&gt;attributeSetting&lt;/key&gt;
&lt;integer&gt;%CHOICE_ISEPOSTURE%&lt;/integer&gt;
&lt;key&gt;choiceAttribute&lt;/key&gt;
&lt;string&gt;selected&lt;/string&gt;
&lt;key&gt;choiceIdentifier&lt;/key&gt;
&lt;string&gt;choice_iseposture&lt;/string&gt;
&lt;/dict&gt;
&lt;dict&gt;
&lt;key&gt;attributeSetting&lt;/key&gt;
&lt;integer&gt;%CHOICE_NVM%&lt;/integer&gt;
&lt;key&gt;choiceAttribute&lt;/key&gt;
&lt;string&gt;selected&lt;/string&gt;
&lt;key&gt;choiceIdentifier&lt;/key&gt;
&lt;string&gt;choice_nvm&lt;/string&gt;
&lt;/dict&gt;
&lt;dict&gt;
&lt;key&gt;attributeSetting&lt;/key&gt;
&lt;integer&gt;%CHOICE_UMBRELLA%&lt;/integer&gt;
&lt;key&gt;choiceAttribute&lt;/key&gt;
&lt;string&gt;selected&lt;/string&gt;
&lt;key&gt;choiceIdentifier&lt;/key&gt;
&lt;string&gt;choice_umbrella&lt;/string&gt;
&lt;/dict&gt;
&lt;/array&gt;
&lt;/plist&gt;
</string>
<key>file_mode</key>
<string>0755</string>
<key>file_path</key>
<string>%RECIPE_CACHE_DIR%/Scripts/InstallerChoices.xml</string>
</dict>
<key>Processor</key>
<string>FileCreator</string>
</dict>
<dict>
<key>Arguments</key>
<dict>
<key>file_content</key>
<string>&lt;!– Optional AnyConnect installer settings are provided below. Configure the setting(s) as &quot;true&quot; (default &quot;false&quot; or commented out) to perform optional action(s) at install time. —&gt;
&lt;Transforms&gt;
&lt;DisableVPN&gt;%DISABLE_VPN%&lt;/DisableVPN&gt;
&lt;DisableCustomerExperienceFeedback&gt;%DISABLE_CUSTOMER_EXPERIENCE_FEEDBACK%&lt;/DisableCustomerExperienceFeedback&gt;
&lt;/Transforms&gt;
</string>
<key>file_mode</key>
<string>0755</string>
<key>file_path</key>
<string>%RECIPE_CACHE_DIR%/Scripts/Profiles/ACTransforms.xml</string>
</dict>
<key>Processor</key>
<string>FileCreator</string>
</dict>
<dict>
<key>Arguments</key>
<dict>
<key>file_content</key>
<string>#!/bin/bash
packagePath=&quot;${0%/*}/AnyConnect.pkg&quot;
choicesXML=&quot;${0%/*}/InstallerChoices.xml&quot;
# Set value in AutoPkg override, default is 1 for &quot;true&quot;
hideUninstallers=&quot;%HIDE_UNINSTALLERS%&quot;
# Array of uninstall application bundles on the installer&apos;s target volume
if [[ -n $3 ]]; then
targetVolume=$3
else
targetVolume=&quot;&quot;
fi
uninstallAppBundlePaths=(
&quot;${targetVolume}/Applications/Cisco/Uninstall AnyConnect DART.app&quot;
&quot;${targetVolume}/Applications/Cisco/Uninstall AnyConnect.app&quot;
)
exitCode=0
# Run embedded installer with the Choice Changes XML
if [[ -r &quot;${packagePath}&quot; &amp;&amp; -r &quot;${choicesXML}&quot; ]]; then
if ! /usr/sbin/installer -applyChoiceChangesXML &quot;${choicesXML}&quot; -pkg &quot;${packagePath}&quot; -target &quot;$3&quot;; then
echo &quot;Installation of package \&quot;${packagePath}\&quot; failed.&quot;
exitCode=1
fi
else
echo &quot;Package \&quot;${packagePath}\&quot; not found.&quot;
exitCode=1
fi
# Hide uninstallers
# Override will specify 1 as &quot;true&quot;
# Set to another value to specify &quot;false&quot;
# If variable is unset/null or still contains an AutoPkg variable reference, treat as &quot;true&quot;
if [[ &quot;${hideUninstallers}&quot; -eq 1 || \
-z &quot;${hideUninstallers}&quot; || \
&quot;${hideUninstallers}&quot; == &quot;%&quot;&quot;HIDE_UNINSTALLERS&quot;&quot;%&quot; ]]; then
for uninstallAppBundlePath in &quot;${uninstallAppBundlePaths[@]}&quot;
do
if [[ -d &quot;${uninstallAppBundlePath}&quot; ]]; then
if /usr/bin/chflags hidden &quot;${uninstallAppBundlePath}&quot;; then
echo &quot;Uninstaller app bundle \&quot;${uninstallAppBundlePath}\&quot; was hidden successfully.&quot;
else
echo &quot;Uninstaller app bundle \&quot;${uninstallAppBundlePath}\&quot; was not hidden successfully.&quot;
exitCode=1
fi
else
echo &quot;Uninstaller app bundle \&quot;${uninstallAppBundlePath}\&quot; was not found and cannot be hidden.&quot;
fi
done
else
echo &quot;Uninstallers will not be hidden.&quot;
fi
exit &quot;${exitCode}&quot;
</string>
<key>file_mode</key>
<string>0755</string>
<key>file_path</key>
<string>%RECIPE_CACHE_DIR%/Scripts/postinstall</string>
</dict>
<key>Processor</key>
<string>FileCreator</string>
</dict>
<dict>
<key>Arguments</key>
<dict>
<key>pkg_request</key>
<dict>
<key>chown</key>
<array>
</array>
<key>id</key>
<string>%PKGID%.%VENDOR%%SOFTWARETITLE%</string>
<key>pkgname</key>
<string>%VENDOR%_%SOFTWARETITLE%_%version%</string>
<key>pkgroot</key>
<string>%RECIPE_CACHE_DIR%/pkgroot</string>
<key>pkgtype</key>
<string>flat</string>
<key>scripts</key>
<string>%RECIPE_CACHE_DIR%/Scripts</string>
<key>version</key>
<string>%version%</string>
</dict>
</dict>
<key>Processor</key>
<string>PkgCreator</string>
</dict>
<dict>
<key>Arguments</key>
<dict>
<key>path_list</key>
<array>
<string>%RECIPE_CACHE_DIR%/%VENDOR%</string>
<string>%RECIPE_CACHE_DIR%/pkgroot</string>
</array>
</dict>
<key>Processor</key>
<string>PathDeleter</string>
</dict>
</array>
</dict>
</plist>

Example VPN XML file:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<?xml version="1.0" encoding="UTF-8"?>
<AnyConnectProfile xmlns="http://schemas.xmlsoap.org/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.xmlsoap.org/encoding/ AnyConnectProfile.xsd">
<ClientInitialization>
<UseStartBeforeLogon UserControllable="true">false</UseStartBeforeLogon>
<AutomaticCertSelection UserControllable="false">true</AutomaticCertSelection>
<ShowPreConnectMessage>false</ShowPreConnectMessage>
<CertificateStore>All</CertificateStore>
<CertificateStoreOverride>true</CertificateStoreOverride>
<ProxySettings>Native</ProxySettings>
<AllowLocalProxyConnections>true</AllowLocalProxyConnections>
<AuthenticationTimeout>12</AuthenticationTimeout>
<AutoConnectOnStart UserControllable="true">false</AutoConnectOnStart>
<MinimizeOnConnect UserControllable="true">true</MinimizeOnConnect>
<LocalLanAccess UserControllable="true">true</LocalLanAccess>
<DisableCaptivePortalDetection UserControllable="false">false</DisableCaptivePortalDetection>
<ClearSmartcardPin UserControllable="false">true</ClearSmartcardPin>
<IPProtocolSupport>IPv4,IPv6</IPProtocolSupport>
<AutoReconnect UserControllable="false">true
<AutoReconnectBehavior UserControllable="false">DisconnectOnSuspend</AutoReconnectBehavior>
</AutoReconnect>
<AutoUpdate UserControllable="false">true</AutoUpdate>
<RSASecurIDIntegration UserControllable="false">Automatic</RSASecurIDIntegration>
<WindowsLogonEnforcement>SingleLocalLogon</WindowsLogonEnforcement>
<WindowsVPNEstablishment>LocalUsersOnly</WindowsVPNEstablishment>
<AutomaticVPNPolicy>false</AutomaticVPNPolicy>
<PPPExclusion UserControllable="false">Disable
<PPPExclusionServerIP UserControllable="false"></PPPExclusionServerIP>
</PPPExclusion>
<EnableScripting UserControllable="false">false</EnableScripting>
<EnableAutomaticServerSelection UserControllable="true">false
<AutoServerSelectionImprovement>20</AutoServerSelectionImprovement>
<AutoServerSelectionSuspendTime>4</AutoServerSelectionSuspendTime>
</EnableAutomaticServerSelection>
<RetainVpnOnLogoff>false</RetainVpnOnLogoff>
<AllowManualHostInput>true</AllowManualHostInput>
</ClientInitialization>
<ServerList>
<HostEntry>
<HostName>example.com/</HostName>
<HostAddress>example.com</HostAddress>
<UserGroup>example</UserGroup>
</HostEntry>
</ServerList>
</AnyConnectProfile>
view raw

example.xml

hosted with ❤ by GitHub

Example .pkg recipe override:


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
<plist version="1.0">
<dict>
<key>Identifier</key>
<string>local.pkg.CiscoAnyConnect</string>
<key>Input</key>
<dict>
<key>CHOICE_DART</key>
<string>1</string>
<key>CHOICE_FIREAMP</key>
<string>1</string>
<key>CHOICE_ISEPOSTURE</key>
<string>1</string>
<key>CHOICE_NVM</key>
<string>1</string>
<key>CHOICE_POSTURE</key>
<string>1</string>
<key>CHOICE_UMBRELLA</key>
<string>1</string>
<key>CHOICE_VPN</key>
<string>1</string>
<key>CHOICE_WEBSECURITY</key>
<string>1</string>
<key>CONTENT_XML</key>
<string>Put_escaped_XML_profile_text_into_AutoPkg_recipe_override
</string>
<key>DISABLE_CUSTOMER_EXPERIENCE_FEEDBACK</key>
<string>false</string>
<key>DISABLE_VPN</key>
<string>false</string>
<key>DOWNLOAD_URL</key>
<string>https://company.com/anyconnect-macos-4.10.04071-predeploy-k9.dmg</string&gt;
<key>HIDE_UNINSTALLERS</key>
<string>1</string>
<key>NAME</key>
<string>Cisco AnyConnect Secure Mobility Client</string>
<key>PKGID</key>
<string>com.cisco.anyconnect</string>
<key>SOFTWARETITLE</key>
<string>AnyConnectSecureMobilityClient</string>
<key>SOFTWARETITLE1</key>
<string>AnyConnect</string>
<key>SOFTWARETITLE2</key>
<string>Secure</string>
<key>SOFTWARETITLE3</key>
<string>Mobility</string>
<key>SOFTWARETITLE4</key>
<string>Client</string>
<key>UMBRELLA_FINGERPRINT</key>
<string>2a7145a02f0b4b9799695b224af3f6c3</string>
<key>UMBRELLA_ORGANIZATION_ID</key>
<string>7775762</string>
<key>UMBRELLA_USER_ID</key>
<string>65034259</string>
<key>VENDOR</key>
<string>Cisco</string>
<key>VPN_XML</key>
<string>example.xml</string>
</dict>
<key>ParentRecipe</key>
<string>com.company.pkg.CiscoAnyConnect</string>
<key>ParentRecipeTrustInfo</key>
<dict>
<key>non_core_processors</key>
<dict/>
<key>parent_recipes</key>
<dict>
<key>com.company.download.CiscoAnyConnect</key>
<dict>
<key>path</key>
<string>~/Library/AutoPkg/RecipeRepos/com.company.autopkg_recipes/CiscoAnyConnect/CiscoAnyConnect.download.recipe</string>
<key>sha256_hash</key>
<string>16f0a121a1e537585c4de9324e13512689751f4dda53c8ab61223dc0ac8bbd34</string>
</dict>
<key>com.company.pkg.CiscoAnyConnect</key>
<dict>
<key>path</key>
<string>~/Library/AutoPkg/RecipeRepos/com.company.autopkg_recipes/CiscoAnyConnect/CiscoAnyConnect.pkg.recipe</string>
<key>sha256_hash</key>
<string>b9d0d31e987c232d4b71c381b1f51ab8ba9108474297694aeae137cf5ab8ff87</string>
</dict>
</dict>
</dict>
</dict>
</plist>
view raw

gistfile1.txt

hosted with ❤ by GitHub

WWDC 2022 notes

$
0
0

This week, as in 2020 and 2021, I’m attending Apple’s WWDC 2022 conference from the comforts of home. As part of this, I’m taking notes during the labs and session videos. Due to wanting to stay on the right side of Apple’s NDA, I’ve been posting my notes to Apple’s developer forums rather than to here.

To make it easier for Mac admins to access them, I’ve set up a post in the forums where I’ve linking the various forum posts with my notes. It’s available via the link below:

https://developer.apple.com/forums/thread/707541

Slides from the “Leveling Up – Managing admin rights in the enterprise” session at Penn State MacAdmins Conference 2022

Slides from the “Leveling Up – Managing admin rights in the enterprise” session at MacDevOpsYVR 2022 conference

Videos from Penn State MacAdmins Campfire Sessions 2022

$
0
0

The good folks at Penn State have been posting session videos from the Penn State MacAdmins Campfire Sessions to YouTube. As they become available, you should be able to access them via the link below:

I’ve linked my Leveling Up – Managing admin rights in the enterprise session here:

Session videos from MacDevOps YVR 2022 now available

Viewing all 764 articles
Browse latest View live