<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title>MacBlog</title>
        <link>https://macblog.org</link>
        <description></description>
        <generator>Zola</generator>
        <language>en</language>
        <atom:link href="https://macblog.org/rss.xml" rel="self" type="application/rss+xml"/>
        <lastBuildDate>Mon, 06 Nov 2023 00:00:00 +0000</lastBuildDate>
        <item>
            <title>Use AutoPkg to package GitHub repositories with no binary assets</title>
            <pubDate>Mon, 06 Nov 2023 00:00:00 +0000</pubDate>
            <link>https://macblog.org/autopkg-github-no-assets/</link>
            <guid>https://macblog.org/autopkg-github-no-assets/</guid>
            <description>&lt;p&gt;GitHub is a popular channel for software distribution, and AutoPkg simplifies the task of packaging GitHub-released apps.
AutoPkg&#x27;s &lt;code&gt;GitHubReleasesInfoProvider&lt;&#x2F;code&gt; processor is the standard method for identifying the latest version of software released using GitHub&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;docs.github.com&#x2F;en&#x2F;repositories&#x2F;releasing-projects-on-github&#x2F;about-releases&quot;&gt;Releases&lt;&#x2F;a&gt; feature, but it has one key requirement - a binary asset must be attached to the release.&lt;&#x2F;p&gt;
&lt;p&gt;However, not all software adheres to this convention.
Some repositories might only contain simple shell scripts or other non-binary assets. &lt;&#x2F;p&gt;
&lt;p&gt;To work around this requirement of &lt;code&gt;GitHubReleasesInfoProvider&lt;&#x2F;code&gt;, you can use AutoPkg&#x27;s &lt;code&gt;URLTextSearcher&lt;&#x2F;code&gt; and &lt;code&gt;URLDownloader&lt;&#x2F;code&gt; processors to download the release in the form of a zip archive.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Every GitHub release automatically provides compressed archives of repository contents in both zip and tar formats.
You can access the URLs of these archives via GitHub&#x27;s REST API at the following endpoint:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;plaintext&quot; class=&quot;language-plaintext z-code&quot;&gt;&lt;code class=&quot;language-plaintext&quot; data-lang=&quot;plaintext&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;https:&#x2F;&#x2F;api.github.com&#x2F;repos&#x2F;{OWNER}&#x2F;{REPOSITORY}&#x2F;releases&#x2F;latest
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The JSON response contains a key called &amp;quot;zipball_url&amp;quot; which points to the zip archive:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;plaintext&quot; class=&quot;language-plaintext z-code&quot;&gt;&lt;code class=&quot;language-plaintext&quot; data-lang=&quot;plaintext&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;{
  ...
  &amp;quot;zipball_url&amp;quot;: &amp;quot;https:&#x2F;&#x2F;api.github.com&#x2F;repos&#x2F;{OWNER}&#x2F;{REPOSITORY}&#x2F;zipball&#x2F;v1.0.0&amp;quot;
  ...
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Extracting this URL is straighforward using the &lt;code&gt;URLTextSearcher&lt;&#x2F;code&gt; processor and the regular expression &lt;code&gt;zipball_url\&amp;quot;: \&amp;quot;(.*)\&amp;quot;&lt;&#x2F;code&gt;.
Once extracted, you can download the archive using the URLDownloader processor.&lt;&#x2F;p&gt;
&lt;p&gt;With an archive of the repository downloaded, you can proceed with additional processors as needed to package the repository contents.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;example&quot;&gt;Example&lt;&#x2F;h2&gt;
&lt;p&gt;Consider an example repository that contains a shell script named &lt;code&gt;example.sh&lt;&#x2F;code&gt;, and your goal is to create an installer package that places an executable copy of this script in the default path.
Below is a complete example recipe process:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Process&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;URLTextSearcher&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;url&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;https:&#x2F;&#x2F;api.github.com&#x2F;repos&#x2F;{OWNER}&#x2F;{REPOSITORY}&#x2F;releases&#x2F;latest&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;re_pattern&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;zipball_url&lt;span class=&quot;z-constant z-character z-escape z-double-quoted z-yaml&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;: &lt;span class=&quot;z-constant z-character z-escape z-double-quoted z-yaml&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;(.*)&lt;span class=&quot;z-constant z-character z-escape z-double-quoted z-yaml&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;result_output_var_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;zipball_url&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;request_headers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Accept&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;application&#x2F;vnd.github+json&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;X-GitHub-Api-Version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;2022-11-28&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;URLDownloader&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;url&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%zipball_url%&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;filename&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%NAME%.zip&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Unarchiver&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;archive_path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;downloads&#x2F;%NAME%.zip&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;PkgRootCreator&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;pkgdirs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-flow-mapping z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-mapping z-begin z-yaml&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-mapping z-end z-yaml&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;pkgroot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;scripts&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;PkgRootCreator&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;pkgdirs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;usr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;0755&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;usr&#x2F;local&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;0755&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;usr&#x2F;local&#x2F;bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;0755&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;pkgroot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;pkgroot&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Copier&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;destination_path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;pkgroot&#x2F;usr&#x2F;local&#x2F;bin&#x2F;example&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;overwrite&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-yaml&quot;&gt;true&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;source_path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;%NAME%&#x2F;*&#x2F;example.sh&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;FileCreator&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;file_path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;scripts&#x2F;postinstall&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;file_mode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;0755&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;file_content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-block-scalar z-literal z-yaml&quot;&gt;|&lt;&#x2F;span&gt;
&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        #!&#x2F;bin&#x2F;bash
        &#x2F;bin&#x2F;chmod +x &#x2F;usr&#x2F;local&#x2F;bin&#x2F;example

&lt;&#x2F;span&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;PkgCreator&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;pkg_request&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;pkgname&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%NAME%&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;pkgdir&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;org.macblog.githubexample&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;options&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;purge_ds_store&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;scripts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;scripts&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;chown&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
          &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;usr&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;user&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;root&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;group&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;admin&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;First, the recipe will locate the latest release of the target repository and its associated &lt;code&gt;zipball_url&lt;&#x2F;code&gt; using &lt;code&gt;URLTextSearcher&lt;&#x2F;code&gt;.
Next, it will download the archive using &lt;code&gt;URLDownloader&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Following that, the recipe will extract the archive and create a root directory for building an installer package.
It will then copy the target shell script &lt;code&gt;example.sh&lt;&#x2F;code&gt; from the extracted repository contents to the package root directory at the required location (e.g., &lt;code&gt;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;example&lt;&#x2F;code&gt;). 
Finally, a &lt;code&gt;postinstall&lt;&#x2F;code&gt; script is created to ensure that the file is executable after installation, and everything is packaged into a &lt;code&gt;.pkg&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;authentication-for-private-repos&quot;&gt;Authentication for private repos&lt;&#x2F;h2&gt;
&lt;p&gt;This recipe pattern is also handy for accessing releases without assets in private repositories. 
To do this, you&#x27;ll need to create a &lt;a href=&quot;https:&#x2F;&#x2F;docs.github.com&#x2F;en&#x2F;authentication&#x2F;keeping-your-account-and-data-secure&#x2F;managing-your-personal-access-tokens&quot;&gt;personal access token&lt;&#x2F;a&gt; and set the &lt;code&gt;GITHUB_TOKEN&lt;&#x2F;code&gt; environment variable &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;autopkg&#x2F;wiki&#x2F;FAQ#how-do-i-provide-a-github-personal-access-token-to-autopkg&quot;&gt;as described here&lt;&#x2F;a&gt;.
Then, simply add an &lt;code&gt;Authorization&lt;&#x2F;code&gt; header using Bearer authentication to the &lt;code&gt;URLTextSearcher&lt;&#x2F;code&gt; and &lt;code&gt;URLDownloader&lt;&#x2F;code&gt; processors as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;URLTextSearcher&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;url&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;https:&#x2F;&#x2F;api.github.com&#x2F;repos&#x2F;{OWNER}&#x2F;{REPOSITORY}&#x2F;releases&#x2F;latest&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;re_pattern&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;zipball_url&lt;span class=&quot;z-constant z-character z-escape z-double-quoted z-yaml&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;: &lt;span class=&quot;z-constant z-character z-escape z-double-quoted z-yaml&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;(.*)&lt;span class=&quot;z-constant z-character z-escape z-double-quoted z-yaml&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;result_output_var_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;zipball_url&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;request_headers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Accept&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;application&#x2F;vnd.github+json&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;X-GitHub-Api-Version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;2022-11-28&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Authorization&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Bearer %GITHUB_TOKEN%&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;URLDownloader&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;url&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%zipball_url%&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;filename&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%NAME%.zip&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;request_headers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Authorization&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Bearer %GITHUB_TOKEN%&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This approach keeps your options open for packaging a variety of GitHub releases, whether they include binary assets or not.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Manage and enforce custom Login and Background items in macOS Ventura</title>
            <pubDate>Mon, 24 Oct 2022 00:00:00 +0000</pubDate>
            <link>https://macblog.org/manage-custom-login-items/</link>
            <guid>https://macblog.org/manage-custom-login-items/</guid>
            <description>&lt;p&gt;macOS Ventura introduces a new feature that provides users an interface to selectively enable and disable Login and Background items.&lt;&#x2F;p&gt;
&lt;p&gt;You may be familiar with &amp;quot;Login Items&amp;quot; – those apps, documents, or server connections you&#x27;ve configured in &lt;em&gt;System Preferences &amp;gt; Users &amp;amp; Groups &amp;gt; Login Items&lt;&#x2F;em&gt; to automatically open when you log in.
The feature and interface has remained largely unchanged since Mac OS X Tiger.&lt;&#x2F;p&gt;
&lt;p&gt;macOS Ventura extends this idea to encompass &lt;em&gt;any&lt;&#x2F;em&gt; process configured to automatically launch in the background.
&lt;code&gt;launchd&lt;&#x2F;code&gt; jobs like LaunchDaemons and LaunchAgents can now be toggled on or off in the new System Settings app.&lt;&#x2F;p&gt;
&lt;p&gt;This means non-apps, like any custom scripts you deploy to your managed Macs, can be easily turned off.
Depending on how you manage your Macs, the ability to trivially disable management processes can have compliance, audit, and user support implications.&lt;&#x2F;p&gt;
&lt;p&gt;Along with the new functionality, Apple is providing a new Configuration Profile payload to manage or &amp;quot;lock on&amp;quot; your organization&#x27;s login items on MDM-enrolled Macs.
Login and Background items managed by this new payload cannot be disabled by users within the System Settings&lt;&#x2F;p&gt;
&lt;p&gt;This guide will demonstrate how you can sign, package, and &amp;quot;lock on&amp;quot; a custom script.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Official documentation from Apple is &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;apple&#x2F;device-management&#x2F;blob&#x2F;release&#x2F;mdm&#x2F;profiles&#x2F;com.apple.servicemanagement.yaml&quot;&gt;currently sparse&lt;&#x2F;a&gt;.
Rather than attempting to fully document all aspects of &amp;quot;service management&amp;quot; features, this guide focuses on managing custom shell scripts you might run on your organization&#x27;s Macs.&lt;&#x2F;p&gt;
&lt;p&gt;First, I&#x27;ll offer my observations on how managed Login and Background Items work in practice.&lt;&#x2F;p&gt;
&lt;p&gt;Applications configured to run in the background at login appear in &lt;em&gt;System Settings &amp;gt; General &amp;gt; Login Items&lt;&#x2F;em&gt; under the &lt;em&gt;Allow in Background&lt;&#x2F;em&gt; heading.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;login-items-apps.8a416ab7b210c3f2.webp&quot;width=&quot;720&quot; height=&quot;641&quot;&gt;&lt;figcaption&gt;Two apps configured to run in the background at login.&lt;&#x2F;figcaption&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Things are more complicated with items that are not apps, such as a shell script executed by a &lt;code&gt;launchd&lt;&#x2F;code&gt; job.&lt;&#x2F;p&gt;
&lt;p&gt;Running a shell script via a LaunchDaemon or LaunchAgent is a common pattern used by administrators to automatically perform management tasks on managed Macs.&lt;&#x2F;p&gt;
&lt;p&gt;As a minimal example, the following LaunchDaemon plist will run a script at path &lt;code&gt;&#x2F;opt&#x2F;pretendco&#x2F;example-startup-script.sh&lt;&#x2F;code&gt; when the Mac starts up:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-preprocessor z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-xml&quot;&gt;xml&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;encoding&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;UTF-8&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;?&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-sgml z-doctype z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-doctype z-xml&quot;&gt;DOCTYPE&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-documentroot z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-external-content z-xml&quot;&gt;PUBLIC&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-&#x2F;&#x2F;Apple&#x2F;&#x2F;DTD PLIST 1.0&#x2F;&#x2F;EN&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;http:&#x2F;&#x2F;www.apple.com&#x2F;DTDs&#x2F;PropertyList-1.0.dtd&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Label&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.pretendco.startup&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;ProgramArguments&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;opt&#x2F;pretendco&#x2F;example-startup-script.zsh&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If a launchd task executes a script using the &lt;code&gt;Program&lt;&#x2F;code&gt; or &lt;code&gt;ProgramArguments&lt;&#x2F;code&gt; key, that script&#x27;s filename appears as the display value in System Settings.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;login-items-unsigned-script.95c55ac6d8c7664f.webp&quot;width=&quot;720&quot; height=&quot;641&quot;&gt;&lt;figcaption&gt;A shell script run by a LaunchDaemon lists that script&#x27;s filename in System Settings &gt; General &gt; Login Items.&lt;&#x2F;figcaption&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Either of the following &lt;code&gt;launchd&lt;&#x2F;code&gt; job configurations results in System Settings listing the item by filename:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Program&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;opt&#x2F;example.zsh&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;ProgramArguments&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;opt&#x2F;example.zsh&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Items are listed according to what they run.
The details of how macOS determines a login item&#x27;s attribution chain are complex and poorly documented.&lt;&#x2F;p&gt;
&lt;p&gt;The gist is that scripts are attributed by filename in the absence of additional identity information.
I will explain a method to provide that identity information by code signing the script later in this guide.&lt;&#x2F;p&gt;
&lt;p&gt;Before that, let&#x27;s look at how to enforce Login and Background items via Configuration Profile.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;manage-items-using-mdm&quot;&gt;Manage items using MDM&lt;&#x2F;h2&gt;
&lt;p&gt;We can use the new &lt;code&gt;com.apple.servicemanagement&lt;&#x2F;code&gt; Configuration Profile payload to automatically enable, allow, and &amp;quot;lock on&amp;quot; our &lt;code&gt;launchd&lt;&#x2F;code&gt; jobs and associated scripts.&lt;&#x2F;p&gt;
&lt;p&gt;This payload allows you to configure rules to control which Login Items cannot be disabled by a user in &lt;em&gt;System Settings &amp;gt; General &amp;gt; Login Items&lt;&#x2F;em&gt;.
&lt;strong&gt;Administrative users can still use &lt;code&gt;launchctl&lt;&#x2F;code&gt; to unload a &lt;code&gt;launchd&lt;&#x2F;code&gt; job.&lt;&#x2F;strong&gt;
Managing an item via MDM only disables the GUI control to easily toggle an item off.&lt;&#x2F;p&gt;
&lt;p&gt;Rules are defined as an array of dictionaries within a Configuration Profile.
Each rule defines one of five &lt;code&gt;RuleTypes&lt;&#x2F;code&gt; that control different items:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Rule type&lt;&#x2F;th&gt;&lt;th&gt;Manages&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;TeamIdentifier&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Any item signed by that team&#x27;s certificate(s)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;BundleIdentifier&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Single item exactly matching a bundle identifier, e.g. &lt;code&gt;org.macblog.exampleapp&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Label&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Single &lt;code&gt;launchd&lt;&#x2F;code&gt; job definition with exactly matching label, e.g. &lt;code&gt;org.macblog.startup&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;BundleIdentifierPrefix&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Any item with a bundle identifier starting with the provided value, e.g. &lt;code&gt;org.macblog&lt;&#x2F;code&gt; matches&lt;br&gt;- &lt;code&gt;org.macblog.example&lt;&#x2F;code&gt;&lt;br&gt;- &lt;code&gt;org.macblog.somethingelse&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;LabelPrefix&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Any &lt;code&gt;launchd&lt;&#x2F;code&gt; job definition with a label starting with the provided value, e.g. &lt;code&gt;org.macblog&lt;&#x2F;code&gt; matches&lt;br&gt;- &lt;code&gt;org.macblog.example&lt;&#x2F;code&gt;&lt;br&gt;- &lt;code&gt;org.macblog.somethingelse&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;In general, you should use the most explicit rule type applicable to a particular login item.
It may be tempting to use broad &lt;code&gt;TeamIdentifier&lt;&#x2F;code&gt; rules for convenience, but if we&#x27;re getting new controls, I want to use them correctly.
I may not want to manage and &amp;quot;lock on&amp;quot; &lt;em&gt;any&lt;&#x2F;em&gt; process a vendor might install, making a &lt;code&gt;TeamIdentifier&lt;&#x2F;code&gt; rule inappropriate.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a complete example Configuration Profile to manage two specific LaunchDaemons by label:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-preprocessor z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-xml&quot;&gt;xml&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;encoding&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;UTF-8&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;?&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-sgml z-doctype z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-doctype z-xml&quot;&gt;DOCTYPE&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-documentroot z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-external-content z-xml&quot;&gt;PUBLIC&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-&#x2F;&#x2F;Apple&#x2F;&#x2F;DTD PLIST 1.0&#x2F;&#x2F;EN&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;http:&#x2F;&#x2F;www.apple.com&#x2F;DTDs&#x2F;PropertyList-1.0.dtd&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadDisplayName&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Example Login and Background Item Management&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadIdentifier&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.apple.servicemanagement.CA085574-9E75-4049-AACF-B7546F8B1378.privacy&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadUUID&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;E572AD76-1AA0-48CA-872F-3A59784148F4&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadType&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Configuration&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadScope&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;System&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadContent&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadDescription&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Configures managed Login and Background items.&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadDisplayName&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Example Login and Background Item Management&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadIdentifier&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;A2EF9B5B-C13F-432C-8645-8FFE1C2024B7&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadUUID&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;023BAA5C-29D4-4CAB-8042-64832AD3E6BB&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadType&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.apple.servicemanagement&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadOrganization&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Pretendco&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Rules&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;RuleType&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Label&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;RuleValue&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.pretendco.example-startup-script&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Comment&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;LaunchDaemon that runs a shell script at startup.&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;RuleType&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Label&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;RuleValue&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.pretendco.second-example&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Comment&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Another, different, example LaunchDaemon.&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Apple has provided a new command line tool in Ventura to help discover the values you might need to include in a &lt;code&gt;com.apple.servicemanagement&lt;&#x2F;code&gt; profile.
You can run &lt;code&gt;sudo sfltool dumpbtm&lt;&#x2F;code&gt; to view a verbose listing of all loaded Login and Background items.&lt;&#x2F;p&gt;
&lt;p&gt;Here, however, I&#x27;m focused here on demonstrating how to manage custom background items you create.
Next, I&#x27;ll walk through preparing a script for deployment.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;packaging-a-startup-script-from-scratch&quot;&gt;Packaging a startup script from scratch&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s step through a complete example of creating a script and LaunchDaemon designed to run at startup.
We&#x27;ll use &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;munki&#x2F;munki-pkg&quot;&gt;munkipkg&lt;&#x2F;a&gt; to package these components for deployment. If you&#x27;re not familiar with munkipkg, &lt;a href=&quot;https:&#x2F;&#x2F;www.elliotjordan.com&#x2F;posts&#x2F;munkipkg-01-intro&#x2F;&quot;&gt;Elliot Jordan&#x27;s You Might Like MunkiPkg guide&lt;&#x2F;a&gt; is an excellent resource.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;setup&quot;&gt;Setup&lt;&#x2F;h3&gt;
&lt;p&gt;Create a new project and scaffold out the structure with the following commands.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;munkipkg --create macblog-example
mkdir -p macblog-example&#x2F;payload&#x2F;Library&#x2F;LaunchDaemons
mkdir -p macblog-example&#x2F;payload&#x2F;opt&#x2F;macblog
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The project folder will look like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;plaintext&quot; class=&quot;language-plaintext z-code&quot;&gt;&lt;code class=&quot;language-plaintext&quot; data-lang=&quot;plaintext&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;macblog-example
├── build
├── build-info.plist
├── payload
│   ├── Library
│   │   └── LaunchDaemons
│   └── opt
│       └── macblog
└── scripts
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;the-script&quot;&gt;The script&lt;&#x2F;h3&gt;
&lt;p&gt;For this example, we&#x27;ll create a simple script that will write a log file when run.&lt;&#x2F;p&gt;
&lt;p&gt;Save the following to &lt;code&gt;payload&#x2F;opt&#x2F;macblog&#x2F;example-startup-script.zsh&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#!&#x2F;bin&#x2F;zsh
echo &amp;quot;$( &#x2F;bin&#x2F;date ): example script execution&amp;quot; &amp;gt;&amp;gt; &#x2F;Library&#x2F;Logs&#x2F;example.log
exit 0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;the-launchdaemon&quot;&gt;The LaunchDaemon&lt;&#x2F;h3&gt;
&lt;p&gt;Next, create a LaunchDaemon to run the script every time the computer starts up.
There are &lt;a href=&quot;https:&#x2F;&#x2F;launchd.info&quot;&gt;many options for launchd job definitions&lt;&#x2F;a&gt; but we&#x27;ll keep it very minimal.&lt;&#x2F;p&gt;
&lt;p&gt;Save the following to &lt;code&gt;payload&#x2F;Library&#x2F;LaunchDaemons&#x2F;org.macblog.example.plist&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-preprocessor z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-xml&quot;&gt;xml&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;encoding&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;UTF-8&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;?&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-sgml z-doctype z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-doctype z-xml&quot;&gt;DOCTYPE&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-documentroot z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-external-content z-xml&quot;&gt;PUBLIC&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-&#x2F;&#x2F;Apple&#x2F;&#x2F;DTD PLIST 1.0&#x2F;&#x2F;EN&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;http:&#x2F;&#x2F;www.apple.com&#x2F;DTDs&#x2F;PropertyList-1.0.dtd&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Label&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;org.macblog.example&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;ProgramArguments&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;opt&#x2F;macblog&#x2F;example-startup-script.zsh&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;the-postinstall-script&quot;&gt;The &lt;code&gt;postinstall&lt;&#x2F;code&gt; script&lt;&#x2F;h3&gt;
&lt;p&gt;In order to set the proper file ownership and permissions, create a &lt;code&gt;postinstall&lt;&#x2F;code&gt; script.
This script will run during installation of the package, after the files are in place.&lt;&#x2F;p&gt;
&lt;p&gt;Save the following to &lt;code&gt;scripts&#x2F;postinstall&lt;&#x2F;code&gt; - note the lack of a file extension on this file; you must follow this convention:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#!&#x2F;bin&#x2F;zsh
&#x2F;bin&#x2F;chmod 0744 &#x2F;opt&#x2F;macblog&#x2F;example-startup-script.zsh
&#x2F;usr&#x2F;sbin&#x2F;chown root:wheel &#x2F;opt&#x2F;macblog&#x2F;example-startup-script.zsh
&#x2F;bin&#x2F;chmod 0644 &#x2F;Library&#x2F;LaunchDaemons&#x2F;org.macblog.example.plist
&#x2F;usr&#x2F;sbin&#x2F;chown root:wheel &#x2F;Library&#x2F;LaunchDaemons&#x2F;org.macblog.example.plist
&#x2F;bin&#x2F;launchctl bootstrap system &#x2F;Library&#x2F;LaunchDaemons&#x2F;org.macblog.example.plist
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This script also loads the LaunchDaemon after installation, so you won&#x27;t need to reboot the system for the startup script to run for the first time.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sign-the-startup-script&quot;&gt;Sign the startup script&lt;&#x2F;h3&gt;
&lt;p&gt;I recently wrote a &lt;a href=&quot;https:&#x2F;&#x2F;macblog.org&#x2F;sign-scripts&#x2F;&quot;&gt;full guide to signing custom scripts&lt;&#x2F;a&gt;, so I won&#x27;t detail the entire process again here.
Go read that guide first.&lt;&#x2F;p&gt;
&lt;p&gt;Use a &lt;strong&gt;Developer ID Application&lt;&#x2F;strong&gt; certificate issued by Apple to code sign the startup script:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;codesign --sign &amp;quot;Developer ID Application: MacBlog.org (SHJS42SFS32S)&amp;quot; \
    --identifier &amp;quot;org.macblog.example&amp;quot; \
    payload&#x2F;opt&#x2F;macblog&#x2F;example-startup-script.zsh
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By signing the script, we provide identity information to macOS about the authorship of the code.
These details are used to display the attribution of the item in &lt;em&gt;System Settings &amp;gt; General &amp;gt; Login Items&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;mark&gt;This is the key to properly managing the login item.
Signing the script provides the idenity information macOS needs to attribute the login item correctly.&lt;&#x2F;mark&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;edit-build-info-plist&quot;&gt;Edit &lt;code&gt;build-info.plist&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;build-info.plist&lt;&#x2F;code&gt; controls various options for how the package is built.
The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;munki&#x2F;munki-pkg#build-info-keys&quot;&gt;MunkiPkg readme details all available build-info keys&lt;&#x2F;a&gt; and offers guidance on their use.&lt;&#x2F;p&gt;
&lt;p&gt;I suggest you &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;munki&#x2F;munki-pkg#package-signing&quot;&gt;sign the package&lt;&#x2F;a&gt; by including &lt;code&gt;signing_info&lt;&#x2F;code&gt;.
If we&#x27;re code signing the deployed startup script, we might as well code sign the deployment package too, right?
You&#x27;ll need a &lt;strong&gt;Developer ID Installer&lt;&#x2F;strong&gt; certificate from Apple to sign the package.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;package-it-all-up-and-test&quot;&gt;Package it all up and test&lt;&#x2F;h3&gt;
&lt;p&gt;The full project layout now looks like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;plaintext&quot; class=&quot;language-plaintext z-code&quot;&gt;&lt;code class=&quot;language-plaintext&quot; data-lang=&quot;plaintext&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;macblog-example
├── build
├── build-info.plist
├── payload
│   ├── Library
│   │   └── LaunchDaemons
│   │       └── org.macblog.example.plist
│   └── opt
│       └── macblog
│           └── example-startup-script.zsh
└── scripts
    └── postinstall
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Make sure you&#x27;re in the directory containing the &lt;code&gt;macblog-example&lt;&#x2F;code&gt; project, then run:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;munkipkg macblog-example
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This outputs your completed package to the &lt;code&gt;macblog-example&#x2F;build&lt;&#x2F;code&gt; directory.&lt;&#x2F;p&gt;
&lt;p&gt;If you install the finalized package, you&#x27;ll notice &lt;code&gt;sudo launchctl list&lt;&#x2F;code&gt; will now report the the &lt;code&gt;org.macblog.example&lt;&#x2F;code&gt; job running, and &lt;code&gt;&#x2F;Library&#x2F;Logs&#x2F;example.log&lt;&#x2F;code&gt; will show an entry.&lt;&#x2F;p&gt;
&lt;p&gt;More importantly, &lt;em&gt;System Settings &amp;gt; General &amp;gt; Login Items&lt;&#x2F;em&gt; will list a new item attributed to the signing identity you used to sign the script!&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;login-items-signed-script.204939cfa77e111a.webp&quot;width=&quot;720&quot; height=&quot;641&quot;&gt;&lt;figcaption&gt;A signed script attributed to the signing identity.&lt;&#x2F;figcaption&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;The UI displays the attribution of &lt;em&gt;what&#x27;s ultimately being executed&lt;&#x2F;em&gt; – in this case, the &lt;code&gt;example-startup-script.zsh&lt;&#x2F;code&gt; file.
Since that file is signed, the identity information tied to that certificate is shown in &lt;em&gt;System Settings&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;mark&gt;&lt;strong&gt;The LaunchDaemon does not determine the attribution shown in the interface.&lt;&#x2F;strong&gt;
Think about it this way: the interface displays identity information about what&#x27;s running, not what &amp;quot;causes&amp;quot; it to run.&lt;&#x2F;mark&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;manage-the-script-using-mdm&quot;&gt;Manage the script using MDM&lt;&#x2F;h3&gt;
&lt;p&gt;Create a Configuration Profile using the example above.
The specific rule to manage the custom script should look like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;RuleType&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Label&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;RuleValue&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;org.macblog.example&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Comment&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Example rule&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that the &lt;code&gt;RuleValue&lt;&#x2F;code&gt; must match the &lt;code&gt;Label&lt;&#x2F;code&gt; of the LaunchDaemon we created earlier.&lt;&#x2F;p&gt;
&lt;p&gt;For the sake of completeness, a full example Configuration Profile will look like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-preprocessor z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-xml&quot;&gt;xml&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;encoding&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;UTF-8&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;?&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-sgml z-doctype z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-doctype z-xml&quot;&gt;DOCTYPE&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-documentroot z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-external-content z-xml&quot;&gt;PUBLIC&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-&#x2F;&#x2F;Apple&#x2F;&#x2F;DTD PLIST 1.0&#x2F;&#x2F;EN&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;http:&#x2F;&#x2F;www.apple.com&#x2F;DTDs&#x2F;PropertyList-1.0.dtd&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadDisplayName&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Example Login and Background Item Management&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadIdentifier&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.apple.servicemanagement.CA085574-9E75-4049-AACF-B7546F8B1378.privacy&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadUUID&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;E572AD76-1AA0-48CA-872F-3A59784148F4&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadType&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Configuration&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadScope&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;System&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadContent&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadDescription&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Configures managed Login and Background items.&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadDisplayName&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Example Login and Background Item Management&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadIdentifier&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;A2EF9B5B-C13F-432C-8645-8FFE1C2024B7&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadUUID&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;023BAA5C-29D4-4CAB-8042-64832AD3E6BB&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadType&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.apple.servicemanagement&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadOrganization&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Pretendco&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Rules&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;RuleType&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Label&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;RuleValue&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;org.macblog.example&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Comment&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Example rule&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When deployed to your endpoints via MDM, the Configuration Profile applies the rules provided.
Since we signed the script being executed, its identity information is shown in Login Items.
The script is flagged as &amp;quot;managed by your organization&amp;quot; and is &amp;quot;locked on.&amp;quot;&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;login-items-signed-locked.44143277333ab0cd.webp&quot;width=&quot;720&quot; height=&quot;641&quot;&gt;&lt;figcaption&gt;Managed login item locked on, with proper identity information.&lt;&#x2F;figcaption&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;All done!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;avoid-pitfalls&quot;&gt;Avoid pitfalls&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;ve seen some launchd configurations that use the &lt;code&gt;ProgramArguments&lt;&#x2F;code&gt; array to first specify the path to an interpreter, then the path to a script, like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;ProgramArguments&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;bin&#x2F;zsh&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;opt&#x2F;example.zsh&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This tells macOS that &lt;code&gt;&#x2F;bin&#x2F;zsh&lt;&#x2F;code&gt; (or bash, or Python, etc) is the process your LaunchDaemon is launching, which your script as an argument.
That&#x27;s wrong, and it causes macOS to attribute the interpretter as the launched process.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;login-items-interpretter.46f9b17adc7c9926.webp&quot;width=&quot;720&quot; height=&quot;641&quot;&gt;&lt;figcaption&gt;Listing a script&#x27;s interpretter in the launchd plist will lead to an incorrect attribution in System Settings.&lt;&#x2F;figcaption&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;&lt;strong&gt;Don&#x27;t do this.&lt;&#x2F;strong&gt;
You should set the path to the script&#x27;s interpreter in its shebang, then make the script itself executable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;future&quot;&gt;Future&lt;&#x2F;h2&gt;
&lt;p&gt;Managing legacy launchd plists works fine for now in Ventura, but there&#x27;s a reason &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;documentation&#x2F;servicemanagement&#x2F;smappservice&#x2F;4024717-statusforlegacyurl?language=objc&quot;&gt;they&#x27;re marked &lt;strong&gt;legacy&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;mark&gt;The concept of &amp;quot;login items&amp;quot; and the new &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;documentation&#x2F;servicemanagement&#x2F;smappservice?language=objc&quot;&gt;SMAppService&lt;&#x2F;a&gt; API signals a transition in Apple&#x27;s recommended application design process.&lt;&#x2F;mark&gt;
All helper resources should live inside an app bundle, and macOS will increasingly expect items to be deployed this way.&lt;&#x2F;p&gt;
&lt;p&gt;In a future version of macOS, it will likely be the &lt;strong&gt;only&lt;&#x2F;strong&gt; method to automatically launch a process.
Deleting an app bundle would delete all associated resources and automated processes.
That&#x27;s a win for the end user.&lt;&#x2F;p&gt;
&lt;p&gt;With this clear signal toward a future without LaunchDaemons and LaunchAgents, I&#x27;m personally going to invest more time in learning Swift.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>How to sign scripts and other custom code</title>
            <pubDate>Tue, 04 Oct 2022 00:00:00 +0000</pubDate>
            <link>https://macblog.org/sign-scripts/</link>
            <guid>https://macblog.org/sign-scripts/</guid>
            <description>&lt;p&gt;Code signing is a method of certifying that a program or script was created by a specific party, and has not been altered since it was signed.&lt;&#x2F;p&gt;
&lt;p&gt;While code signing is typically discussed in the context of apps (.app bundles), the same concept applies to almost any file stored on disk.
You can easily code sign custom scripts and other files you deploy on your managed Macs.&lt;&#x2F;p&gt;
&lt;p&gt;This article provides an overview of why and how you might want to do that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-sign-your-code-as-a-mac-administrator&quot;&gt;Why sign your code as a Mac administrator?&lt;&#x2F;h2&gt;
&lt;p&gt;Signing your code provides a few benefits.&lt;&#x2F;p&gt;
&lt;p&gt;First, it certifies &lt;strong&gt;authenticity&lt;&#x2F;strong&gt;.
Signed code provides macOS (and your users) a mechanism to verify that a program was created by a specific trusted entity, and deployed to the Mac without modification.&lt;&#x2F;p&gt;
&lt;p&gt;Second, it verifies code &lt;strong&gt;integrity&lt;&#x2F;strong&gt;.
If a user or malicious process modifies the code, a code signature check will fail.
As an administrator, you can leverage code signature verification to detect when custom programs have been altered or tampered with.&lt;&#x2F;p&gt;
&lt;p&gt;Third, macOS continues to surface security- and privacy-related information within the macOS interface.
Things that used to be &amp;quot;behind the scenes,&amp;quot; like programs an administrator might run an organizationally managed Mac, are becoming more visible.&lt;&#x2F;p&gt;
&lt;p&gt;This increased visibility is good for end users, and means we need to take an extra step as administrators to supply identity information about the programs we deploy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;signed-scripts-are-not-necessarily-secure-scripts&quot;&gt;Signed scripts are not necessarily secure scripts&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s important to note that the presence of a code signature does not mean a script is &amp;quot;safe.&amp;quot;
&lt;mark&gt;Code signing does not evaluate a script for security vulnerabilities, malicious behavior, or code correctness.&lt;&#x2F;mark&gt;
The signature only assures that the script was provided by some entity and has not been changed since it was provided.&lt;&#x2F;p&gt;
&lt;p&gt;For app bundles, Gatekeeper assesses the code signature when a user opens that app for the first time.
Changes to the bundle&#x27;s contents after the time of signing will invalidate that signature.
If the signature is invalid, Gatekeeper prevents the app from running.&lt;&#x2F;p&gt;
&lt;p&gt;Gatekeeper does no such assessment for code signed scripts you might run by automation (like via &lt;code&gt;launchd&lt;&#x2F;code&gt;) on a managed Mac.
It offers no protection against scripts with invalid signatures.&lt;&#x2F;p&gt;
&lt;p&gt;A malicious actor could modify external files referenced by a script, alter its interpreter, or try a number of other attacks – all without invalidating that script&#x27;s signature.
macOS makes no attempt to validate a script&#x27;s contents or referenced resources.&lt;&#x2F;p&gt;
&lt;p&gt;Signed scripts are certainly no &lt;em&gt;less&lt;&#x2F;em&gt; secure to run or deploy than unsigned scripts, but &lt;strong&gt;please do not mistake code signing as a security practice&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-can-i-sign&quot;&gt;What can I sign?&lt;&#x2F;h2&gt;
&lt;p&gt;You can sign just about any &amp;quot;flat&amp;quot; file.
Text files; shell scripts; Python modules; photo files; PDFs; XML property list files like LaunchDaemons and LaunchAgents.&lt;&#x2F;p&gt;
&lt;p&gt;Shell scripts are the most relevant file type for most administrators, but the steps below are the same for any file type you might sign.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;get-a-signing-certificate&quot;&gt;Get a signing certificate&lt;&#x2F;h2&gt;
&lt;p&gt;A foundational element of all public key infrastructure is trust.
A code signing certificate needs to be issued by a certificate authority that macOS trusts in order to be considered valid.&lt;&#x2F;p&gt;
&lt;p&gt;The best place to get a trusted code signing certificate is from Apple.
Members of the &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;programs&#x2F;&quot;&gt;Apple Developer Program&lt;&#x2F;a&gt; can generate one of several different certificate types suitable for code signing.&lt;&#x2F;p&gt;
&lt;p&gt;I recommend the &lt;strong&gt;Developer ID Application&lt;&#x2F;strong&gt; certificate.
This certificate type includes the Code Signing extended key usage object identifier &lt;code&gt;1.3.6.1.5.5.7.3.3&lt;&#x2F;code&gt; required to sign code.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Sign in to the Apple Developer Program account portal.&lt;&#x2F;li&gt;
&lt;li&gt;Click &amp;quot;Certificates, IDs &amp;amp; Profiles&amp;quot;.&lt;&#x2F;li&gt;
&lt;li&gt;Click the dropdown menu near the upper left labeled &amp;quot;iOS, tvOS, watchOS&amp;quot; then select &amp;quot;macOS&amp;quot;.&lt;&#x2F;li&gt;
&lt;li&gt;Click &amp;quot;All&amp;quot; under the &amp;quot;Certificates&amp;quot; heading, then click the plus button near the upper right.&lt;&#x2F;li&gt;
&lt;li&gt;When prompted &amp;quot;What type of certificate do you need?&amp;quot;, select &amp;quot;Developer ID&amp;quot;, click Continue, then select &amp;quot;&lt;strong&gt;Developer ID Application&lt;&#x2F;strong&gt;.&amp;quot;&lt;&#x2F;li&gt;
&lt;li&gt;Follow Apple&#x27;s on-screen instructions to generate a Certificate Signing Request (CSR) and install the resultant certificate in your login keychain.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Other certificates available from Apple may also work, but the &lt;strong&gt;Developer ID Application&lt;&#x2F;strong&gt; certificate is the best choice for this task.&lt;&#x2F;p&gt;
&lt;p&gt;If you do not participate in the Apple Developer Program, other vendors may provide code signing certificates.
You can also easily &lt;a href=&quot;https:&#x2F;&#x2F;eclecticlight.co&#x2F;2019&#x2F;01&#x2F;16&#x2F;code-signing-for-the-concerned-2-creating-a-personal-certificate&#x2F;&quot;&gt;generate a self-signed code signing certificate&lt;&#x2F;a&gt; on your Mac.
However, self-signed or third-party certificates are unlikely to be trusted by default on your client Macs.&lt;&#x2F;p&gt;
&lt;p&gt;Make your life easier and use an Apple-provided code signing certificate.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-sign-a-file&quot;&gt;How to sign a file&lt;&#x2F;h2&gt;
&lt;p&gt;You&#x27;ll need to know the common name of the certificate you wish to use for code signing.
You can list the certificates installed in your keychain that are suitable for code signing with the following command:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;security find-identity -p codesigning -v
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A list of code signing certificates will be displayed on screen.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  1) {hash} &amp;quot;Developer ID Application: MacBlog.org (TEAMID)&amp;quot;
     1 valid identities found
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The SHA-1 fingerprint and common name is displayed for each valid code signing certificate in your login keychain.
Note the common name (in quotes) of the certificate you&#x27;d like to use.
You&#x27;ll need to provide that exact common name as an argument to the &lt;code&gt;codesign&lt;&#x2F;code&gt; binary.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;codesign --sign &amp;quot;{signing identity}&amp;quot; \
    --identifier &amp;quot;{reverse-DNS string}&amp;quot; \
    &#x2F;path&#x2F;to&#x2F;file.zsh
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In practice, this would look something like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;codesign --sign &amp;quot;Developer ID Application: MacBlog.org (SHJS42SFS32S)&amp;quot; \
    --identifier &amp;quot;org.macblog.example&amp;quot; \
    ~&#x2F;Code&#x2F;example.zsh
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first option, &lt;code&gt;--sign&lt;&#x2F;code&gt;, tells &lt;code&gt;codesign&lt;&#x2F;code&gt; we wish to sign a file.
We follow that option with the full name of the signing identity we wish to use.
This is one of the valid signing identities we listed earlier using the &lt;code&gt;security&lt;&#x2F;code&gt; command.
Typically, this will be the common name of the Developer ID certificate you generated in the Apple Developer portal.&lt;&#x2F;p&gt;
&lt;p&gt;The second option, &lt;code&gt;--identifier&lt;&#x2F;code&gt;, is optional but recommended.
By convention, the identifier should be a &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Reverse_domain_name_notation&quot;&gt;reverse-DNS formatted&lt;&#x2F;a&gt; string that uniquely identifies your program.&lt;&#x2F;p&gt;
&lt;p&gt;If you omit the &lt;code&gt;--identifier&lt;&#x2F;code&gt; option, the file&#x27;s name (minus extension) is used as a default identifier value.
Again, the option is not required, but it helps reduce confusion.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, pass the path to the file you want to sign.
After executing the command you will be prompted to provide your keychain password (assuming your signing identity is stored in the login keychain).
This authorizes the &lt;code&gt;codesign&lt;&#x2F;code&gt; utility to access the private key for that certificate stored in your keychain.&lt;&#x2F;p&gt;
&lt;p&gt;The file is now signed!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-is-the-signature-stored&quot;&gt;Where is the signature stored?&lt;&#x2F;h2&gt;
&lt;p&gt;When developing and signing a full app bundle, the resultant &lt;code&gt;.app&lt;&#x2F;code&gt; will contain a &lt;code&gt;MyApp.app&#x2F;Contents&#x2F;_CodeSignature&lt;&#x2F;code&gt; folder containing information about the code signature.&lt;&#x2F;p&gt;
&lt;p&gt;Single files like scripts, however, don&#x27;t have a directory structure.&lt;&#x2F;p&gt;
&lt;p&gt;Instead, the signature is stored in the file&#x27;s extended attributes.
To quote Apple&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;library&#x2F;archive&#x2F;technotes&#x2F;tn2206&#x2F;_index.html&quot;&gt;macOS Code Signing in depth article&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;...code signing uses extended attributes to store signatures in non-Mach-O executables such as script files.
If the extended attributes are lost then the program&#x27;s signature will be broken.
Many file transfer techniques do not preserve extended attributes...&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;You can list a file&#x27;s extended attributes using &lt;code&gt;xattr&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;xattr -l &#x2F;path&#x2F;to&#x2F;file.pdf
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note the &lt;code&gt;com.apple.cs.CodeDirectory&lt;&#x2F;code&gt; and &lt;code&gt;com.apple.cs.CodeRequirements&lt;&#x2F;code&gt; attributes listed in the output.
These store the components of the single file&#x27;s code signature.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;verify-a-code-signature&quot;&gt;Verify a code signature&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;codesign&lt;&#x2F;code&gt; binary can also verify the integrity of a file&#x27;s code signature with the &lt;code&gt;-v&lt;&#x2F;code&gt; or &lt;code&gt;--verify&lt;&#x2F;code&gt; flag.
This tool frustratingly interprets the short &lt;code&gt;-v&lt;&#x2F;code&gt; flag as either &amp;quot;verify&amp;quot; or &amp;quot;verbose&amp;quot; depending on the context of other passed flags.
I stick with the longer form &lt;code&gt;--verify&lt;&#x2F;code&gt; to avoid confusion.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;codesign --verify &#x2F;path&#x2F;to&#x2F;script.zsh
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;No output (and a &lt;code&gt;0&lt;&#x2F;code&gt; return code) means the signature is valid and the file is unaltered since being signed.
If you&#x27;re interested in output, adding a second &lt;code&gt;v&lt;&#x2F;code&gt; flag will provide more detail.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$ &#x2F;usr&#x2F;bin&#x2F;codesign --verify -v &#x2F;path&#x2F;to&#x2F;script.zsh
script.zsh: valid on disk
script.zsh: satisfies its Designated Requirement
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Otherwise, specifics of the problem with a signature will be displayed, and the command returns an error code.&lt;&#x2F;p&gt;
&lt;p&gt;Because &lt;code&gt;codesign&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;verify&lt;&#x2F;code&gt; function returns proper success or failure status codes, it&#x27;s easy to validate a code signature within the context of another shell script.
Here is a small example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;if &#x2F;usr&#x2F;bin&#x2F;codesign -v &amp;quot;&#x2F;path&#x2F;to&#x2F;file.zsh&amp;quot;; then
    echo &amp;quot;Code signature is valid.&amp;quot;
else
    echo &amp;quot;Code signature is invalid!&amp;quot;
fi
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Your configuration management system can run checks like the above to validate the integrity of custom scripts deployed on your endpoints.
If the signature check fails, you know you need to redeploy the script.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;delivery&quot;&gt;Delivery&lt;&#x2F;h2&gt;
&lt;p&gt;Source control systems like Git will drop extended attributes from files when committed.
If you sign a script, then commit it to a Git repository, it will no longer be signed.&lt;&#x2F;p&gt;
&lt;p&gt;Additionally, your configuration management tool may or may not be able to distribute files with extended attributes – and thus code signing – intact.&lt;&#x2F;p&gt;
&lt;p&gt;Because of these limitations, I recommend you package any signed code as a final step before distribution.
Signed scripts &lt;strong&gt;will&lt;&#x2F;strong&gt; retain extended attributes and remain signed when delivered to managed Macs if you package them. &lt;&#x2F;p&gt;
&lt;h2 id=&quot;common-signing-problems&quot;&gt;Common signing problems&lt;&#x2F;h2&gt;
&lt;p&gt;I mentioned you can code sign pretty much any file type.
This includes images, PDFs, text files – almost anything (though in some cases, I&#x27;m not sure why you would want to).&lt;&#x2F;p&gt;
&lt;p&gt;If you try to sign an incompatible file – like a directory – you&#x27;ll get an error message stating &lt;code&gt;bundle format unrecognized, invalid, or unsuitable&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you receive the error &lt;code&gt;resource fork, Finder information, or similar detritus not allowed&lt;&#x2F;code&gt;, this indicates the file has extended attributes that are incompatible with computing a code signature hash.
You may be able to discard these attributes if they are not essential to the file type. For example, the most common incompatible extended attribute is the legacy &amp;quot;Finder Info&amp;quot; stored in the &lt;code&gt;com.apple.FinderInfo&lt;&#x2F;code&gt; attribute. This attribute contains metadata like Finder tags and other information that is unlikely relavent for files mass deployed by an administrator.&lt;&#x2F;p&gt;
&lt;p&gt;Again, list the file&#x27;s extended attributes using &lt;code&gt;xattr&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;xattr -l &#x2F;path&#x2F;to&#x2F;file.pdf
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note the &lt;code&gt;com.apple.FinderInfo&lt;&#x2F;code&gt; attribute in the ouput.&lt;&#x2F;p&gt;
&lt;p&gt;Removing the &amp;quot;Finder Info&amp;quot; attribute is as simple as &lt;code&gt;xattr -d com.apple.FinderInfo &#x2F;path&#x2F;to&#x2F;file.pdf&lt;&#x2F;code&gt;.
Or, remove &lt;em&gt;all&lt;&#x2F;em&gt; extended attributes via &lt;code&gt;xattr -c &#x2F;path&#x2F;to&#x2F;file.pdf&lt;&#x2F;code&gt;.
You should then be able to code sign the file.&lt;&#x2F;p&gt;
&lt;p&gt;But remember – do not strip all extended attributes &lt;em&gt;after&lt;&#x2F;em&gt; signing the file.
That would remove the signature!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further reading&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve covered the basics here, but will close with a few recommended resources for more information on code signing within macOS.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;documentation&#x2F;technotes&#x2F;tn3127-inside-code-signing-requirements&quot;&gt;Apple - TN3127: Inside Code Signing: Requirements&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;library&#x2F;archive&#x2F;documentation&#x2F;Security&#x2F;Conceptual&#x2F;CodeSigningGuide&#x2F;Introduction&#x2F;Introduction.html&quot;&gt;Apple - About Code Signing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;library&#x2F;archive&#x2F;technotes&#x2F;tn2206&#x2F;_index.html&quot;&gt;Apple - TN2206 macOS Code Signing In Depth&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
        </item>
        <item>
            <title>How to examine the network traffic of MDM enrollment during Setup Assistant</title>
            <pubDate>Sat, 28 May 2022 00:00:00 +0000</pubDate>
            <link>https://macblog.org/mdmpackettrace/</link>
            <guid>https://macblog.org/mdmpackettrace/</guid>
            <description>&lt;p&gt;Part of my job is to test (and re-test) first-time setup workflows for new and
repurposed Macs.&lt;&#x2F;p&gt;
&lt;p&gt;I recently needed to analyze the flow of network traffic during initial MDM
enrollment to confirm an on-premise network was permitting all required traffic.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;tcpdump&lt;&#x2F;code&gt; tool – included with macOS – is a powerful utility that allows you
to record all network traffic passing through any interface on the Mac. It
requires elevated privileges to run, however. This presents a problem, since we
do not yet have an account capable of running elevated processes during Setup
Assistant. We haven&#x27;t even created a local account yet!&lt;&#x2F;p&gt;
&lt;p&gt;To work around this, we need to enable the &lt;code&gt;root&lt;&#x2F;code&gt; account &lt;em&gt;before&lt;&#x2F;em&gt; proceeding
through &lt;strong&gt;Setup Assistant&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;&lt;mark&gt;I strongly recommend doing these sorts of analyses on a dedicated test Mac
that you don&#x27;t mind erasing.&lt;&#x2F;mark&gt; Gather the data you need, then erase it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reinstall-macos&quot;&gt;Reinstall macOS&lt;&#x2F;h2&gt;
&lt;p&gt;First, we need to return the Mac to a &amp;quot;fresh&amp;quot; state by reinstalling macOS.&lt;&#x2F;p&gt;
&lt;p&gt;Apple provides &lt;a href=&quot;https:&#x2F;&#x2F;support.apple.com&#x2F;en-us&#x2F;HT204904&quot;&gt;complete instructions on reinstalling the operating system&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re using a Mac with an Apple Silicon chip, you can &lt;em&gt;very&lt;&#x2F;em&gt; quickly
&lt;a href=&quot;https:&#x2F;&#x2F;support.apple.com&#x2F;guide&#x2F;apple-configurator-mac&#x2F;revive-or-restore-a-mac-with-apple-silicon-apdd5f3c75ad&#x2F;mac&quot;&gt;restore the Mac using Apple Configurator&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;enable-root-from-macos-recovery&quot;&gt;Enable &lt;code&gt;root&lt;&#x2F;code&gt; from macOS Recovery&lt;&#x2F;h2&gt;
&lt;p&gt;Next, we need to &lt;em&gt;temporarily&lt;&#x2F;em&gt; enable the &lt;code&gt;root&lt;&#x2F;code&gt; account by setting a
password for it. We&#x27;ll disable it later, but this is &lt;strong&gt;required&lt;&#x2F;strong&gt; to be able to
run privileged processes during Setup Assistant.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Start up the Mac in &lt;a href=&quot;https:&#x2F;&#x2F;support.apple.com&#x2F;guide&#x2F;mac-help&#x2F;intro-to-macos-recovery-mchl46d531d6&#x2F;mac&quot;&gt;Recovery mode&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Once Recovery loads, select &lt;em&gt;Utilities &amp;gt; Terminal&lt;&#x2F;em&gt; on the top menu to open a
Terminal window.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Initiate a password reset for the &lt;code&gt;root&lt;&#x2F;code&gt; account using the following command,
depending on whether the Mac has an Apple Silicon or Intel chip:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;For a Mac with an Apple Silicon chip...&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;dscl -f &#x2F;Volumes&#x2F;Data&#x2F;private&#x2F;var&#x2F;db&#x2F;dslocal&#x2F;nodes&#x2F;Default localhost -passwd &#x2F;Local&#x2F;Default&#x2F;Users&#x2F;root
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;For a Mac with an Intel chip...&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;dscl -f &#x2F;Volumes&#x2F;Macintosh\ HD\ -\ Data&#x2F;private&#x2F;var&#x2F;db&#x2F;dslocal&#x2F;nodes&#x2F;Default localhost -passwd &#x2F;Local&#x2F;Default&#x2F;Users&#x2F;root
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;When prompted to enter a &lt;code&gt;New password:&lt;&#x2F;code&gt;, type in the password you wish to
use with the &lt;code&gt;root&lt;&#x2F;code&gt; account. The value will not be displayed on screen, and
you will &lt;em&gt;not&lt;&#x2F;em&gt; be prompted to confirm it, so use caution.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Restart the Mac by typing &lt;code&gt;reboot&lt;&#x2F;code&gt; then pressing &lt;kbd&gt;Return&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;open-a-terminal-during-setup-assistant&quot;&gt;Open a Terminal during Setup Assistant&lt;&#x2F;h2&gt;
&lt;p&gt;When you start up the Mac, you&#x27;ll see the &amp;quot;hello&amp;quot; screen and Setup Assistant
will begin. Select your language to continue.&lt;&#x2F;p&gt;
&lt;p&gt;Next, press &lt;kbd&gt;⌃ Control&lt;&#x2F;kbd&gt; + &lt;kbd&gt;⌥ Option&lt;&#x2F;kbd&gt; + &lt;kbd&gt;⌘ Command&lt;&#x2F;kbd&gt; +
&lt;kbd&gt;T&lt;&#x2F;kbd&gt; on the keyboard to open a Terminal window.&lt;&#x2F;p&gt;
&lt;p&gt;Terminal will open in the background, and you&#x27;ll be able to switch back and
forth between the Setup Assistant and Terminal windows.&lt;&#x2F;p&gt;
&lt;p&gt;Setup Assistant runs under the temporary &lt;code&gt;_mbsetupuser&lt;&#x2F;code&gt; user account. This is a
standard – rather than administrator – account. Elevate to root by typing &lt;code&gt;su -&lt;&#x2F;code&gt;, then entering the password you previously set for the root account in macOS
Recovery.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;terminal-during-setup-assistant.55778a6853f54fe1.webp&quot;width=&quot;720&quot; height=&quot;449&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Great, now we have a &lt;code&gt;root&lt;&#x2F;code&gt; shell!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;run-tcpdump&quot;&gt;Run &lt;code&gt;tcpdump&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;With a root shell, we can run elevated processes like &lt;code&gt;tcpdump&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Advance through Setup Assistant until you reach the &lt;strong&gt;Remote Management&lt;&#x2F;strong&gt;
screen. Switch focus to the Terminal window, then run:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;tcpdump -nn -i any | tee -a &#x2F;Users&#x2F;Shared&#x2F;enrollment.dump
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will display all traffic for all network interfaces, and will skip reverse
resolution of network addresses to DNS names. I find these options useful to see
where traffic is flowing, and the unresolved IP addresses and port numbers are
the relevant bits of information I&#x27;m after.&lt;&#x2F;p&gt;
&lt;p&gt;I also use the &lt;code&gt;tee&lt;&#x2F;code&gt; program to simultaneously print the traffic to standard
output and also save a log to a known location. Writing the output to a file
within &lt;code&gt;&#x2F;Users&#x2F;Shared&lt;&#x2F;code&gt; ensures the file persists through any reboots and is
accessible once Setup Assistant completes. You could use &lt;code&gt;tcpdump&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;-w&lt;&#x2F;code&gt; flag
to save the output to a file, but this creates a binary file that isn&#x27;t
immediately readable. Using &lt;code&gt;tee&lt;&#x2F;code&gt; is my personal preference.&lt;&#x2F;p&gt;
&lt;p&gt;There are tons of options for &lt;code&gt;tcpdump&lt;&#x2F;code&gt;, which is not the point of this post. I
recommend &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;documentation&#x2F;network&#x2F;recording_a_packet_trace&quot;&gt;Apple&#x27;s developer documentation on recording a packet
trace&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;danielmiessler.com&#x2F;study&#x2F;tcpdump&#x2F;&quot;&gt;Daniel Miessler&#x27;s tcpdump tutorial&lt;&#x2F;a&gt; for
extensive help using the tool.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;clean-up&quot;&gt;Clean up&lt;&#x2F;h2&gt;
&lt;p&gt;Once MDM enrollment completes, switch focus to the Terminal window and press
&lt;kbd&gt;⌘ Command&lt;&#x2F;kbd&gt; + &lt;kbd&gt;C&lt;&#x2F;kbd&gt; to quit the &lt;code&gt;tcmpdump&lt;&#x2F;code&gt; process.&lt;&#x2F;p&gt;
&lt;p&gt;The packet trace is displayed in the Terminal window for you to analyze. If
you&#x27;ve also &lt;code&gt;tee&lt;&#x2F;code&gt;&#x27;d the output to a file, you&#x27;ll be able to copy that
file to another system for analysis after you&#x27;ve completed Setup Assistant.&lt;&#x2F;p&gt;
&lt;p&gt;The only thing left to do is disable &lt;code&gt;root&lt;&#x2F;code&gt; login. Do this from your
administrator-level account by running:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;dscl . -create &#x2F;Users&#x2F;root UserShell &#x2F;usr&#x2F;bin&#x2F;false
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or – since you&#x27;re doing this on a test device – erase the Mac and start over
fresh!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Slides and video for the &#x27;Solving problems with custom AutoPkg processors&#x27; session at the University of Utah Mac Admin Meeting</title>
            <pubDate>Fri, 20 May 2022 00:00:00 +0000</pubDate>
            <link>https://macblog.org/utah-may-2022/</link>
            <guid>https://macblog.org/utah-may-2022/</guid>
            <description>&lt;p&gt;I recently presented at the monthly &lt;a href=&quot;https:&#x2F;&#x2F;apple.lib.utah.edu&#x2F;&quot;&gt;University of Utah Mac Admin Meeting&lt;&#x2F;a&gt;
about two of my custom AutoPkg processors: &lt;a href=&quot;https:&#x2F;&#x2F;macblog.org&#x2F;datetime&quot;&gt;DatetimeOutputter&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;macblog.org&#x2F;icons&quot;&gt;AppIconExtractor&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Here are links to a recording of the presentation and the associated slides:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;stream.lib.utah.edu&#x2F;index.php?c=details&amp;amp;id=13501&quot;&gt;Solving problems with custom AutoPkg processors&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;downloads.lib.utah.edu&#x2F;media_streaming_presentation_documents&#x2F;pdf&#x2F;mac_mgrs&#x2F;20220518_mm&#x2F;2022.05.18_mm_autopkg.pdf&quot;&gt;Slides (PDF)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
        </item>
        <item>
            <title>Output the Date and Time in AutoPkg Recipes</title>
            <pubDate>Tue, 01 Mar 2022 00:00:00 +0000</pubDate>
            <link>https://macblog.org/autopkg-datetime/</link>
            <guid>https://macblog.org/autopkg-datetime/</guid>
            <description>&lt;p&gt;I recently needed to use the date and time of an AutoPkg run from within the
context of recipe.&lt;&#x2F;p&gt;
&lt;p&gt;While AutoPkg itself is aware of the date and time of a run, that information is
not accessible to other processors within the recipe.&lt;&#x2F;p&gt;
&lt;p&gt;To fill this need, I wrote a new AutoPkg processor: &lt;strong&gt;DatetimeOutputter&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;DatetimeOutputter&lt;&#x2F;strong&gt; helps you reference the current date and time as a
variable within your AutoPkg recipes. Additionally, it can calculate future and
past dates to enhance advanced workflows.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;current-date-and-time&quot;&gt;Current date and time&lt;&#x2F;h2&gt;
&lt;p&gt;At its core, &lt;strong&gt;DatetimeOutputter&lt;&#x2F;strong&gt; adds a &lt;code&gt;datetime&lt;&#x2F;code&gt; variable to an AutoPkg
recipe execution. The datetime is outputted in ISO 8601 format relevant to the
local time of the computer running the recipe.&lt;&#x2F;p&gt;
&lt;p&gt;Calling the processor using &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;autopkg&#x2F;wiki&#x2F;Processor-Locations#shared-recipe-processors&quot;&gt;Shared Processor&lt;&#x2F;a&gt; syntax, with no
arguments, invokes this default behavior. Here are examples in both XML and YAML
recipe format.&lt;&#x2F;p&gt;
&lt;p&gt;XML:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Process&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Processor&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.github.haircut.processors&#x2F;DatetimeOutputter&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;YAML:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Process&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;com.github.haircut.processors&#x2F;DatetimeOutputter&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will output a new &lt;code&gt;datetime&lt;&#x2F;code&gt; variable you can use in subsequent processors.
&lt;code&gt;datetime&lt;&#x2F;code&gt; will look something like &lt;code&gt;2022-03-01T09:45:45.544391&lt;&#x2F;code&gt; by default.&lt;&#x2F;p&gt;
&lt;p&gt;You can control the output format by supplying a &lt;code&gt;datetime_format&lt;&#x2F;code&gt; argument. The
processor accepts any &lt;a href=&quot;https:&#x2F;&#x2F;strftime.org&#x2F;&quot;&gt;strftime&lt;&#x2F;a&gt;-compatible format.&lt;&#x2F;p&gt;
&lt;p&gt;Additionally, you can pass the &lt;code&gt;use_utc&lt;&#x2F;code&gt; argument as &lt;code&gt;True&lt;&#x2F;code&gt; to output the
datetime relative to UTC rather than your computer&#x27;s local time.&lt;&#x2F;p&gt;
&lt;p&gt;This example illustrates both concepts:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Process&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;com.github.haircut.processors&#x2F;DatetimeOutputter&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;datetime_format&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%A, %B %e, %Y at %l:%M %p&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;use_utc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-yaml&quot;&gt;True&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This would output something like &lt;code&gt;Tuesday, March 1, 2022 at 1:45 PM&lt;&#x2F;code&gt; based on
UTC time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;past-and-future-dates&quot;&gt;Past and future dates&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s handy to know when a recipe runs, but determining past and future dates –
e.g. one week from now, or 3 days ago – can augment many workflows.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;DatetimeOutputter&lt;&#x2F;strong&gt; can generate an arbitrary number of datetime &amp;quot;deltas.&amp;quot; A
datetime delta adds or subtracts time from the current datetime and outputs a
variable in your preferred format.&lt;&#x2F;p&gt;
&lt;p&gt;Outputting a delta requires specifying a few arguments.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;output_name&lt;&#x2F;code&gt;: the output variable name for the time delta. Whatever you set
here is the variable name you can use in subsequent processors.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;direction&lt;&#x2F;code&gt;: specify whether the generated datetime should be in the &lt;code&gt;future&lt;&#x2F;code&gt;
or &lt;code&gt;past&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;format&lt;&#x2F;code&gt;: the &lt;a href=&quot;https:&#x2F;&#x2F;strftime.org&#x2F;&quot;&gt;strftime&lt;&#x2F;a&gt;-compatible format to output the datetime.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;interval&lt;&#x2F;code&gt;: a dictionary of keys specifying one or more values to add or
subtract from the current datetime. Valid keys are: &lt;code&gt;weeks&lt;&#x2F;code&gt;, &lt;code&gt;days&lt;&#x2F;code&gt;, &lt;code&gt;hours&lt;&#x2F;code&gt;,
&lt;code&gt;minutes&lt;&#x2F;code&gt;, &lt;code&gt;seconds&lt;&#x2F;code&gt;, &lt;code&gt;microseconds&lt;&#x2F;code&gt;, and &lt;code&gt;milliseconds&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The &lt;code&gt;interval&lt;&#x2F;code&gt; argument accepts any number of keyword arguments compatible with
&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;datetime.html#timedelta-objects&quot;&gt;Python&#x27;s timedelta object&lt;&#x2F;a&gt;, as listed above. This means you may need
to convert far-future or past intervals to &amp;quot;weeks&amp;quot; or &amp;quot;days;&amp;quot; e.g. instead of
specifying &lt;code&gt;months: 2&lt;&#x2F;code&gt;, use &lt;code&gt;weeks: 8&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s an example of outputting two deltas:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;com.github.haircut.processors&#x2F;DatetimeOutputter&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;deltas&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;output_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;one_week_in_future&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;direction&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;future&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;datetime_format&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%Y-%m-%d 00:00:00&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;interval&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;weeks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;1&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;output_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;two_days_six_hours_twelve_minutes_ago&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;direction&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;past&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;datetime_format&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%A, %B %e, at %Y %H:%M:%S&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;interval&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;days&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;2&lt;&#x2F;span&gt;
          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;hours&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;6&lt;&#x2F;span&gt;
          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;minutes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;12&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This would output two new variables as follows:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;one_week_in_future&lt;&#x2F;code&gt; with the value &lt;code&gt;2022-03-08 00:00:00&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;two_days_six_hours_twelve_minutes_ago&lt;&#x2F;code&gt; with the value &lt;code&gt;Sunday, February 27, 2022 at 03:33:45&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You can output as many deltas as you need by simply adding new dictionaries to
the &lt;code&gt;deltas&lt;&#x2F;code&gt; array of the processor. Each will be available for use by later
processors via variable substitution.&lt;&#x2F;p&gt;
&lt;p&gt;Deltas always respect the &lt;code&gt;use_utc&lt;&#x2F;code&gt; option of the processor, if set. In a single
run of &lt;strong&gt;DatetimeOutputter&lt;&#x2F;strong&gt; you cannot output UTC- and non-UTC-based datetimes.
If you have a need for this, run &lt;strong&gt;DatetimeOutputter&lt;&#x2F;strong&gt; multiple times in your
recipe, setting &lt;code&gt;use_utc&lt;&#x2F;code&gt; accordingly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;example-use-cases&quot;&gt;Example use cases&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;keep-it-simple-with-just-the-date-and-time&quot;&gt;Keep it simple with just the date and time&lt;&#x2F;h3&gt;
&lt;p&gt;In the simplest use case, you might wish to note the date a package was uploaded
by &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;grahampugh&#x2F;jamf-upload&#x2F;wiki&#x2F;JamfUploader-AutoPkg-Processors&quot;&gt;JamfUploader&lt;&#x2F;a&gt; within the Jamf Pro package notes field. Call
&lt;strong&gt;DatetimeOutputter&lt;&#x2F;strong&gt; first to generate the &lt;code&gt;datetime&lt;&#x2F;code&gt; variable, then reference
that variable as &lt;code&gt;%datetime%&lt;&#x2F;code&gt; in the next processor like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Process&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;com.github.haircut.processors&#x2F;DatetimeOutputter&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;com.github.grahampugh.jamf-upload.processors&#x2F;JamfPackageUploader&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;pkg_notes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Uploaded via AutoPkg %datetime%&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;output-a-future-datetime-for-use-with-munki-s-force-install-after-date-feature&quot;&gt;Output a future datetime for use with Munki&#x27;s &amp;quot;force install after date&amp;quot; feature&lt;&#x2F;h3&gt;
&lt;p&gt;Munki includes a feature to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;munki&#x2F;munki&#x2F;wiki&#x2F;Pkginfo-Files#force-install-after-date&quot;&gt;force installation of a package after a specified
date&lt;&#x2F;a&gt;. Setting the &lt;code&gt;force_install_after_date&lt;&#x2F;code&gt; key in a package&#x27;s &lt;code&gt;pkginfo&lt;&#x2F;code&gt;
dictionary will cause client Macs to forcefully logout or restart to install the
software after that (local) date and time.&lt;&#x2F;p&gt;
&lt;p&gt;If you use this functionality, Munki recommends setting the
&lt;code&gt;force_install_after_date&lt;&#x2F;code&gt; to at least 2 weeks in the future.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;DatetimeOutputter&lt;&#x2F;strong&gt; can help you generate this future date in the required
format:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;com.github.haircut.processors&#x2F;DatetimeOutputter&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;format&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%Y-%m-%dT%H:%M:%SZ&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;deltas&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;output_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;force_after&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;direction&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;future&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;interval&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;weeks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;2&lt;&#x2F;span&gt;

&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;MunkiImporter&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;MUNKI_REPO&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&amp;lt;path to Munki repo&amp;gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;pkg_path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%pkg%&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;pkginfo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;force_install_after_date&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%force_after%&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will automate the calculation of a two-week window after uploading the
package during which users will be prompted – but not forced – to install the
package. After &lt;code&gt;force_date&lt;&#x2F;code&gt; passes, users will be forced to install the
software.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;output-a-future-date-for-use-with-a-jamf-pro-policy-activation-date&quot;&gt;Output a future date for use with a Jamf Pro policy activation date&lt;&#x2F;h3&gt;
&lt;p&gt;You might wish to delay the installation of an application update for some
number of days after release. One way to do this is to configure a Jamf Pro
policy to include the &amp;quot;Activation Date&#x2F;Time&amp;quot; server-side limitation. This
prevents the policy from running before the configured date and time.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;DatetimeOutputter&lt;&#x2F;strong&gt; can generate a dynamic datetime stamp &lt;em&gt;n&lt;&#x2F;em&gt; number of days
in the future. This means the new version of an application will be uploaded to
your Jamf Pro server, and the installation policy ready to go when the
Activation Date&#x2F;Time rolls around. Automatically!&lt;&#x2F;p&gt;
&lt;p&gt;First, we add an &lt;code&gt;activation_date&lt;&#x2F;code&gt; key to the &lt;code&gt;date_time_limitations&lt;&#x2F;code&gt; of a
policy template. We populate the key with an &lt;code&gt;%activation_date%&lt;&#x2F;code&gt; substitution
variable we will later define within the associated AutoPkg recipe.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Install-after-1-week.xml&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-preprocessor z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-xml&quot;&gt;xml&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;encoding&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;UTF-8&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;?&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;policy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;general&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Install %NAME% 1 Week After Release&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;enabled&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;true&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;enabled&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;trigger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;CHECKIN&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;trigger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;trigger_checkin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;true&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;trigger_checkin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;frequency&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Once per computer&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;frequency&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;date_time_limitations&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;activation_date&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%activation_date%&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;activation_date&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;date_time_limitations&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;general&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;scope&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;all_computers&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;false&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;all_computers&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;computer_groups&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;computer_group&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%UPDATE_GROUP_NAME%&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;computer_group&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;computer_groups&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;scope&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;self_service&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;use_for_self_service&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;false&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;use_for_self_service&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;self_service&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;package_configuration&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;packages&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;size&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;1&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;size&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;package&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%pkg_name%&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;action&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;install&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;action&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;package&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;packages&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;package_configuration&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;policy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, we&#x27;ll use &lt;strong&gt;DatetimeOutputter&lt;&#x2F;strong&gt; to generate a datestamp 1 week in
the future from the time of the AutoPkg run, in the format Jamf Pro expects for
midnight on that date. We set the &lt;code&gt;output_name&lt;&#x2F;code&gt; to &lt;code&gt;activation_date&lt;&#x2F;code&gt; to match
what the policy template expects.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;StopProcessingIf&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;predicate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;pkg_uploaded == False&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;com.github.haircut.processors&#x2F;DatetimeOutputter&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;deltas&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;output_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;activation_date&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;direction&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;future&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;datetime_format&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%Y-%m-%d 00:00:00&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;interval&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;weeks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;1&lt;&#x2F;span&gt;

&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;com.github.grahampugh.jamf-upload.processors&#x2F;JamfPolicyUploader&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;policy_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Install %NAME% 1 Week After Release&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;policy_template&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Install-after-1-week.xml&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will create a policy that installs the uploaded package, but remains
inactive until 1 week in the future. At that future date, the policy will
automatically activate and install on eligible Macs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;more-info&quot;&gt;More info&lt;&#x2F;h2&gt;
&lt;p&gt;These are just a few of the potential use cases for this processor. Please check
the full details in the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;haircut-recipes&#x2F;blob&#x2F;master&#x2F;Processors&#x2F;README.md&quot;&gt;README&lt;&#x2F;a&gt;. And as always – pull requests are open
if you have an improvement or correction!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Dynamically Add Dock Items with the Jamf Binary</title>
            <pubDate>Sun, 13 Feb 2022 00:00:00 +0000</pubDate>
            <link>https://macblog.org/jamf-binary-dock/</link>
            <guid>https://macblog.org/jamf-binary-dock/</guid>
            <description>&lt;p&gt;Adding your organization&#x27;s common tools or newly-installed items to a user&#x27;s
Dock can minimize confusion for your colleagues, and is a common task for Mac
admins.&lt;&#x2F;p&gt;
&lt;p&gt;For those managing their fleet with Jamf Pro, the &lt;code&gt;jamf&lt;&#x2F;code&gt; binary includes a
&lt;code&gt;modifyDock&lt;&#x2F;code&gt; command which allows you to apply certain Dock modifications. It
isn&#x27;t a fully-featured Dock management tool, but it does include enough
functionality to add new items to a user&#x27;s Dock.&lt;&#x2F;p&gt;
&lt;p&gt;I was recently working on a project where I needed to conditionally add a Dock
item based on some scripted logic. I wanted to minimize external dependencies,
so I developed a method to leverage the &lt;code&gt;jamf&lt;&#x2F;code&gt; binary&#x27;s built-in Dock management
capability and its &lt;code&gt;-file&lt;&#x2F;code&gt; flag to complete the task.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;First, here&#x27;s the documentation for the &lt;code&gt;modifyDock&lt;&#x2F;code&gt; command, which you can read
by running &lt;code&gt;sudo jamf help modifyDock&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; class=&quot;language-text z-code&quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Usage:  jamf modifyDock -file &amp;lt;file name&amp;gt; [-leaveRunning] [-beginning] [-remove]
Usage:  jamf modifyDock -id &amp;lt;dock_item_id&amp;gt; [-leaveRunning] [-beginning] [-remove]

  -file          The file that contains the formatted dock items.
  -id            The dock_item_id of the dock item on the JSS.
  -leaveRunning  The Dock process will not be restarted.
  -beginning     The item will be placed at the beginning (left side) of the Dock.
  -remove        The item will be removed instead of added.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Typical use of this command assumes use of the &lt;code&gt;-id&lt;&#x2F;code&gt; flag, which requires
passing the ID of a &amp;quot;Dock Item&amp;quot; as configured within your Jamf Pro instance.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.jamf.com&#x2F;jamf-pro&#x2F;documentation&#x2F;Dock_Items.html&quot;&gt;Dock Items can be added to Jamf Pro&lt;&#x2F;a&gt; via the web console or by
using Jamf Admin. Once you&#x27;ve added a Dock Item to Jamf Pro, you can add it to a
Mac&#x27;s dock by using the Dock Items payload within a Policy, or by calling &lt;code&gt;sudo jamf modifyDock -id &amp;lt;Dock Item ID&amp;gt;&lt;&#x2F;code&gt; on the Mac itself.&lt;&#x2F;p&gt;
&lt;p&gt;However, the &lt;code&gt;jamf&lt;&#x2F;code&gt; binary&#x27;s &lt;code&gt;modifyDock&lt;&#x2F;code&gt; command also accepts a &lt;code&gt;-file&lt;&#x2F;code&gt; flag.
The built-in help states the flag expects &lt;code&gt;The file that contains the formatted dock items.&lt;&#x2F;code&gt; – a little vague. Online searches didn&#x27;t turn up much additional
information, and the official Jamf Pro documentation doesn&#x27;t cover the binary in
great detail.&lt;&#x2F;p&gt;
&lt;p&gt;With some experimentation, I found that the &lt;code&gt;-file&lt;&#x2F;code&gt; flag expects an on-disk
path to a file that contains XML representing one or more Dock item entries.&lt;&#x2F;p&gt;
&lt;p&gt;Roughly, the required format of that XML to add an app to the Dock is as
follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;GUID&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;-91117049&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;tile-data&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;file-data&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;_CFURLString&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;file:&#x2F;&#x2F;[path to app]&#x2F;&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;_CFURLStringType&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;15&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;file-label&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;[item name]&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;tile-type&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;file-tile&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Note: The GUID key can be any value, but Jamf Pro uses a consistent value across
all instances, to my knowledge.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s easy enough to generate the required data on-the-fly within a shell
script, so I wrote a function to do just that.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-shell&quot;&gt;dockitem&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-braces z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-keyword z-control z-conditional z-if z-shell&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-double-brace z-begin z-shell&quot;&gt;[[&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;-&lt;&#x2F;span&gt;d&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-shell&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-substring z-begin z-shell&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-shell&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-shell&quot;&gt;4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-shell&quot;&gt;!=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;.app&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-double-brace z-end z-shell&quot;&gt;]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-then z-shell&quot;&gt;then&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;TYPE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;directory&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-else z-shell&quot;&gt;else&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;TYPE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;file&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-end z-shell&quot;&gt;fi&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;TMPFILE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;mktemp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-echo z-shell&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&amp;lt;dict&amp;gt;&amp;lt;key&amp;gt;GUID&amp;lt;&#x2F;key&amp;gt;&amp;lt;integer&amp;gt;-91117049&amp;lt;&#x2F;integer&amp;gt;&amp;lt;key&amp;gt;tile-data&amp;lt;&#x2F;key&amp;gt;&amp;lt;dict&amp;gt;&amp;lt;key&amp;gt;file-data&amp;lt;&#x2F;key&amp;gt;&amp;lt;dict&amp;gt;&amp;lt;key&amp;gt;_CFURLString&amp;lt;&#x2F;key&amp;gt;&amp;lt;string&amp;gt;file:&#x2F;&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;1&lt;span class=&quot;z-keyword z-operator z-expansion z-shell&quot;&gt;%%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;&amp;lt;&#x2F;string&amp;gt;&amp;lt;key&amp;gt;_CFURLStringType&amp;lt;&#x2F;key&amp;gt;&amp;lt;integer&amp;gt;15&amp;lt;&#x2F;integer&amp;gt;&amp;lt;&#x2F;dict&amp;gt;&amp;lt;key&amp;gt;file-label&amp;lt;&#x2F;key&amp;gt;&amp;lt;string&amp;gt;&lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;basename&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&amp;lt;&#x2F;string&amp;gt;&amp;lt;&#x2F;dict&amp;gt;&amp;lt;key&amp;gt;tile-type&amp;lt;&#x2F;key&amp;gt;&amp;lt;string&amp;gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;TYPE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;-tile&amp;lt;&#x2F;string&amp;gt;&amp;lt;&#x2F;dict&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;TMPFILE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-echo z-shell&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;TMPFILE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-punctuation z-section z-braces z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This function requires a single argument: the path to the item you want to add
to the Dock.&lt;&#x2F;p&gt;
&lt;p&gt;Stepping through the function, we first determine if the passed path is a
directory that exists on the Mac. If so – and that directory is not actually an
app bundle – the Dock item will be created as a &amp;quot;directory tile,&amp;quot; which appears
with a folder icon on the Dock. Otherwise, we assume the path is an app or
individual file.&lt;&#x2F;p&gt;
&lt;p&gt;Next, we generate a temporary file on disk to which we can write the XML
representing the new Dock item. The temporary file&#x27;s path is captured.&lt;&#x2F;p&gt;
&lt;p&gt;Then we populate a blob of XML with our custom values, and finally print out the
path to the that temporary file.&lt;&#x2F;p&gt;
&lt;p&gt;Using the function is as simple as calling &lt;code&gt;dockitem&lt;&#x2F;code&gt; within a script, then
passing a path as an argument.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;dockitem&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;Applications&#x2F;Safari.app&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Putting it all together, we can then feed that file to the &lt;code&gt;jamf&lt;&#x2F;code&gt; binary&#x27;s
&lt;code&gt;modifyDock&lt;&#x2F;code&gt; command using command substitution like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;!&#x2F;bin&#x2F;zsh&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-shell&quot;&gt;dockitem&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-braces z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-keyword z-control z-conditional z-if z-shell&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-double-brace z-begin z-shell&quot;&gt;[[&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;-&lt;&#x2F;span&gt;d&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-shell&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-substring z-begin z-shell&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-shell&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-shell&quot;&gt;4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-shell&quot;&gt;!=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;.app&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-double-brace z-end z-shell&quot;&gt;]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-then z-shell&quot;&gt;then&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;TYPE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;directory&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-else z-shell&quot;&gt;else&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;TYPE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;file&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-end z-shell&quot;&gt;fi&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;TMPFILE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;mktemp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-echo z-shell&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&amp;lt;dict&amp;gt;&amp;lt;key&amp;gt;GUID&amp;lt;&#x2F;key&amp;gt;&amp;lt;integer&amp;gt;-91117049&amp;lt;&#x2F;integer&amp;gt;&amp;lt;key&amp;gt;tile-data&amp;lt;&#x2F;key&amp;gt;&amp;lt;dict&amp;gt;&amp;lt;key&amp;gt;file-data&amp;lt;&#x2F;key&amp;gt;&amp;lt;dict&amp;gt;&amp;lt;key&amp;gt;_CFURLString&amp;lt;&#x2F;key&amp;gt;&amp;lt;string&amp;gt;file:&#x2F;&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;1&lt;span class=&quot;z-keyword z-operator z-expansion z-shell&quot;&gt;%%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;&amp;lt;&#x2F;string&amp;gt;&amp;lt;key&amp;gt;_CFURLStringType&amp;lt;&#x2F;key&amp;gt;&amp;lt;integer&amp;gt;15&amp;lt;&#x2F;integer&amp;gt;&amp;lt;&#x2F;dict&amp;gt;&amp;lt;key&amp;gt;file-label&amp;lt;&#x2F;key&amp;gt;&amp;lt;string&amp;gt;&lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;basename&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&amp;lt;&#x2F;string&amp;gt;&amp;lt;&#x2F;dict&amp;gt;&amp;lt;key&amp;gt;tile-type&amp;lt;&#x2F;key&amp;gt;&amp;lt;string&amp;gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;TYPE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;-tile&amp;lt;&#x2F;string&amp;gt;&amp;lt;&#x2F;dict&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;TMPFILE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-echo z-shell&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;TMPFILE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-punctuation z-section z-braces z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;jamf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; modifyDock&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;leaveRunning&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;file&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;dockitem&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;Applications&#x2F;Safari.app&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;jamf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; modifyDock&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;leaveRunning&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;file&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;dockitem&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;Applications&#x2F;BBEdit.app&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;jamf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; modifyDock&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;file&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;dockitem&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;Applications&#x2F;Slack.app&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For another example, let&#x27;s determine the logged-in user&#x27;s home directory and add
that to the Dock as a directory tile.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;!&#x2F;bin&#x2F;zsh&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-shell&quot;&gt;dockitem&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-braces z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-keyword z-control z-conditional z-if z-shell&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-double-brace z-begin z-shell&quot;&gt;[[&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;-&lt;&#x2F;span&gt;d&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-shell&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-substring z-begin z-shell&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-shell&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-shell&quot;&gt;4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-shell&quot;&gt;!=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;.app&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-double-brace z-end z-shell&quot;&gt;]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-then z-shell&quot;&gt;then&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;TYPE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;directory&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-else z-shell&quot;&gt;else&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;TYPE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;file&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-end z-shell&quot;&gt;fi&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;TMPFILE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;mktemp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-echo z-shell&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&amp;lt;dict&amp;gt;&amp;lt;key&amp;gt;GUID&amp;lt;&#x2F;key&amp;gt;&amp;lt;integer&amp;gt;-91117049&amp;lt;&#x2F;integer&amp;gt;&amp;lt;key&amp;gt;tile-data&amp;lt;&#x2F;key&amp;gt;&amp;lt;dict&amp;gt;&amp;lt;key&amp;gt;file-data&amp;lt;&#x2F;key&amp;gt;&amp;lt;dict&amp;gt;&amp;lt;key&amp;gt;_CFURLString&amp;lt;&#x2F;key&amp;gt;&amp;lt;string&amp;gt;file:&#x2F;&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;1&lt;span class=&quot;z-keyword z-operator z-expansion z-shell&quot;&gt;%%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;&amp;lt;&#x2F;string&amp;gt;&amp;lt;key&amp;gt;_CFURLStringType&amp;lt;&#x2F;key&amp;gt;&amp;lt;integer&amp;gt;15&amp;lt;&#x2F;integer&amp;gt;&amp;lt;&#x2F;dict&amp;gt;&amp;lt;key&amp;gt;file-label&amp;lt;&#x2F;key&amp;gt;&amp;lt;string&amp;gt;&lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;basename&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&amp;lt;&#x2F;string&amp;gt;&amp;lt;&#x2F;dict&amp;gt;&amp;lt;key&amp;gt;tile-type&amp;lt;&#x2F;key&amp;gt;&amp;lt;string&amp;gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;TYPE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;-tile&amp;lt;&#x2F;string&amp;gt;&amp;lt;&#x2F;dict&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;TMPFILE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-echo z-shell&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;TMPFILE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-punctuation z-section z-braces z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;CURRENTUSER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;&#x2F;usr&#x2F;sbin&#x2F;scutil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-keyword z-operator z-herestring z-shell&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;show State:&#x2F;Users&#x2F;ConsoleUser&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-pipe z-shell&quot;&gt;|&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;awk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&#x2F;Name :&#x2F; &amp;amp;&amp;amp; ! &#x2F;loginwindow&#x2F; { print $3 }&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;HOMEDIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;dscl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; . read &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;Users&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;CURRENTUSER&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; NFSHomeDirectory &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;jamf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; modifyDock&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;file&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;dockitem&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;HOMEDIR&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This script will read the &lt;code&gt;NFSHomeDirectory&lt;&#x2F;code&gt; attribute of the
currently-logged-in user&#x27;s account and add it to the Dock. Dynamically
determining the user&#x27;s home directory path is not otherwise possible with a Jamf
Pro policy alone, so this method bridges that gap.&lt;&#x2F;p&gt;
&lt;p&gt;Ultimately, you can probably file this method under &amp;quot;things you should probably
do a better way, but this is also kind of neat and you may find a use.&amp;quot;&lt;&#x2F;p&gt;
&lt;p&gt;A purpose-built tool like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;homebysix&#x2F;docklib&#x2F;&quot;&gt;docklib&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kcrawford&#x2F;dockutil&quot;&gt;dockutil&lt;&#x2F;a&gt; will offer
wildly more flexibility and control over the Dock.&lt;&#x2F;p&gt;
&lt;p&gt;But... this will work in a pinch for simple needs.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Automatically Export and Generate App Icons in AutoPkg Recipes</title>
            <pubDate>Mon, 31 Jan 2022 00:00:00 +0000</pubDate>
            <link>https://macblog.org/autopkg-icons/</link>
            <guid>https://macblog.org/autopkg-icons/</guid>
            <description>&lt;p&gt;I&#x27;m a stickler for including icons for all policies available in Jamf Pro&#x27;s Self
Service app. They help users find items in Self Service, and generally make the
app easier to use.&lt;&#x2F;p&gt;
&lt;p&gt;However, I don&#x27;t like manually extracting icons from apps. It&#x27;s easy enough with
a tool like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;SAP&#x2F;macos-icon-generator&quot;&gt;SAP&#x27;s Icons app&lt;&#x2F;a&gt;, but if I&#x27;m automating package and
policy creation with AutoPkg, I should similarly be able to automate icon
creation, right?&lt;&#x2F;p&gt;
&lt;p&gt;I created the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;haircut-recipes&#x2F;blob&#x2F;master&#x2F;Processors&#x2F;AppIconExtractor.py&quot;&gt;&lt;strong&gt;AppIconExtractor&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; AutoPkg processor to fully automate
this task.&lt;&#x2F;p&gt;
&lt;p&gt;At it&#x27;s core, &lt;strong&gt;AppIconExtractor&lt;&#x2F;strong&gt; examines an app and exports its icon as a PNG
image file.&lt;&#x2F;p&gt;
&lt;p&gt;More technically, it reads the &lt;code&gt;CFBundleIconFile&lt;&#x2F;code&gt; property from an app&#x27;s
&lt;code&gt;Info.plist&lt;&#x2F;code&gt; and saves that image as a PNG file at the path of your choice.&lt;&#x2F;p&gt;
&lt;p&gt;Additionally, &lt;code&gt;ApplIconExtractor&lt;&#x2F;code&gt; can create icon variations by compositing a
secondary image on top of the app&#x27;s icon. This makes it simple to automatically
create a version of an icon with a destructive &amp;quot;red X&amp;quot; icon superimposed over
the app icon for use in uninstallation policies, or a version with an &amp;quot;update&amp;quot;
graphic for use in policies that update an app.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;all-icons.9697d1810d061335.webp&quot;alt=&quot;Examples of the unmodified app icon, &amp;#x27;install&amp;#x27;, &amp;#x27;update&amp;#x27;, and &amp;#x27;uninstall&amp;#x27; composited icons.&quot;width=&quot;720&quot; height=&quot;245&quot;&gt;&lt;&#x2F;figure&gt;&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;add-my-recipes-and-install-the-pillow-library&quot;&gt;Add my recipes and install the Pillow library&lt;&#x2F;h2&gt;
&lt;p&gt;First, you&#x27;ll need my recipe repository available to your local AutoPkg
installation. Add it with &lt;code&gt;autopkg repo-add haircut-recipes&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;AppIconExtractor&lt;&#x2F;strong&gt; requires installation of the &lt;a href=&quot;https:&#x2F;&#x2F;python-pillow.org&#x2F;&quot;&gt;Pillow&lt;&#x2F;a&gt; Python
library.&lt;&#x2F;p&gt;
&lt;p&gt;Pillow is used to convert and composite icons, and can be easily installed on 
the Mac you use to run AutoPkg. Use this command:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;usr&#x2F;local&#x2F;autopkg&#x2F;python -m pip install --upgrade Pillow
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that this installs the Pillow library &lt;em&gt;within the path of AutoPkg&#x27;s Python
framework&lt;&#x2F;em&gt;. &lt;strong&gt;This is very important.&lt;&#x2F;strong&gt; If you just run &lt;code&gt;pip&lt;&#x2F;code&gt; or &lt;code&gt;pip3&lt;&#x2F;code&gt; without
the explicit path to AutoPkg&#x27;s Python installation, AutoPkg won&#x27;t be able to
find the library. Recipes will produce an error directing you to install Pillow
using the specifc command above.&lt;&#x2F;p&gt;
&lt;aside&gt;
    &lt;p&gt;The &lt;a
href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;autopkg&#x2F;wiki&#x2F;Processor-MunkiImporter&quot;&gt;MunkiImporter
processor&lt;&#x2F;a&gt;, via munkilib, includes code to extract and convert icons from app
bundles. We could use features of this existing processor to accomplish some of
our needs. However, MunkiImporter does not provide any features to composite
images. Since &lt;strong&gt;AppIconExtractor&lt;&#x2F;strong&gt; is primarily targeted towards
folks managing Macs with tools other than Munki, it makes more sense to require
only a single external dependency – Pillow – that fulfills all our needs.&lt;&#x2F;p&gt;

&lt;&#x2F;aside&gt;
&lt;p&gt;With Pillow installed, you&#x27;re ready to go.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;basic-use&quot;&gt;Basic use&lt;&#x2F;h2&gt;
&lt;p&gt;Using &lt;strong&gt;AppIconExtractor&lt;&#x2F;strong&gt; is as simple as including the processor as a step in a
recipe&#x27;s Process dictionary. Use the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;autopkg&#x2F;wiki&#x2F;Processor-Locations#shared-recipe-processors&quot;&gt;shared processor&lt;&#x2F;a&gt; syntax
to call &lt;code&gt;com.github.haircut.processors&#x2F;AppIconExtractor&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It requires only one argument: &lt;code&gt;source_app&lt;&#x2F;code&gt;, which is the path to the &lt;code&gt;.app&lt;&#x2F;code&gt;
from which to extract an icon. If the path to the app points inside a disk
image, that .dmg will be mounted automatically.&lt;&#x2F;p&gt;
&lt;p&gt;By default, the app&#x27;s icon will be output to the recipe&#x27;s cache directory as
&lt;code&gt;%NAME%.png%&lt;&#x2F;code&gt;. You can optionally override this output path (and filename) by
setting the &lt;code&gt;icon_output_path&lt;&#x2F;code&gt; argument.&lt;&#x2F;p&gt;
&lt;p&gt;A simple example in XML format might look like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Process&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Processor&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.github.haircut.processors&#x2F;AppIconExtractor&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Arguments&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;source_app&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;CoolApp&#x2F;CoolApp.app&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will extract the icon from &amp;quot;CoolApp.app&amp;quot; and save it as a 256px square PNG
image to the recipe cache directory.&lt;&#x2F;p&gt;
&lt;p&gt;As mentioned, adding the &lt;code&gt;icon_output_path&lt;&#x2F;code&gt; argument will give you additional
control over the output path and filename. Here&#x27;s an example in YAML format:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Process&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;com.github.haircut.processors&#x2F;AppIconExtractor&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;source_app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;CoolApp&#x2F;CoolApp.app&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;icon_output_path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;Icons&#x2F;Icon-%NAME%.png&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;generating-composited-variations&quot;&gt;Generating composited variations&lt;&#x2F;h2&gt;
&lt;p&gt;Beyond extracting the app&#x27;s icon, &lt;strong&gt;AppIconExtractor&lt;&#x2F;strong&gt; can also create variation
images by compositing a &amp;quot;template image&amp;quot; on top of the app icon.&lt;&#x2F;p&gt;
&lt;p&gt;The processor can output variations for an &amp;quot;uninstall,&amp;quot; &amp;quot;update,&amp;quot; and &amp;quot;install&amp;quot;
version of the app icon.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;example-composited-icons.1354ec2d4ddba6a3.webp&quot;alt=&quot;Examples of &amp;#x27;install&amp;#x27;, &amp;#x27;update&amp;#x27;, and &amp;#x27;uninstall&amp;#x27; composited icons.&quot;width=&quot;720&quot; height=&quot;245&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;To generate a variation, add a processor argument to set an output path for that
variation. Use one or more of the following arguments:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;composite_install_path&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;composite_update_path&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;composite_uninstall_path&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Omit any variations you don&#x27;t want to generate. The processor will only create
the variations you request be specify an output path.&lt;&#x2F;p&gt;
&lt;p&gt;If you specify only output paths for variations, &lt;strong&gt;AppIconExtractor&lt;&#x2F;strong&gt; will use
sensible defaults to composite suitable icons. The default templates are glyphs
from &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;sf-symbols&#x2F;&quot;&gt;SF Symbols&lt;&#x2F;a&gt; that will work well in most situations. Each
template is 64px in size, and looks nice in the corner.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;default-template-icons.6ca9070ab9e182cb.webp&quot;alt=&quot;Default template icons for &amp;#x27;install&amp;#x27;, &amp;#x27;update&amp;#x27;, and &amp;#x27;uninstall&amp;#x27; variations.&quot;width=&quot;720&quot; height=&quot;245&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;These templates are encoded within the processor; &lt;mark&gt;you don&#x27;t need to do
anything to use these defaults!&lt;&#x2F;mark&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s an example in YAML format:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Process&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;com.github.haircut.processors&#x2F;AppIconExtractor&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;source_app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;CoolApp&#x2F;CoolApp.app&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;icon_output_path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;Icons&#x2F;Icon-%NAME%.png&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;composite_update_path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;Icons&#x2F;Update-%NAME%.png&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;composite_uninstall_path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;RECIPE_CACHE_DIR%&#x2F;Icons&#x2F;Uninstall-%NAME%.png&amp;quot;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice that we included arguments for the &amp;quot;update&amp;quot; and &amp;quot;uninstall&amp;quot; variations,
but did not set the &lt;code&gt;composite_install_path&lt;&#x2F;code&gt; argument. This would output the
&amp;quot;bare&amp;quot; app icon as well as variations for &amp;quot;update&amp;quot; and &amp;quot;uninstall&amp;quot; – but no
&amp;quot;install&amp;quot; variation, since we omitted that argument.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;custom-templates&quot;&gt;Custom templates&lt;&#x2F;h3&gt;
&lt;p&gt;If you don&#x27;t like the default variation templates, you can use your own by
setting &lt;code&gt;composite_install_template&lt;&#x2F;code&gt;, &lt;code&gt;composite_update_template&lt;&#x2F;code&gt; and&#x2F;or
&lt;code&gt;composite_unsinstall_template&lt;&#x2F;code&gt;. Each argument should be the path to alternative
template image to use for that variation.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;AppIconExtractor&lt;&#x2F;strong&gt; will calculate the size of the template image at the path you
specify and correctly anchor that template to the &lt;code&gt;composite_position&lt;&#x2F;code&gt; (see
&amp;quot;Padding and position&amp;quot; below).&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;example-custom-template.4d23aedbf67233f8.webp&quot;alt=&quot;An example of using a custom template image.&quot;width=&quot;720&quot; height=&quot;245&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Here&#x27;s an example of using a custom template to generate an &amp;quot;uninstall&amp;quot;
variation in XML format:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Process&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Processor&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.github.haircut.processors&#x2F;AppIconExtractor&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Arguments&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;source_app&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;CoolApp&#x2F;CoolApp.app&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;composite_uninstall_template&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%RECIPE_DIR%&#x2F;radical-flame.png&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;composite_uninstall_path&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;delete_%NAME%.png&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;padding-and-position&quot;&gt;Padding and position&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;AppIconExtractor&lt;&#x2F;strong&gt; includes a few additional options to customize your
composited icon variations.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;composite_padding&lt;&#x2F;code&gt;: sets the number of pixels from the edge of the image the
superimposed template image is offset. Defaults to &lt;code&gt;10&lt;&#x2F;code&gt; pixels.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;composite_position&lt;&#x2F;code&gt;: sets the corner to which the superimposed template image
for composited variations is anchored. Defaults to &lt;code&gt;br&lt;&#x2F;code&gt; for the bottom-right
corner. You can change this to &lt;code&gt;bl&lt;&#x2F;code&gt; (bottom left), &lt;code&gt;ur&lt;&#x2F;code&gt; (upper right), or ul
(upper left) if you prefer.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Combinations of these options are shown below with the padding highlighted in
pink:&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;padding-and-position.923b044e40c8580d.webp&quot;alt=&quot;Examples of using the composite_padding and composite_position arguments.&quot;width=&quot;720&quot; height=&quot;491&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Clockwise from the upper left, this example shows:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;composite_padding&lt;&#x2F;code&gt; omitted (so it defaults to &lt;code&gt;10&lt;&#x2F;code&gt;) and &lt;code&gt;composite_position&lt;&#x2F;code&gt; of &lt;code&gt;ul&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;composite_padding&lt;&#x2F;code&gt; of &lt;code&gt;20&lt;&#x2F;code&gt; and &lt;code&gt;composite_position&lt;&#x2F;code&gt; of &lt;code&gt;ur&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;composite_padding&lt;&#x2F;code&gt; of &lt;code&gt;0&lt;&#x2F;code&gt; and &lt;code&gt;composite_position&lt;&#x2F;code&gt; omitted (so it defaults to &lt;code&gt;br&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;composite_padding&lt;&#x2F;code&gt; of &lt;code&gt;5&lt;&#x2F;code&gt; and &lt;code&gt;composite_position&lt;&#x2F;code&gt; of &lt;code&gt;bl&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Setting these options applies the same settings to &lt;em&gt;all&lt;&#x2F;em&gt; composited variations.
This is an intentional design choice to keep the input arguments – and thus the
required code – more manageable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;output-variables&quot;&gt;Output variables&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;AppIconExtractor&lt;&#x2F;strong&gt; sets the path(s) to the extracted app icon, and any
composited variations, as output variables during an AutoPkg run. This means you
can extract and generate icons, then immediately use those icons in subsequent
processors like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;grahampugh&#x2F;jamf-upload&#x2F;wiki&#x2F;JamfUploader-AutoPkg-Processors&quot;&gt;JamfPolicyUploader&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The following output variables are set if (and only if) the associated
variations are requested:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;app_icon_path&lt;&#x2F;code&gt;: path to the extracted, unmodified app icon. Always set.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;install_icon_path&lt;&#x2F;code&gt; path to the composited &amp;quot;install&amp;quot; variation. Only set if
this variations is requested.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;update_icon_path&lt;&#x2F;code&gt; path to the composited &amp;quot;update&amp;quot; variation. Only set if this
variations is requested.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;uninstall_icon_path&lt;&#x2F;code&gt; path to the composited &amp;quot;uninstall&amp;quot; variation. Only set
if this variations is requested.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;example-uses-in-recipes&quot;&gt;Example uses in recipes&lt;&#x2F;h2&gt;
&lt;p&gt;Here are two examples of using &lt;strong&gt;AppIconExtractor&lt;&#x2F;strong&gt; in a child recipe or
override.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;extract-the-icon-from-an-available-app-bundle&quot;&gt;Extract the icon from an available .app bundle&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;gregneagle-recipes&#x2F;blob&#x2F;master&#x2F;SublimeText&#x2F;SublimeText4.pkg.recipe&quot;&gt;Greg Neagle&#x27;s recipe for Sublime Text 4&lt;&#x2F;a&gt; leaves the unarchived
.app available in the recipe cache dir at &lt;code&gt;%RECIPE_CACHE_DIR%&#x2F;%NAME%&#x2F;Sublime Text.app&lt;&#x2F;code&gt;. We&#x27;ll use this to extract the Sublime Text icon using
&lt;strong&gt;AppIconExtractor&#x27;s&lt;&#x2F;strong&gt; default settings.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Process&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;com.github.haircut.processors&#x2F;AppIconExtractor&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;source_app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;%NAME%&#x2F;Sublime Text.app&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;com.github.grahampugh.jamf-upload.processors&#x2F;JamfPolicyUploader&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;policy_template&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%POLICY_TEMPLATE%&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;policy_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%POLICY_NAME%&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;icon&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%app_icon_path%&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;replace_icon&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-yaml&quot;&gt;True&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This extracts Sublime Text&#x27;s icon without generating any composite variations,
then feeds that extracted icon to the &lt;code&gt;JamfPolicyUploader&lt;&#x2F;code&gt; processor. We set
&lt;code&gt;replace_icon&lt;&#x2F;code&gt; to &lt;code&gt;True&lt;&#x2F;code&gt; to ensure any change to the icon by the vendor is
automatically reflected within our Jamf policy.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;unpacking-a-pkg-to-extract-an-icon&quot;&gt;Unpacking a .pkg to extract an icon&lt;&#x2F;h3&gt;
&lt;p&gt;The recipe for the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;recipes&#x2F;blob&#x2F;master&#x2F;GoogleChrome&#x2F;GoogleChromePkg.pkg.recipe&quot;&gt;Google Chrome Enterprise package&lt;&#x2F;a&gt; downloads a
.pkg directly from the vendor, so no repackaging is needed. And while the
AutoPkg recipe unpacks the package to performe code signature verification, it
then runs the &lt;code&gt;PathDeleter&lt;&#x2F;code&gt; processor to clean up that operation. This means a
child recipe does not have access to a .app from which to extract an icon.&lt;&#x2F;p&gt;
&lt;p&gt;That means we&#x27;ll need to do a little more work to unpack the package again so
that we can get to the app bundle. We&#x27;ll also generate a custom &amp;quot;uninstall&amp;quot;
variations and override the default composition position and padding.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the Process of this more complex example in XML format:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Process&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Processor&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;FlatPkgUnpacker&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Arguments&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;destination_path&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;unpack&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;flat_pkg_path&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%pkg_path%&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Processor&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PkgPayloadUnpacker&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Arguments&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;destination_path&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;unpack&#x2F;pkgpayload&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;pkg_payload_path&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;unpack&#x2F;GoogleChrome.pkg&#x2F;Payload&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Processor&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.github.haircut.processors&#x2F;AppIconExtractor&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Arguments&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;composite_padding&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;20&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;composite_position&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;ul&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;composite_uninstall_path&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;Icon-Uninstall-%NAME%.png&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;composite_uninstall_template&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;Users&#x2F;haircut&#x2F;Documents&#x2F;delete.png&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;icon_output_path&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;Icon-%NAME%.png&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;source_app&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;unpack&#x2F;pkgpayload&#x2F;Google Chrome.app&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Processor&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PathDeleter&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Arguments&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;path_list&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%RECIPE_CACHE_DIR%&#x2F;unpack&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Processor&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.github.grahampugh.jamf-upload.processors&#x2F;JamfPolicyUploader&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Arguments&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;icon&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%app_icon_path%&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;policy_name&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Install %NAME%&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;policy_template&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Self-Service-Policy.xml&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;replace_icon&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Processor&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.github.grahampugh.jamf-upload.processors&#x2F;JamfPolicyUploader&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Arguments&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;icon&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%uninstall_icon_path%&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;policy_name&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Uninstall %NAME%&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;policy_template&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Uninstall-Policy.xml&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;replace_icon&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This unpacks the Google Chrome enterprise package, extracts the unmodified app
icon, and generates an &amp;quot;uninstall&amp;quot; composite version with a custom graphic in
the upper left corner with 20px of padding.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;chrome-custom-example.4b9ce254eaff892c.webp&quot;alt=&quot;Examples of generating an uninstall icon using a custom template&quot;width=&quot;720&quot; height=&quot;245&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;The outputs of &lt;strong&gt;AppIconExtractor&lt;&#x2F;strong&gt; are then used as inputs to
JamfPolicyUploader process runs to set the icons for two different policies.
Setting the &lt;code&gt;replace_icon&lt;&#x2F;code&gt; argument to &lt;code&gt;True&lt;&#x2F;code&gt; ensures that any changes to the
icons are reflected on the Jamf Pro policies.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Hopefully this processor will help you extract icons without the manual work,
and spiff up those Self Service policies.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;haircut-recipes&#x2F;compare&quot;&gt;Pull requests accepted&lt;&#x2F;a&gt; if you fix a bug or make an improvement!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Stopping an AutoPkg Recipe if VirusTotal Detects Malware</title>
            <pubDate>Tue, 14 Dec 2021 00:00:00 +0000</pubDate>
            <link>https://macblog.org/stop-autopkg-virustotal/</link>
            <guid>https://macblog.org/stop-autopkg-virustotal/</guid>
            <description>&lt;p&gt;Hannes Juutilainen&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hjuutilainen&#x2F;autopkg-virustotalanalyzer&quot;&gt;VirusTotalAnalyzer&lt;&#x2F;a&gt; is a fantastic AutoPkg
postprocessor. It automatically queries &lt;a href=&quot;https:&#x2F;&#x2F;www.virustotal.com&quot;&gt;VirusTotal&lt;&#x2F;a&gt; to analyze items
downloaded by AutoPkg and detect potential malware.&lt;&#x2F;p&gt;
&lt;p&gt;VirusTotalAnalyzer was designed to run as a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;autopkg&#x2F;wiki&#x2F;PreAndPostProcessorSupport&quot;&gt;postprocessor&lt;&#x2F;a&gt;.
AutoPkg postprocessors allow you to add extra &amp;quot;steps&amp;quot; to an AutoPkg recipe at
runtime without modifying the recipe itself. By this convention,
VirusTotalAnalyzer scans files after all other recipe steps have completed. This
means a recipe cannot conditionally act on the VirusTotal scan results; the
query happens &lt;em&gt;after&lt;&#x2F;em&gt; the recipe has otherwise finished.&lt;&#x2F;p&gt;
&lt;p&gt;In practice, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;autopkg&#x2F;wiki&#x2F;Processor-CodeSignatureVerifier&quot;&gt;code signature verification&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;autopkg&#x2F;wiki&#x2F;AutoPkg-and-recipe-parent-trust-info&quot;&gt;recipe trust
verification&lt;&#x2F;a&gt;, and after-the-fact VirusTotal scanning offer strong
protections against malicious software. Most Mac admins also report &amp;quot;never&amp;quot;
seeing VirusTotal flag a vendor package; or if they have seen it, investigation
revealed a false positive.&lt;&#x2F;p&gt;
&lt;p&gt;However, many AutoPkg workflows directly upload or import software packages to a
Munki repository or Jamf Pro distribution point as part of a recipe run. If
VirusTotal engines flag an item, VirusTotalAnalyzer reports on the detection
&lt;em&gt;after the item is already uploaded to your systems&lt;&#x2F;em&gt;. Further, most
highly-automated AutoPkg workflows begin deploying the newly-uploaded software
to a test group (or all endpoints) as soon as the recipe completes.&lt;&#x2F;p&gt;
&lt;p&gt;You may require additional assurance that downloaded software is not flagged by
VirusTotal, and want to prevent any flagged files from being uploaded to your
software distribution points.&lt;&#x2F;p&gt;
&lt;p&gt;You can do this by using a custom recipe that runs VirusTotalAnalyzer as a
regular processor – instead of as a postprocessor – combined with the
StopProcessingIf processor. This allows you to terminate a recipe if VirusTotal
reports any hits &lt;strong&gt;before&lt;&#x2F;strong&gt; subsequent recipe steps upload an item to your
systems.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s how to do that.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h3 id=&quot;create-a-custom-recipe&quot;&gt;Create a Custom Recipe&lt;&#x2F;h3&gt;
&lt;p&gt;While it&#x27;s possible to &lt;em&gt;append&lt;&#x2F;em&gt; additional processors to a recipe within a
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;autopkg&#x2F;wiki&#x2F;Recipe-Overrides&quot;&gt;recipe override&lt;&#x2F;a&gt;, or call multiple postprocessors on the command
line, I recommend creating a custom recipe for each application. This allows you
to very specifically define &lt;em&gt;exactly&lt;&#x2F;em&gt; what you wish to happen during a recipe
run.&lt;&#x2F;p&gt;
&lt;p&gt;Yes, this is additional overhead. However, it&#x27;s not uncommon for an organization
to maintain custom recipes for all software to meet automation needs. And hey,
if you want this extra security layer, you&#x27;ll have to work a little for it.&lt;&#x2F;p&gt;
&lt;p&gt;I recommend creating an organization-specific child recipe for each app in your
catalog, and adding the required processors to that child recipe.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s use &lt;a href=&quot;https:&#x2F;&#x2F;rectangleapp.com&quot;&gt;Rectangle&lt;&#x2F;a&gt; as an example. Here&#x27;s the shell of a new custom
recipe:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Identifier&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;org.macblog.pkg.Rectangle&lt;&#x2F;span&gt;
&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;ParentRecipe&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;com.github.dataJAR-recipes.pkg.Rectangle&lt;&#x2F;span&gt;
&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;MinimumVersion&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;2.3&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;NAME&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Rectangle&lt;&#x2F;span&gt;
&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Process&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, I&#x27;ve set a new &lt;code&gt;Identifier&lt;&#x2F;code&gt; for the recipe specific to my organization. In
this example, I ultimately want a .pkg, so I set the &lt;code&gt;ParentRecipe&lt;&#x2F;code&gt; as the
identifier of the &lt;code&gt;pkg&lt;&#x2F;code&gt; version of the Rectangle recipe. Finally, since I&#x27;m
using YAML here, I set the &lt;code&gt;MinimumVersion&lt;&#x2F;code&gt; to &lt;code&gt;2.3&lt;&#x2F;code&gt; to require the version of
AutoPkg that supports YAML-formatted recipes.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m setting the &lt;code&gt;NAME&lt;&#x2F;code&gt; key in the &lt;code&gt;Input&lt;&#x2F;code&gt; dictionary to ensure AutoPkg
recognizes the file as a valid recipe. No additional Input keys are required for
this minimal example. You can, however, customize them to fit your needs.&lt;&#x2F;p&gt;
&lt;p&gt;Since this is a child recipe it inherits all the output of the parent recipe.
That means we don&#x27;t need to do anything to get the pkg output from the
parent, and the child recipe only needs to contain the additional processors we
want to run.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;autopkg-virustotal-stopprocessingif.eb7796f9110248f0.webp&quot;alt=&quot;Flow chart illustrating parent and child AutoPkg recipes.&quot;width=&quot;720&quot; height=&quot;396&quot;&gt;&lt;figcaption&gt;Each child recipe receives and can act on the output of its parent recipe.&lt;&#x2F;figcaption&gt;&lt;&#x2F;figure&gt;&lt;h3 id=&quot;add-virustotalanalyzer-as-a-regular-processor&quot;&gt;Add VirusTotalAnalyzer as a Regular Processor&lt;&#x2F;h3&gt;
&lt;p&gt;Instead of running VirusTotalAnalyzer as a postprocessor, you can call it as a
&amp;quot;regular&amp;quot; processor inside the &lt;code&gt;Process&lt;&#x2F;code&gt; dictionary of our custom recipe. Add it
like so:&lt;&#x2F;p&gt;
&lt;pre class=&quot;language-yaml z-code&quot;&gt;
    &lt;code&gt;
Identifier: org.macblog.pkg.Rectangle
ParentRecipe: com.github.dataJAR-recipes.pkg.Rectangle
MinimumVersion: &quot;2.3&quot;
Input:
  NAME: Rectangle
&lt;mark&gt;Process:
  - Processor: io.github.hjuutilainen.VirusTotalAnalyzer&#x2F;VirusTotalAnalyzer&lt;&#x2F;mark&gt;
    &lt;&#x2F;code&gt;
&lt;&#x2F;pre&gt;
&lt;p&gt;Since processors within a recipe run sequentially, you can run
VirusTotalAnalyzer immediately after downloading an item, but before subsequent
processors upload that item to your systems. It requires only that a &lt;code&gt;pathname&lt;&#x2F;code&gt;
variable exists.&lt;&#x2F;p&gt;
&lt;p&gt;In this example, the parent recipes have already handled downloading and
packaging the app. Our child recipe receives all the output of those previous
actions, and we&#x27;re ready to use VirusTotalAnalyzer to scan the downloaded item
for threats.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;add-a-stopprocessingif-processor&quot;&gt;Add a StopProcessingIf Processor&lt;&#x2F;h3&gt;
&lt;p&gt;Next, add the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;autopkg&#x2F;wiki&#x2F;Processor-StopProcessingIf&quot;&gt;StopProcessingIf&lt;&#x2F;a&gt; processor. The StopProcessingIf processor
terminates a recipe execution if a condition is met. This is most commonly
used to stop processing a recipe if a vendor download has not changed, by
setting the &lt;code&gt;predicate&lt;&#x2F;code&gt; to &lt;code&gt;download_changed == FALSE&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Because StopProcessingIf accepts &lt;a href=&quot;http:&#x2F;&#x2F;developer.apple.com&#x2F;library&#x2F;mac&#x2F;#documentation&#x2F;Cocoa&#x2F;Conceptual&#x2F;Predicates&#x2F;Articles&#x2F;pSyntax.html&quot;&gt;NSPredicate-style&lt;&#x2F;a&gt; conditions, we can
also test more complex conditions.&lt;&#x2F;p&gt;
&lt;p&gt;VirusTotalAnalyzer outputs its findings to the
&lt;code&gt;virus_total_analyzer_summary_result&lt;&#x2F;code&gt; output variable. Within that output is a
&lt;code&gt;ratio&lt;&#x2F;code&gt; key that denotes the number of VirusTotal engines that flagged a file as
suspicious out of the total number of engines that scanned the file, e.g.
&lt;code&gt;0&#x2F;55&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We can use the NSPredicate test &lt;code&gt;BEGINSWITH&lt;&#x2F;code&gt; to target the beginning of the
&lt;code&gt;ratio&lt;&#x2F;code&gt; variable string. That variable is nested a couple levels deep, and we
use dot notation to access nested values. Combined with a &lt;code&gt;NOT&lt;&#x2F;code&gt; negation, our
full predicate is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;NOT virus_total_analyzer_summary_result.data.ratio BEGINSWITH &amp;#39;0&#x2F;&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This means: &lt;em&gt;If the reported ratio from VirusTotal begins with anything other
than &lt;code&gt;0&#x2F;&lt;&#x2F;code&gt;, e.g. &lt;code&gt;1&#x2F;54&lt;&#x2F;code&gt; or &lt;code&gt;23&#x2F;68&lt;&#x2F;code&gt;, stop processing the recipe.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Add these items to the &lt;code&gt;Input&lt;&#x2F;code&gt; and &lt;code&gt;Process&lt;&#x2F;code&gt; dictionaries like so:&lt;&#x2F;p&gt;
&lt;pre class=&quot;language-yaml z-code&quot;&gt;
    &lt;code&gt;
Identifier: org.macblog.pkg.Rectangle
ParentRecipe: com.github.dataJAR-recipes.pkg.Rectangle
MinimumVersion: &quot;2.3&quot;
Input:
  NAME: Rectangle
&lt;mark&gt;  STOP_PREDICATE: &quot;NOT virus_total_analyzer_summary_result.data.ratio BEGINSWITH &#x27;0&#x27;&quot;&lt;&#x2F;mark&gt;  
Process:
  - Processor: io.github.hjuutilainen.VirusTotalAnalyzer&#x2F;VirusTotalAnalyzer

&lt;mark&gt;  - Processor: StopProcessingIf
    Arguments:
      predicate: &quot;%STOP_PREDICATE%&quot;&lt;&#x2F;mark&gt;
    &lt;&#x2F;code&gt;
&lt;&#x2F;pre&gt;
&lt;p&gt;Setting the predicate as an Input key allows you to override the predicate at
recipe runtime if you need to temporarily skip the StopProcessingIf
functionality. Manually passing &lt;code&gt;--key STOP_PREDICATE=FALSEPREDICATE&lt;&#x2F;code&gt; will bypass the
StopProcessingIf processor and allow the recipe to complete, even if VirusTotal
reports a detection.&lt;&#x2F;p&gt;
&lt;p class=&quot;update&quot;&gt;
    &lt;span class=&quot;update-lozenge&quot;&gt;Update:&lt;&#x2F;span&gt; Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;grahamrpugh.com&#x2F;&quot; title=&quot;Graham Pugh&#x27;s website&quot;&gt;Graham Pugh&lt;&#x2F;a&gt; for the suggestion to specify the predicate in the Input dictionary.
&lt;&#x2F;p&gt;
&lt;h3 id=&quot;add-your-other-processors&quot;&gt;Add Your Other Processors&lt;&#x2F;h3&gt;
&lt;p&gt;Add any additional processors &lt;em&gt;after&lt;&#x2F;em&gt; the StopProcessingIf processor to suit
your needs.&lt;&#x2F;p&gt;
&lt;p&gt;You might add &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;grahampugh&#x2F;jamf-upload&#x2F;wiki&#x2F;JamfUploader-AutoPkg-Processors&quot;&gt;JamfUploader&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;autopkg&#x2F;wiki&#x2F;Processor-MunkiImporter&quot;&gt;MunkiImporter&lt;&#x2F;a&gt;
processors to copy a package to your distribution servers. Whatever you add
after the StopProcessingIf processor will be executed only if VirusTotal reports
no malware detections.&lt;&#x2F;p&gt;
&lt;p&gt;This custom recipe can be used just like any other. You can (and should!) make
local overrides, run it in recipe lists, add chat-notifying postprocessors, and
commit it to your organization&#x27;s private recipe repository. Run it manually, or
within AutoPkgr, or in your CI pipeline.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;&#x2F;h3&gt;
&lt;p&gt;There are a few caveats worth mentioning:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;You need to create a custom recipe for every app in your catalog. You may be
doing this already – if so, good for you! (Or, try this
&lt;a href=&quot;https:&#x2F;&#x2F;macblog.org&#x2F;stop-autopkg-virustotal&#x2F;#alternative-to-a-custom-recipe&quot;&gt;alternative&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;You might get false positives, where a single VirusTotal engine erroneously
reports a detection. You&#x27;ll need to follow up manually, and perhaps
temporarily disable the VirusTotalAnalyzer (or StopProcessingIf) processor in
a recipe until VirusTotal or the vendor fixes the issue. As mentioned,
passing &lt;code&gt;--key STOP_PREDICATE=FALSEPREDICATE&lt;&#x2F;code&gt; will disable the StopProcessingIf
behavior.&lt;&#x2F;li&gt;
&lt;li&gt;You cannot set a &amp;quot;threshold&amp;quot; of a permissible number of potential detections.
The predicate used in the StopProcessingIf processor allows only &lt;strong&gt;zero&lt;&#x2F;strong&gt;
detections.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;If you don&#x27;t mind this overhead, and your organization requires this increased
assurance, you fit within the narrow band of utility this process provides. You
might even view the above caveats as good things. If so, enjoy!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;alternative-to-a-custom-recipe&quot;&gt;Alternative to a Custom Recipe&lt;&#x2F;h3&gt;
&lt;p&gt;AutoPkg is flexible, and you can run multiple postprocessors sequentially.
Instead of creating a custom recipe, it&#x27;s possible to &amp;quot;append&amp;quot; the required
postprocessors to an existing recipe on the command line as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;autopkg&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; run com.github.dataJAR-recipes.pkg.Rectangle &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;--&lt;&#x2F;span&gt;post&lt;&#x2F;span&gt; io.github.hjuutilainen.VirusTotalAnalyzer&#x2F;VirusTotalAnalyzer &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;--&lt;&#x2F;span&gt;post&lt;&#x2F;span&gt; StopProcessingIf &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;--&lt;&#x2F;span&gt;key&lt;&#x2F;span&gt; predicate=&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;NOT virus_total_analyzer_summary_result.data.ratio BEGINSWITH &amp;#39;0&amp;#39;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;--&lt;&#x2F;span&gt;post&lt;&#x2F;span&gt; com.github.grahampugh.jamf-upload.processors&#x2F;JamfPackageUploader&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I personally prefer maintaining a custom recipe. I most frequently run multiple
recipes using the &lt;code&gt;-l&lt;&#x2F;code&gt; or &lt;code&gt;--recipe-list&lt;&#x2F;code&gt; flag, and adding postprocessors to a
recipe list run will call all those postprocessors for every recipe. For me,
that decreases the flexibility afforded by creating a very explicit custom
recipe, which is why I recommend that route.&lt;&#x2F;p&gt;
&lt;p&gt;But the multiple-postprocessor option works fine if you prefer it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;complete-examples&quot;&gt;Complete Examples&lt;&#x2F;h3&gt;
&lt;p&gt;Here is a complete recipe example in both YAML and XML formats. It demonstrates
uploading the example Rectangle package to Jamf Pro if VirusTotal engines find
no malware.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;yaml&quot;&gt;YAML&lt;&#x2F;h4&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Identifier&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;org.macblog.pkg.Rectangle&lt;&#x2F;span&gt;
&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;ParentRecipe&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;com.github.dataJAR-recipes.pkg.Rectangle&lt;&#x2F;span&gt;
&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;MinimumVersion&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;2.3&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;NAME&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Rectangle&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;STOP_PREDICATE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;NOT virus_total_analyzer_summary_result.data.ratio BEGINSWITH &amp;#39;0&amp;#39;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Process&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;io.github.hjuutilainen.VirusTotalAnalyzer&#x2F;VirusTotalAnalyzer&lt;&#x2F;span&gt;

  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;StopProcessingIf&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;predicate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%STOP_PREDICATE%&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;com.github.grahampugh.jamf-upload.processors&#x2F;JamfPackageUploader&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;xml&quot;&gt;XML&lt;&#x2F;h4&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-preprocessor z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-xml&quot;&gt;xml&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;encoding&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;UTF-8&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;?&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-sgml z-doctype z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-doctype z-xml&quot;&gt;DOCTYPE&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-documentroot z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-external-content z-xml&quot;&gt;PUBLIC&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-&#x2F;&#x2F;Apple&#x2F;&#x2F;DTD PLIST 1.0&#x2F;&#x2F;EN&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;http:&#x2F;&#x2F;www.apple.com&#x2F;DTDs&#x2F;PropertyList-1.0.dtd&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Identifier&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;org.macblog.pkg.Rectangle&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Input&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;NAME&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Rectangle&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;STOP_PREDICATE&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;NOT virus_total_analyzer_summary_result.data.ratio BEGINSWITH &amp;#39;0&amp;#39;&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;MinimumVersion&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;2.3&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;ParentRecipe&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.github.dataJAR-recipes.pkg.Rectangle&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Process&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Processor&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;io.github.hjuutilainen.VirusTotalAnalyzer&#x2F;VirusTotalAnalyzer&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Arguments&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;predicate&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;%STOP_PREDICATE%&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Processor&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;StopProcessingIf&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Processor&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.github.grahampugh.jamf-upload.processors&#x2F;JamfPackageUploader&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</description>
        </item>
        <item>
            <title>Using JXA in Jamf Pro Scripts and Extension Attributes</title>
            <pubDate>Thu, 18 Nov 2021 00:00:00 +0000</pubDate>
            <link>https://macblog.org/jamf-jxa/</link>
            <guid>https://macblog.org/jamf-jxa/</guid>
            <description>&lt;p&gt;Quick follow-up to my earlier guide on &lt;a href=&quot;https:&#x2F;&#x2F;macblog.org&#x2F;parse-json-command-line-mac&#x2F;&quot;&gt;using JavaScript for Automation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There must be something in the air that put the topic of JXA on the minds of
the Apple community. Armin Briegel shared a &lt;a href=&quot;https:&#x2F;&#x2F;scriptingosx.com&#x2F;2021&#x2F;11&#x2F;the-unexpected-return-of-javascript-for-automation&#x2F;&quot;&gt;great roundup of recent JXA
work&lt;&#x2F;a&gt;, and the #scripting channel on the &lt;a href=&quot;https:&#x2F;&#x2F;www.macadmins.org&quot;&gt;MacAdmins Slack team&lt;&#x2F;a&gt; is
full of folks discussing new and old discoveries.&lt;&#x2F;p&gt;
&lt;p&gt;Here are a handful of additional tips.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;excutable-jxa-scripts&quot;&gt;Excutable JXA scripts&lt;&#x2F;h3&gt;
&lt;p&gt;You can run JXA directly by including the JavaScript language flag in a script&#x27;s
shebang, like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; class=&quot;language-javascript z-code&quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-shebang z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;#!&lt;&#x2F;span&gt;&#x2F;usr&#x2F;bin&#x2F;osascript -l JavaScript&lt;&#x2F;span&gt;

&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-ts&quot;&gt;function&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-definition z-function z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;Application&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;currentApplication&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;includeStandardAdditions&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-ts&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;systemInfo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;cpuType&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Save the file with a name and extension you like. I&#x27;ve been using &lt;code&gt;.scpt&lt;&#x2F;code&gt;, which
is the convention suggested by Apple&#x27;s own Script Editor application. Something
like &lt;code&gt;cputype.scpt&lt;&#x2F;code&gt; will work just fine.&lt;&#x2F;p&gt;
&lt;p&gt;Mark the file as executable by running &lt;code&gt;chmod +x cputype.scpt&lt;&#x2F;code&gt;. Then, you can
run it on your system by simply calling &lt;code&gt;.&#x2F;cputype.scpt&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This will output the CPU architecture of the computer, for example &lt;code&gt;ARM64E&lt;&#x2F;code&gt; or
&lt;code&gt;Intel x86-64...&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;jxa-in-jamf-pro-scripts&quot;&gt;JXA in Jamf Pro Scripts&lt;&#x2F;h3&gt;
&lt;p&gt;You can drop a JXA script directly in Jamf Pro without any modification. As
long as you include the JavaScript shebang outlined above, you&#x27;re good to go.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;You do not necessarily need to wrap JXA in a shell script.&lt;&#x2F;strong&gt; It might make
sense to &amp;quot;shell out&amp;quot; to a JXA function from a shell script for some use cases,
but it is not a requirement.&lt;&#x2F;p&gt;
&lt;p&gt;Jamf &lt;a href=&quot;https:&#x2F;&#x2F;docs.jamf.com&#x2F;10.0.0&#x2F;jamf-pro&#x2F;administrator-guide&#x2F;Managing_Scripts.html&quot;&gt;supports non-compiled AppleScript files&lt;&#x2F;a&gt; natively, and you
can use them in your Policies like any other script.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;jxa-in-jamf-pro-extension-attributes&quot;&gt;JXA in Jamf Pro Extension Attributes&lt;&#x2F;h3&gt;
&lt;p&gt;Same deal; specify the Script type for the Extension Attribute, and include the
JavaScript language flag shebang. Ensure your function returns the required
&lt;code&gt;&amp;lt;result&amp;gt;&amp;lt;&#x2F;result&amp;gt;&lt;&#x2F;code&gt; wrapper surrounding the output. You can do that with simple
&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Operators&#x2F;Addition&quot;&gt;string concatenation using the plus operator&lt;&#x2F;a&gt;, like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; class=&quot;language-javascript z-code&quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-shebang z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;#!&lt;&#x2F;span&gt;&#x2F;usr&#x2F;bin&#x2F;osascript -l JavaScript&lt;&#x2F;span&gt;

&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-ts&quot;&gt;function&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-definition z-function z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;Application&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;currentApplication&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;includeStandardAdditions&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-ts&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&amp;lt;result&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;systemInfo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;cpuType&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&amp;lt;&#x2F;result&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will output &lt;code&gt;&amp;lt;result&amp;gt;ARM64E&amp;lt;&#x2F;result&amp;gt;&lt;&#x2F;code&gt;, for example, which will show up on
your computer&#x27;s inventory record during the next device inventory.&lt;&#x2F;p&gt;
&lt;p&gt;--&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s it. Hopefully this helps you store and run JavaScript for Automation
scripts.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>How to Parse JSON on the macOS Command Line Without External Tools Using JavaScript for Automation</title>
            <pubDate>Sun, 14 Nov 2021 00:00:00 +0000</pubDate>
            <link>https://macblog.org/parse-json-command-line-mac/</link>
            <guid>https://macblog.org/parse-json-command-line-mac/</guid>
            <description>&lt;p&gt;JSON – &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;JSON&quot;&gt;JavaScript Object Notation&lt;&#x2F;a&gt; – is the lingua franca for
shipping data between systems. Everything from software APIs to web services
commonly support, and typically default to, outputting data in JSON format.&lt;&#x2F;p&gt;
&lt;p&gt;Because of its ubiquity, you&#x27;re bound to run into a need to manipulate a chunk
of JSON in the course of managing your fleet.&lt;&#x2F;p&gt;
&lt;p&gt;For example, you might run a shell script on your Macs that instructs them to
read data from an external system via its API using &lt;code&gt;curl&lt;&#x2F;code&gt;. That external system
returns a big ol&#x27; heap of JSON, but you need to extract only a single data point
from that payload, then act on that value.&lt;&#x2F;p&gt;
&lt;p&gt;This is somewhat of a challenge in the shell because macOS does not include any
native or pre-installed tools to help you hack down that JSON. Administrators
often resort to workarounds like shelling out to Python or using &lt;code&gt;sed&lt;&#x2F;code&gt; and &lt;code&gt;awk&lt;&#x2F;code&gt;
to approximate parsing.&lt;&#x2F;p&gt;
&lt;p&gt;However, another, &lt;strong&gt;native&lt;&#x2F;strong&gt; solution is right there in the name: use
JavaScript.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h3 id=&quot;javascript-jxa-and-open-scripting-architecture&quot;&gt;JavaScript, JXA and Open Scripting Architecture&lt;&#x2F;h3&gt;
&lt;p&gt;It seems appropriate to use JavaScript to parse &lt;em&gt;JavaScript&lt;&#x2F;em&gt; Object Notation,
right? But how? Can you do that without relying on external tools?&lt;&#x2F;p&gt;
&lt;p&gt;Since Mac OS X Yosemite, Apple has supported JavaScript as a language to
interact with the &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;library&#x2F;archive&#x2F;documentation&#x2F;LanguagesUtilities&#x2F;Conceptual&#x2F;MacAutomationScriptingGuide&#x2F;HowMacScriptingWorks.html&quot;&gt;Open Scripting Architecture (OSA)&lt;&#x2F;a&gt;. OSA enables
interapplication communication for automation, and using JavaScript for this
purpose is known as &lt;em&gt;JavaScript for Automation&lt;&#x2F;em&gt; (JXA).&lt;&#x2F;p&gt;
&lt;p&gt;JXA is built right into macOS and lets you use JavaScript without any
additional tooling.&lt;&#x2F;p&gt;
&lt;p&gt;You may be familiar with using the &lt;code&gt;osascript&lt;&#x2F;code&gt; binary to execute AppleScript
snippets. While AppleScript is a more common choice for accessing OSA
functionality, you can trivially use JavaScript instead.&lt;&#x2F;p&gt;
&lt;p&gt;On the command line, use the &lt;code&gt;-l&lt;&#x2F;code&gt; (that&#x27;s a lowercase L) flag  with &lt;code&gt;osascript&lt;&#x2F;code&gt;
to specify &lt;code&gt;JavaScript&lt;&#x2F;code&gt; as the scripting language. Without the flag, &lt;code&gt;osascript&lt;&#x2F;code&gt;
defaults to expecting AppleScript. &lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a simple example derived from &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;library&#x2F;archive&#x2F;documentation&#x2F;LanguagesUtilities&#x2F;Conceptual&#x2F;MacAutomationScriptingGuide&#x2F;DisplayDialogsandAlerts.html#&#x2F;&#x2F;apple_ref&#x2F;doc&#x2F;uid&#x2F;TP40016239-CH15-SW1&quot;&gt;Apple&#x27;s sample code&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; class=&quot;language-javascript z-code&quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;osascript&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;l&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;JavaScript&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;e&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;var app = Application.currentApplication(); app.includeStandardAdditions = true; app.displayDialog(&amp;quot;Hello from JavaScript!&amp;quot;);&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will display a dialog window using JavaScript. Easy!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;using-jxa-to-read-json-in-a-shell-script&quot;&gt;Using JXA to read JSON in a shell script&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s look at an example where we use the &lt;a href=&quot;https:&#x2F;&#x2F;ip-api.com&quot;&gt;ip-api.com&lt;&#x2F;a&gt; service to query
the current geographic location of the system based on its IP address.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; class=&quot;language-javascript z-code&quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-shebang z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;#!&lt;&#x2F;span&gt;&#x2F;bin&#x2F;bash&lt;&#x2F;span&gt;

&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;GEODATA&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;curl&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;s&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;http&lt;&#x2F;span&gt;:&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;ip-api.com&#x2F;json&#x2F; )&lt;&#x2F;span&gt;

&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;read&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;r&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;d&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;JXA&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-bitwise z-shift z-ts&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;EOF&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-function z-expression z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-ts&quot;&gt;function&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-definition z-function z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;ipinfo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-constant z-json z-ts&quot;&gt;JSON&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-json z-ts&quot;&gt;parse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;\&lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;$GEODATA&lt;span class=&quot;z-constant z-character z-escape z-ts&quot;&gt;\`&lt;&#x2F;span&gt;);
	return ipinfo.city;
}
EOF

CITY=$( osascript -l &amp;#39;JavaScript&amp;#39; &amp;lt;&amp;lt;&amp;lt; &amp;quot;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;JXA&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&amp;quot; )

echo &amp;quot;This computer is in &lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;CITY&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;First, we call the ip-api service by using &lt;code&gt;curl&lt;&#x2F;code&gt; to send a &lt;code&gt;GET&lt;&#x2F;code&gt; request to the
service&#x27;s JSON endpoint. The results are stored in a variable called &lt;code&gt;GEODATA&lt;&#x2F;code&gt;
via &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;bash&#x2F;manual&#x2F;html_node&#x2F;Command-Substitution.html&quot;&gt;command substitution&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Next, we use the &lt;code&gt;read -r -d &#x27;&#x27; VARIABLE_NAME &amp;lt;&amp;lt;LIMIT_STRING&lt;&#x2F;code&gt; &amp;quot;bashism&amp;quot; to store
a multi-line JavaScript program as a variable using &lt;a href=&quot;https:&#x2F;&#x2F;tldp.org&#x2F;LDP&#x2F;abs&#x2F;html&#x2F;here-docs.html&quot;&gt;here-document&lt;&#x2F;a&gt;
notation. This makes it easier to write and maintain the JavaScript code, rather
than trying to smoosh it into a single line.&lt;&#x2F;p&gt;
&lt;p&gt;This (extremely basic) JavaScript program takes advantage of JXA&#x27;s special
&lt;code&gt;run()&lt;&#x2F;code&gt; function. &lt;code&gt;run()&lt;&#x2F;code&gt; is automatically executed when the program is called,
and will print any output returned.&lt;&#x2F;p&gt;
&lt;p&gt;Within the JavaScript code, notice the assignment of &lt;code&gt;ipinfo&lt;&#x2F;code&gt; references the
&lt;code&gt;GEODATA&lt;&#x2F;code&gt; variable defined in the outer shell script via variable expansion. The
JSON returned by ip-api.com is a native JavaScript data structure that could be
used directly, but for safety we treat it as a string and parse it using the
&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Global_Objects&#x2F;JSON&#x2F;parse&quot;&gt;&lt;code&gt;JSON.parse()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; method. Since most JSON payloads are multi-line
strings, we wrap the variable expansion in &lt;code&gt;``&lt;&#x2F;code&gt; backticks to take
advantage of &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Template_literals&quot;&gt;JavaScript&#x27;s template literal&lt;&#x2F;a&gt; feature. And finally,
those backticks need to be escaped using &lt;code&gt;\&lt;&#x2F;code&gt; backslashes since they&#x27;re embedded
within a shall script. Whew!&lt;&#x2F;p&gt;
&lt;aside class=&quot;alert&quot;&gt;&lt;p&gt;When I first published this article, I advised that you could reference and use
a JSON object received from a remote source directly, without running it through
&lt;code&gt;JSON.parse()&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This is true, but it&#x27;s not secure. I was assuming the safety of the external
data.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;paulgalow.com&#x2F;how-to-work-with-json-api-data-in-macos-shell-scripts&quot; title=&quot;How to work with JSON API data in macOS shell scripts without external dependencies&quot;&gt;Paul Galow wisely pointed out&lt;&#x2F;a&gt; that a malicious source could
potentially send JavaScript instead of JSON, which our script would dutifully
execute. RCEs are bad. Be like Paul and run payloads through
&lt;code&gt;JSON.parse()&lt;&#x2F;code&gt;. This ensures things that aren&#x27;t JSON cause the script
to error.&lt;&#x2F;p&gt;
&lt;&#x2F;aside&gt;
&lt;p&gt;A quick aside on quoting and here-documents: Quoting the limit string (&lt;code&gt;EOF&lt;&#x2F;code&gt; in
this case) will &lt;strong&gt;prevent&lt;&#x2F;strong&gt; variable expansion within the here-document.
&lt;code&gt;&amp;lt;&amp;lt;&#x27;EOF&#x27;&lt;&#x2F;code&gt; would cause &lt;code&gt;$GEODATA&lt;&#x2F;code&gt; to be interpretted literally rather than
replaced by the results of the &lt;code&gt;curl&lt;&#x2F;code&gt; command. The unquoted &lt;code&gt;&amp;lt;&amp;lt;EOF&lt;&#x2F;code&gt; allows the
variable to expand as expected.&lt;&#x2F;p&gt;
&lt;p&gt;Next, we simply return the &lt;code&gt;city&lt;&#x2F;code&gt; attribute of the &lt;code&gt;ipinfo&lt;&#x2F;code&gt; object.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, we use the &lt;code&gt;osascript&lt;&#x2F;code&gt; binary to run the JavaScript program.
&lt;code&gt;osascript&lt;&#x2F;code&gt; can read input from &lt;code&gt;stdin&lt;&#x2F;code&gt;, so we use &lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&lt;&#x2F;code&gt; to read the program
stored in the &lt;code&gt;JXA&lt;&#x2F;code&gt; variable. Storing its output in the &lt;code&gt;CITY&lt;&#x2F;code&gt; variable lets us
use it elsewhere in the shell script. In this case we&#x27;re outputting a nice
message. Running the script will print &lt;code&gt;This computer is in Atlanta&lt;&#x2F;code&gt; (or
your approximate location) to your terminal.&lt;&#x2F;p&gt;
&lt;p&gt;That was an extremely verbose explanation of a very basic program! But,
hopefully it helps explain the patterns being used here. Now let&#x27;s try something
more complex.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;complex-json-manipulation&quot;&gt;Complex JSON manipulation&lt;&#x2F;h3&gt;
&lt;p&gt;Our next example will demonstrate the power of JavaScript&#x27;s native JSON
capabilities. It&#x27;s a neat trick to pull a single attribute out of a simple JSON
payload – but it&#x27;s &lt;strong&gt;actually useful&lt;&#x2F;strong&gt; to manipulate the data using
conditional logic.&lt;&#x2F;p&gt;
&lt;p&gt;Here we&#x27;ll pull the recent commit history of the AutoPkg GitHub repository, then
retrieve the commits whose commit message length is longer than the soft
50-character recommended maximum length.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the code:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; class=&quot;language-javascript z-code&quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-shebang z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;#!&lt;&#x2F;span&gt;&#x2F;bin&#x2F;bash&lt;&#x2F;span&gt;

&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;GITHUB&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;curl&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;s&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;https&lt;&#x2F;span&gt;:&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;api.github.com&#x2F;repos&#x2F;autopkg&#x2F;autopkg&#x2F;commits )&lt;&#x2F;span&gt;

&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;read&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;r&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;d&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;GITCOMMITS&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-bitwise z-shift z-ts&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;EOF&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-function z-expression z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-ts&quot;&gt;function&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-definition z-function z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;commits&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-constant z-json z-ts&quot;&gt;JSON&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-json z-ts&quot;&gt;parse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;\&lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;$GITHUB&lt;span class=&quot;z-constant z-character z-escape z-ts&quot;&gt;\`&lt;&#x2F;span&gt;);
	const long_messages = [];
	for (const commit of commits) {
		if (commit.commit.message.length &amp;gt; 50) {
			var msg = &amp;quot;&amp;#39;&amp;quot; + commit.commit.message + &amp;quot;&amp;#39; - Commit &amp;quot; + commit.sha;
			long_messages.push(msg);
		}
	}
	return long_messages.join(&amp;quot;&lt;span class=&quot;z-constant z-character z-escape z-ts&quot;&gt;\n&lt;&#x2F;span&gt;&amp;quot;);
}
EOF

osascript -l &amp;quot;JavaScript&amp;quot; &amp;lt;&amp;lt;&amp;lt; &amp;quot;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;GITCOMMITS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The basic structure is largely the same as in the previous example: use &lt;code&gt;curl&lt;&#x2F;code&gt;
to gather data, then feed that into a JavaScript program.&lt;&#x2F;p&gt;
&lt;p&gt;The cool part is being able to manipulate the JSON data in place. Here, we&#x27;re
iterating through each commit and checking the string length of each commit
message. If that length is longer than 50 characters, we append that message to
an array, along with the commit&#x27;s SHA hash. Finally, we return a newline-joined
string of those commits.&lt;&#x2F;p&gt;
&lt;p&gt;The end result prints only those commit messages longer than 50 characters.&lt;&#x2F;p&gt;
&lt;p&gt;This example would have been &lt;em&gt;extremely&lt;&#x2F;em&gt; cumbersome to implement in pure shell.
With JXA, it&#x27;s just some relatively simple JavaScript.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;reading-json-files-from-disk&quot;&gt;Reading JSON files from disk&lt;&#x2F;h3&gt;
&lt;p&gt;You can also read JSON files that exist on disk with just a tiny bit of extra
effort.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; class=&quot;language-javascript z-code&quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-shebang z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;#!&lt;&#x2F;span&gt;&#x2F;bin&#x2F;bash&lt;&#x2F;span&gt;

&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;read&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;r&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;d&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;PARSE&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-bitwise z-shift z-ts&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;EOF&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;Application&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;currentApplication&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;includeStandardAdditions&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-ts&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;

&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-ts&quot;&gt;function&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-definition z-function z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;parseJSON&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;path&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;read&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;path&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-constant z-json z-ts&quot;&gt;JSON&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-json z-ts&quot;&gt;parse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-ts&quot;&gt;function&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-definition z-function z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;parsed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;parseJSON&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;path&#x2F;to&#x2F;some&#x2F;file.json&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;parsed&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;some&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;EOF&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This time, we&#x27;re using using JXA to get an instance of the &amp;quot;current
application.&amp;quot; This lets us do useful things like access the file system. We
define a reusable function to parse a JSON file at a path supplied as a
parameter. Within the &lt;code&gt;run()&lt;&#x2F;code&gt; function, we call that &lt;code&gt;parseJSON()&lt;&#x2F;code&gt; function and
supply the full path to a JSON file. We can then access the parsed JSON
properties using standard &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Operators&#x2F;Property_accessors&quot;&gt;dot notation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;other-tools-and-alternatives&quot;&gt;Other tools and alternatives&lt;&#x2F;h3&gt;
&lt;p&gt;Why go through the trouble of using JXA for these use cases?&lt;&#x2F;p&gt;
&lt;p&gt;First, it&#x27;s really not much &amp;quot;trouble.&amp;quot; I&#x27;d be implementing similar logic in
another external language or tool. This is more or less adding a thin wrapper.
As long as you are comfortable writing JavaScript (or searching StackOverflow),
it&#x27;s very little extra effort.&lt;&#x2F;p&gt;
&lt;p&gt;But why not use another tool or method?&lt;&#x2F;p&gt;
&lt;p&gt;When running code on client systems within a fleet, it&#x27;s best to use the tools
those clients have available by default.&lt;&#x2F;p&gt;
&lt;p&gt;Since &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;documentation&#x2F;macos-release-notes&#x2F;macos-catalina-10_15-release-notes#:~:text=49764202&quot;&gt;Apple will soon stop shipping scripting runtimes&lt;&#x2F;a&gt; such as
Python, Perl, and Ruby, you &lt;strong&gt;should not&lt;&#x2F;strong&gt; rely on &amp;quot;shelling out&amp;quot; to those
languages. Sure, it might be easy enough to add a &lt;code&gt;parse=$( python -c &#x27;import json;...&#x27; )&lt;&#x2F;code&gt; call to your script; but at this point you&#x27;d just be creating new
technical debt. Don&#x27;t do that.&lt;&#x2F;p&gt;
&lt;p&gt;If you ship your own Python 3 runtime – such as with &amp;quot;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;macadmins&#x2F;python&quot;&gt;macadmin
python&lt;&#x2F;a&gt;&amp;quot; – you could, of course, use that. Installing your own
Python 3 framework on your clients is a great idea if you routinely use Python
code to manage them. Otherwise, it &lt;em&gt;is&lt;&#x2F;em&gt; another external dependency.&lt;&#x2F;p&gt;
&lt;p&gt;Alternatively, you &lt;em&gt;could&lt;&#x2F;em&gt; pull down &lt;a href=&quot;https:&#x2F;&#x2F;stedolan.github.io&#x2F;jq&#x2F;&quot;&gt;jq&lt;&#x2F;a&gt; on your client systems. jq is
built specifically to handle JSON on the command line and in shell scripts. But
again – it&#x27;s an external dependency.&lt;&#x2F;p&gt;
&lt;p&gt;Using JXA requires no new installations or configuration changes. It will simply
run on your systems as they currently exist.&lt;&#x2F;p&gt;
&lt;p&gt;For that reason, I think JXA a great tool to reach for when you need to work
with JSON.&lt;&#x2F;p&gt;
&lt;p&gt;Plus, constraints are fun, right?!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;further-reading&quot;&gt;Further reading&lt;&#x2F;h3&gt;
&lt;p&gt;Interacting with JSON is a common need, but these examples barely scratch the
surface of what you can achieve with JavaScript for Automation.&lt;&#x2F;p&gt;
&lt;p&gt;JXA even includes an &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;JXA-Cookbook&#x2F;JXA-Cookbook&#x2F;wiki&#x2F;Using-Objective-C-%28ObjC%29-with-JXA&quot;&gt;Objective-C bridge&lt;&#x2F;a&gt;, which allows you to use macOS
frameworks like AppKit and Foundation.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;JXA-Cookbook&#x2F;JXA-Cookbook&quot;&gt;JXA Cookbook&lt;&#x2F;a&gt; on GitHub contains a wealth of information and
is an essential read on this topic. It&#x27;s a great supplement to Apple&#x27;s somewhat
&lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;library&#x2F;archive&#x2F;releasenotes&#x2F;InterapplicationCommunication&#x2F;RN-JavaScriptForAutomation&#x2F;index.html&quot;&gt;sparse documentation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>How to Disable iCloud Private Relay in macOS Monterey</title>
            <pubDate>Wed, 27 Oct 2021 00:00:00 +0000</pubDate>
            <link>https://macblog.org/disable-icloud-private-relay/</link>
            <guid>https://macblog.org/disable-icloud-private-relay/</guid>
            <description>&lt;p&gt;Apple recently introduced &lt;a href=&quot;https:&#x2F;&#x2F;support.apple.com&#x2F;en-us&#x2F;HT212614&quot;&gt;iCloud Private Relay&lt;&#x2F;a&gt; as an additional
benefit for iCloud+ subscribers. The feature routes Safari web browsing
(and some other insecure Internet traffic) through a semi-anonymizing service
to reduce third parties&#x27; ability to profile and track individual users.&lt;&#x2F;p&gt;
&lt;p&gt;However, it may be necessary in some environments to disable iCloud Private
Relay. The feature may interfere with management controls, prevent required
traffic auditing, or complicate troubleshooting procedures.&lt;&#x2F;p&gt;
&lt;p&gt;Apple provides a &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;support&#x2F;prepare-your-network-for-icloud-private-relay&quot;&gt;guide to prepare your network or service for iCloud Private
Relay&lt;&#x2F;a&gt;, but it&#x27;s also possible to disable the feature using a
&lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;documentation&#x2F;devicemanagement&#x2F;restrictions&quot;&gt;Restrictions&lt;&#x2F;a&gt; Configuration Profile.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;To disable iCloud Private Relay, set the &lt;code&gt;allowCloudPrivateRelay&lt;&#x2F;code&gt; key to &lt;code&gt;false&lt;&#x2F;code&gt;
in the &lt;code&gt;com.apple.applicationaccess&lt;&#x2F;code&gt; domain. An example full Configuration
Profile is below:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-preprocessor z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-xml&quot;&gt;xml&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;encoding&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;UTF-8&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;?&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-sgml z-doctype z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-doctype z-xml&quot;&gt;DOCTYPE&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-documentroot z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-external-content z-xml&quot;&gt;PUBLIC&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-&#x2F;&#x2F;Apple&#x2F;&#x2F;DTD PLIST 1.0&#x2F;&#x2F;EN&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;http:&#x2F;&#x2F;www.apple.com&#x2F;DTDs&#x2F;PropertyList-1.0.dtd&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadContent&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadDisplayName&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Restrictions&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadIdentifier&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.apple.applicationaccess.E8C72ECD-7122-4C66-853F-3F3467D1AEF5&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadType&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;com.apple.applicationaccess&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadUUID&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;1953B7E6-DB5C-4FDA-A579-2EE05978F4B6&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadVersion&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;1&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;allowCloudPrivateRelay&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
                &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;false&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
            &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadDescription&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Disables the iCloud Private Relay feature.&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadDisplayName&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Disable iCloud Private Relay&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadIdentifier&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;E31B0811-3164-49CE-BAA9-67075398DE85&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadOrganization&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Company Name&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadScope&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;System&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadType&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Configuration&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadUUID&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;ECEB2ECA-B16F-41F8-9909-7DD36FA1609C&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;PayloadVersion&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;1&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;dict&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;plist&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This profile is also &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;haircut&#x2F;1dbb4a0ea6988d5bf2c9388b03047faa&quot;&gt;available on GitHub&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Once installed, this profile:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Stops traffic from routing to &lt;code&gt;mask.icloud.com&lt;&#x2F;code&gt; and &lt;code&gt;mask-h2.icloud.com&lt;&#x2F;code&gt; at
the network level.&lt;&#x2F;li&gt;
&lt;li&gt;Removes &amp;quot;Private Relay&amp;quot; from the list of services available to enable in
&lt;em&gt;System Preferences &amp;gt; Apple ID&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Removes the &amp;quot;Use iCloud Private Relay&amp;quot; checkbox from the &amp;quot;Network&amp;quot; pane in
System Preferences.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;requirements&quot;&gt;Requirements&lt;&#x2F;h3&gt;
&lt;p&gt;Unlike many Configuration Profiles payloads, the &lt;code&gt;com.apple.applicationaccess&lt;&#x2F;code&gt;
payload is re-evaluated after initial installation.&lt;&#x2F;p&gt;
&lt;p&gt;That means this profile can be pre-installed on systems running macOS versions
prior to Monterey. Go ahead and deploy this restriction to your fleet before
they upgrade to macOS Monterey so the configuration takes immediate effect. It
won&#x27;t have any effect on macOS Big Sur (or previous systems), but will begin
working once the system is upgraded to Monterey.&lt;&#x2F;p&gt;
&lt;p&gt;This restriction &lt;em&gt;does not&lt;&#x2F;em&gt; require Supervision.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;caveat&quot;&gt;Caveat&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;ve noted a small bug in macOS Monterey 12.0.1. If the Configuration Profile
restricting iCloud Private Relay is installed &lt;em&gt;while the relay is active&lt;&#x2F;em&gt;, the
checkbox in &lt;em&gt;System Preferences &amp;gt; Network&lt;&#x2F;em&gt; remains visible.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;icloud-private-relay-network-preferences.67faf81eda002bc1.webp&quot;alt=&quot;iCloud Private Relay checkbox in System Preferences &amp;gt; Network.&quot;width=&quot;720&quot; height=&quot;686&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Private Relay &lt;mark&gt;is in fact disabled&lt;&#x2F;mark&gt;, and no traffic is routed through
the service. The &amp;quot;Private Relay&amp;quot; feature &lt;em&gt;is&lt;&#x2F;em&gt; removed from the listing in
&lt;em&gt;System Preferences &amp;gt; Apple ID&lt;&#x2F;em&gt;. This visual bug persists through reboots, but
only occurs when the profile is installed while iCloud Private Relay is already
running.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Getting the currently logged-in user&#x27;s ID (UID) for launchctl</title>
            <pubDate>Mon, 15 Mar 2021 00:00:00 +0000</pubDate>
            <link>https://macblog.org/uid/</link>
            <guid>https://macblog.org/uid/</guid>
            <description>&lt;p&gt;Many scripted macOS workflows require determining the username of the currently logged-in user. Whether you wish to execute a command as that user via &lt;code&gt;su&lt;&#x2F;code&gt; or you just want to log the username during your script&#x27;s execution, you may need to query macOS for this information.&lt;&#x2F;p&gt;
&lt;p&gt;This is a solved problem, and Armin Briegel&#x27;s excellent article on &lt;a href=&quot;https:&#x2F;&#x2F;scriptingosx.com&#x2F;2020&#x2F;02&#x2F;getting-the-current-user-in-macos-update&#x2F;&quot;&gt;Getting the current user in macOS&lt;&#x2F;a&gt; outlines the best method.&lt;&#x2F;p&gt;
&lt;p&gt;In addition to determining the logged-in user&#x27;s username, you may also need their user ID number, or UID. For example, loading a LaunchAgent as a specific user requires providing that user&#x27;s UID. &lt;&#x2F;p&gt;
&lt;p&gt;Previous solutions involved grabbing the logged-in user&#x27;s username, then feeding that to &lt;code&gt;id -u $loggedInUser&lt;&#x2F;code&gt; – but you can get the currently logged-in user&#x27;s UID in one step.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;the-code&quot;&gt;The code&lt;&#x2F;h2&gt;
&lt;p&gt;A slight modification of Armin&#x27;s recommendation for grabbing the username will give us the UID.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;for-bash-and-zsh&quot;&gt;For bash and zsh&lt;&#x2F;h3&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;loggedInUserID=$( scutil &amp;lt;&amp;lt;&amp;lt; &amp;quot;show State:&#x2F;Users&#x2F;ConsoleUser&amp;quot; | awk &amp;#39;&#x2F;kCGSSessionUserIDKey :&#x2F; { print $3 }&amp;#39; )
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;for-shell&quot;&gt;For shell&lt;&#x2F;h3&gt;
&lt;p&gt;Vanilla shell does not support the &lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;tldp.org&#x2F;LDP&#x2F;abs&#x2F;html&#x2F;x17837.html&quot;&gt;here-string&lt;&#x2F;a&gt; used in the previous example, so instead we must pipe the &lt;code&gt;show&lt;&#x2F;code&gt; statement to &lt;code&gt;scutil&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;loggedInUserID=$( echo &amp;quot;show State:&#x2F;Users&#x2F;ConsoleUser&amp;quot; | scutil | awk &amp;#39;&#x2F;kCGSSessionUserIDKey :&#x2F; { print $3 }&amp;#39; )
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Both variants will return the UID of the currently logged-in user, or an empty string if the Mac is sitting at the login window.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;an-example-and-a-note-on-launchctl-syntax&quot;&gt;An example and a note on &lt;code&gt;launchctl&lt;&#x2F;code&gt; syntax&lt;&#x2F;h2&gt;
&lt;p&gt;With a UID in hand, you can now load a LaunchAgent &lt;em&gt;as&lt;&#x2F;em&gt; that user:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;launchctl asuser &amp;lt;uid&amp;gt; launchctl load &#x2F;Library&#x2F;LaunchAgents&#x2F;com.org.example.plist
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However! In macOS Big Sur, I&#x27;m finding &lt;code&gt;launchctl&lt;&#x2F;code&gt; is more reliable using the launchctl 2.0 syntax (as &lt;a href=&quot;https:&#x2F;&#x2F;babodee.wordpress.com&#x2F;2016&#x2F;04&#x2F;09&#x2F;launchctl-2-0-syntax&#x2F;&quot;&gt;documented by Balmes Pavlov&lt;&#x2F;a&gt;). This makes sense, as subcommands like &lt;code&gt;asuser&lt;&#x2F;code&gt; have been marked as &amp;quot;legacy&amp;quot; for some time now.&lt;&#x2F;p&gt;
&lt;p&gt;Switching from the &amp;quot;legacy&amp;quot; subcommand &lt;code&gt;asuser&lt;&#x2F;code&gt; to &lt;code&gt;bootstrap gui&#x2F;&amp;quot;${loggedInUserID}&amp;quot;&lt;&#x2F;code&gt; consistently loads launchd tasks, and is my current recommendation.&lt;&#x2F;p&gt;
&lt;p&gt;A complete example of loading a LaunchAgent as the currently logged-in user:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;loggedInUserID=$( scutil &amp;lt;&amp;lt;&amp;lt; &amp;quot;show State:&#x2F;Users&#x2F;ConsoleUser&amp;quot; | awk &amp;#39;&#x2F;kCGSSessionUserIDKey :&#x2F; &amp;amp;&amp;amp; ! &#x2F;loginwindow&#x2F; { print $3 }&amp;#39; )
&#x2F;bin&#x2F;launchctl bootstrap gui&#x2F;&amp;quot;${loggedInUserID}&amp;quot; &#x2F;Library&#x2F;LaunchAgents&#x2F;com.org.example.plist
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</description>
        </item>
        <item>
            <title>Renaming Computers via Snipe-IT using Jamf Pro</title>
            <pubDate>Wed, 13 Jan 2021 00:00:00 +0000</pubDate>
            <link>https://macblog.org/jamf-snipe-rename/</link>
            <guid>https://macblog.org/jamf-snipe-rename/</guid>
            <description>&lt;p&gt;A couple of years ago, I shared a &lt;a href=&quot;https:&#x2F;&#x2F;www.macblog.org&#x2F;post&#x2F;automatically-renaming-computers-from-a-google-sheet-with-jamf-pro&#x2F;&quot;&gt;method to set a Mac&#x27;s hostname via a Google
Sheet&lt;&#x2F;a&gt;. It&#x27;s worked well at my organization (as well as many others!) and
helped us keep our computer names consistent.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ve since moved to using &lt;a href=&quot;https:&#x2F;&#x2F;snipeitapp.com&#x2F;&quot;&gt;Snipe-IT&lt;&#x2F;a&gt; for asset management. Snipe is a
fantastic open-source tool that simplifies inventory tracking for our whole IT
shop. It also includes a robust API that allows us to integrate with external
systems and processes.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m now using the Snipe API to script our computer naming process. We treat
Snipe as the system of record for all inventory, and any change made to a
computer&#x27;s hostname in Snipe can be reflected on &lt;em&gt;both&lt;&#x2F;em&gt; the client system and in
Jamf Pro. Here&#x27;s how.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;why-python&quot;&gt;Why Python?&lt;&#x2F;h2&gt;
&lt;p&gt;For many years, Apple included Python 2.7 with the default installation of
macOS. With the 2019 release macOS Catalina, of &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;documentation&#x2F;macos-release-notes&#x2F;macos-catalina-10_15-release-notes#:~:text=Scripting%20Language%20Runtimes&quot;&gt;Apple began warning&lt;&#x2F;a&gt; that
&amp;quot;future versions of macOS will not include&amp;quot; runtimes for popular languages
including Python.&lt;&#x2F;p&gt;
&lt;p&gt;As of macOS Big Sur 11.1, the Python 2.7 runtime is still present. However,
&lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;doc&#x2F;sunset-python-2&#x2F;&quot;&gt;Python 2 is no longer maintained&lt;&#x2F;a&gt; and is not a good choice for forward
compatibility. Many administrators are moving their system administration
processes to shell scripts, which mostly &amp;quot;run anywhere&amp;quot; and don&#x27;t rely on any
runtime dependencies.&lt;&#x2F;p&gt;
&lt;p&gt;Despite the convenience and portablity of shell scripts, I maintain a number of
complex Python workflows that are arduous or ill-suited to port to shell.&lt;&#x2F;p&gt;
&lt;p&gt;This script interfaces with the Snipe API, which accepts and returns data in
JSON format. While tools and workarounds exist to work with JSON in shell
scripts, it&#x27;s frankly painful.&lt;&#x2F;p&gt;
&lt;p&gt;In my organization, I&#x27;ve taken to installing Python 3 to a known location using
Greg Neagle&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gregneagle&#x2F;relocatable-python&quot;&gt;Relocatable Python&lt;&#x2F;a&gt; tool. This allows me to use Python&#x27;s
native JSON tooling and interact with the Snipe API without hassle.&lt;&#x2F;p&gt;
&lt;p&gt;As such, this script is written in Python 3, and the shebang on line &lt;code&gt;1&lt;&#x2F;code&gt;
requires you to specify the path to the Python 3 runtime you&#x27;ve installed on the
client system.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-script&quot;&gt;The script&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve published this script is as a project on Github at
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;haircut&#x2F;jamf-snipe-rename&quot;&gt;haircut&#x2F;jamf-snipe-rename&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;set_computer_name.py&lt;&#x2F;code&gt; script is what you&#x27;re looking for.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-it-does&quot;&gt;What it does&lt;&#x2F;h3&gt;
&lt;p&gt;The script gathers the serial number of the computer upon which it&#x27;s running,
then queries your Snipe instance via the API to discover its current Asset Name
as set within that system. Then, it sets the hostname of the computer using the
Jamf binary&#x27;s &lt;code&gt;setComputerName&lt;&#x2F;code&gt; command.&lt;&#x2F;p&gt;
&lt;p&gt;As a fallback, if your Snipe instance does not have a record of the serial
number, the computer name will be set to that serial number. Setting the
hostname to the computer&#x27;s serial number is a reasonable alternative, as it lets
us easily identify machines that could not be renamed by the script, then fix
the source data within Snipe. And, the serial number is much better than a bunch
of Macs named &amp;quot;Sarah&#x27;s MacBook Pro!&amp;quot;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;setting-up-snipe&quot;&gt;Setting up Snipe&lt;&#x2F;h2&gt;
&lt;p&gt;I recommend setting up a dedicated local user with restricted access in Snipe to
handle all requests associated with this workflow. &lt;&#x2F;p&gt;
&lt;p&gt;The Snipe documentation explains &lt;a href=&quot;https:&#x2F;&#x2F;snipe-it.readme.io&#x2F;docs&#x2F;managing-users&quot;&gt;creating users&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;snipe-it.readme.io&#x2F;docs&#x2F;permissions&quot;&gt;setting
permissions&lt;&#x2F;a&gt;. I name my user something relevant like &amp;quot;Jamf Computer Naming
User&amp;quot; or similar.&lt;&#x2F;p&gt;
&lt;p&gt;Following the principle of least privilege, grant this local user &lt;em&gt;only&lt;&#x2F;em&gt; the
&lt;strong&gt;View&lt;&#x2F;strong&gt; permission under &lt;strong&gt;Assets&lt;&#x2F;strong&gt; and &lt;strong&gt;Create API Keys&lt;&#x2F;strong&gt; under &lt;strong&gt;Self&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Log in to Snipe as the new local user, and &lt;a href=&quot;https:&#x2F;&#x2F;snipe-it.readme.io&#x2F;reference#generating-api-tokens&quot;&gt;generate an API key&lt;&#x2F;a&gt;. This will
generate a (very long) &lt;a href=&quot;https:&#x2F;&#x2F;oauth.net&#x2F;2&#x2F;bearer-tokens&#x2F;&quot;&gt;bearer token&lt;&#x2F;a&gt; we&#x27;ll use to authenticate our script&#x27;s
requests.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;using-the-script&quot;&gt;Using the script&lt;&#x2F;h2&gt;
&lt;p&gt;Save a local copy of &lt;code&gt;set_computer_name.py&lt;&#x2F;code&gt; and configure the &lt;code&gt;SNIPE_SERVER&lt;&#x2F;code&gt;
value (near the top of the script) to point toward your Snipe installation. It&#x27;s
important to only provide the base URL here, as the script will add the full
path to the API endpoint we need.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;encrypting-script-parameters&quot;&gt;Encrypting script parameters&lt;&#x2F;h3&gt;
&lt;p&gt;Since we&#x27;re using the sensitive API key in our script to authenticate requests
to Snipe, it&#x27;s best not to hardcode that API key into the script. Nor is it wise
to pass the API key as a &lt;a href=&quot;https:&#x2F;&#x2F;docs.jamf.com&#x2F;10.26.0&#x2F;jamf-pro&#x2F;administrator-guide&#x2F;Scripts.html&quot;&gt;script parameter&lt;&#x2F;a&gt; in cleartext.&lt;&#x2F;p&gt;
&lt;p&gt;While the restricted permissions of the Snipe user limit the potential damage
from a leaked key, it&#x27;s still best to avoid the hazard by encrypting the user&#x27;s
API key and passing it as a script paramter.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m using Jamf&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jamf&#x2F;Encrypted-Script-Parameters&quot;&gt;Encrypted Script Parameters&lt;&#x2F;a&gt; utility to securely pass the API token from Jamf Pro to the client system. A full explanation of the utility is beyond this article&#x27;s scope, but briefly:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Follow Jamf&#x27;s README to encrypt your API key.&lt;&#x2F;li&gt;
&lt;li&gt;Note the ecrypted value, salt, and passphrase. Save them all in your
organization&#x27;s shared password manager :)&lt;&#x2F;li&gt;
&lt;li&gt;Paste the salt and passphrase in the &lt;code&gt;TOKEN_SALT&lt;&#x2F;code&gt; and &lt;code&gt;TOKEN_PASSPHRASE&lt;&#x2F;code&gt;
constants near the top of your copy of the script.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;adding-the-script-to-jamf-pro&quot;&gt;Adding the script to Jamf Pro&lt;&#x2F;h3&gt;
&lt;p&gt;Within your Jamf Pro instance, visit _Management Settings &amp;gt; Computer Management&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Scripts_, then add a new script. Name it something helpful, like &amp;quot;Set Computer
Name from Snipe&amp;quot; and then set the label for Parameter 4 to &amp;quot;Encrypted API Key.&amp;quot;
Paste in your (configured) copy of the script, then save.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;running-the-script-via-policy&quot;&gt;Running the script via policy&lt;&#x2F;h3&gt;
&lt;p&gt;Create a new policy, then configure the &amp;quot;Script&amp;quot; payload. Add the &amp;quot;Set Computer
Name from Snipe&amp;quot; script, then fill in the &amp;quot;Encrypted API Key&amp;quot; script parameter
with the encrypted API key you created earlier.&lt;&#x2F;p&gt;
&lt;p&gt;I recommend updating the computer&#x27;s inventory after renaming it, so that your
Jamf instance is updated with the new hostname as soon as possible. If your
deployment is large, consider omitting the inventory update to save on the
processing burden inherent in updating inventory.&lt;&#x2F;p&gt;
&lt;p&gt;How and when to run the script is largely dependent on your needs. I run the
renaming process early in our provisioning workflow using Jamf&#x27;s &amp;quot;Enrollment
Complete&amp;quot; trigger.&lt;&#x2F;p&gt;
&lt;p&gt;You could also create a secondary policy that runs on a routine basis – say,
weekly – to ensure Jamf data stays consistent with your inventory data in Snipe.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;running-the-script-outside-of-jamf-pro&quot;&gt;Running the script outside of Jamf Pro&lt;&#x2F;h3&gt;
&lt;p&gt;If your organization does not use Jamf Pro to manage Macs, you can still use
this script after a few modifications.&lt;&#x2F;p&gt;
&lt;p&gt;As written, the script uses the Jamf binary&#x27;s &lt;code&gt;setComputerName&lt;&#x2F;code&gt; command. This is
a convenient shorthand for running the following three commands:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; scutil&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;set&lt;&#x2F;span&gt; ComputerName &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;name&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; scutil&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;set&lt;&#x2F;span&gt; LocalHostName &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;name&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; scutil&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;set&lt;&#x2F;span&gt; HostName &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;name&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Within this &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;haircut&#x2F;jamf-snipe-rename&quot;&gt;project&#x27;s repository&lt;&#x2F;a&gt;, I&#x27;ve also shared
&lt;code&gt;set_computer_name_non_jamf.py&lt;&#x2F;code&gt; which substitues the Jamf binary call for the
three commands above. This non-Jamf script expects an &lt;em&gt;encrypted&lt;&#x2F;em&gt; Snipe API
token as its first positional parameter. If you&#x27;re using this workflow with a
management platform other than Jamf, I&#x27;ve left it as an exercise to the reader
on passing the parameter. Even if you&#x27;re not using Jamf, their &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jamf&#x2F;Encrypted-Script-Parameters&quot;&gt;encrypted script
parameters&lt;&#x2F;a&gt; project is platform agnostic.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;This transition from my previous &lt;a href=&quot;https:&#x2F;&#x2F;www.macblog.org&#x2F;post&#x2F;automatically-renaming-computers-from-a-google-sheet-with-jamf-pro&#x2F;&quot;&gt;Google Sheets-based workflow&lt;&#x2F;a&gt; has been a
big help in my organization. It allows us to treat our inventory system as our
source of truth for computer names, as it should be. Changes made in the
inventory system are reflected on the client system with no manual intervention.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Don&#x27;t disable accessibility options during Setup Assistant</title>
            <pubDate>Fri, 27 Nov 2020 00:00:00 +0000</pubDate>
            <link>https://macblog.org/dont-disable-accessibility/</link>
            <guid>https://macblog.org/dont-disable-accessibility/</guid>
            <description>&lt;p&gt;macOS Big Sur includes a new screen during Setup Assistant: Accessbility. It
prompts users to explore the accessibility features of macOS to adapt their
computer to their vision, motor, hearing, and cognitive needs.&lt;&#x2F;p&gt;
&lt;p&gt;You might want to disable or skip this setup screen. Don&#x27;t.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;


    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;macos-big-sur-accessibility-setup-assistant.4ea9a23bb3413974.webp&quot;width=&quot;720&quot; height=&quot;450&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;The first time you boot a Mac, it runs through a process known as Setup
Assistant. This lets your users configure some basic options before they begin
using the computer. With each new macOS release, Apple adds additional screens
to Setup Assistant. Some are of dubious utility. &lt;&#x2F;p&gt;
&lt;p&gt;Most popular MDMs allow you, as an administrator, to instruct Macs to skip
certain screens during Setup Assistant. In a corporate environment, your users
may not need to set up Apple Pay, or agree to the Terms and Conditions – so it
makes sense to simply skip these screens and streamline their first boot.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;mark&gt;&lt;strong&gt;If you support more humans than only yourself, how those humans
interact with their computer is not your decision.&lt;&#x2F;strong&gt;&lt;&#x2F;mark&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Even those who would not traditionally consider themselves in need of
accessibility features can still benefit. Putting these options front and center
allows everyone the opportunity to explore settings that might just make their
Mac a bit easier to use.&lt;&#x2F;p&gt;
&lt;p&gt;Kudos to Apple for making accessibility a &lt;em&gt;default&lt;&#x2F;em&gt; aspect of the macOS setup
process.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Sending Autopkg and JSSImporter Notifications to Google Hangouts Chat</title>
            <pubDate>Mon, 29 Apr 2019 00:00:00 +0000</pubDate>
            <link>https://macblog.org/autopkg-google-chat/</link>
            <guid>https://macblog.org/autopkg-google-chat/</guid>
            <description>&lt;p&gt;Although &lt;a href=&quot;https:&#x2F;&#x2F;slack.com&quot;&gt;Slack&lt;&#x2F;a&gt; has seemingly taken over the world
of workplace chat, my organization is a &lt;strong&gt;G Suite&lt;&#x2F;strong&gt; shop and we use 
&lt;a href=&quot;https:&#x2F;&#x2F;gsuite.google.com&#x2F;products&#x2F;chat&#x2F;&quot;&gt;Hangouts Chat&lt;&#x2F;a&gt; for a majority
of our internal communication. It&#x27;s included as a &amp;quot;core&amp;quot; G Suite app,
so why not use the product we already have, right?&lt;&#x2F;p&gt;
&lt;p&gt;I wanted a way to post notifications to Hangsouts Chat rooms when
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;autopkg&quot;&gt;autopkg&lt;&#x2F;a&gt; downloads new software, or makes
changes to our Jamf Pro server via
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jssimporter&#x2F;JSSImporter&quot;&gt;JSSImporter&lt;&#x2F;a&gt;. No solution existed.
Building on the excellent Slack-centric work of both &lt;a href=&quot;https:&#x2F;&#x2F;grahamrpugh.com&#x2F;2017&#x2F;12&#x2F;22&#x2F;slack-for-autopkg-jssimporter.html&quot;&gt;Graham R
Pugh&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;derflounder.wordpress.com&#x2F;2018&#x2F;07&#x2F;06&#x2F;automating-autopkg-runs-with-autopkg-conductor&#x2F;&quot;&gt;Rich
Trouton&lt;&#x2F;a&gt;,
I&#x27;ve made two different &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;autopkg&#x2F;wiki&#x2F;PreAndPostProcessorSupport&quot;&gt;autopkg
postprocessors&lt;&#x2F;a&gt;
to send autopkg notifications to Google Hangouts Chat.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h3 id=&quot;hangoutschatnotifier-simple-notifications&quot;&gt;&lt;code&gt;HangoutsChatNotifier&lt;&#x2F;code&gt; - simple notifications&lt;&#x2F;h3&gt;
&lt;p&gt;If you&#x27;d just like to know when your automated autopkg run downloads new
software, &lt;code&gt;HangoutsChatNotifier&lt;&#x2F;code&gt; will send a simple note to a Hangouts
Chat room.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;simple-notification.45fae1b8cbb3c35c.webp&quot;width=&quot;720&quot; height=&quot;103&quot;&gt;&lt;&#x2F;figure&gt;&lt;h3 id=&quot;hangoutschatjssnotifier-going-deeper-with-jssimporter&quot;&gt;&lt;code&gt;HangoutsChatJSSNotifier&lt;&#x2F;code&gt; - going deeper with &lt;code&gt;JSSImporter&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;If you&#x27;re using &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jssimporter&#x2F;JSSImporter&quot;&gt;JSSImporter&lt;&#x2F;a&gt; to
automate the process of adding the software autopkg downloads to your JSS,
&lt;code&gt;HangoutsChatJSSNotifier&lt;&#x2F;code&gt; will send more detailed messages to a Hangouts Chat
room.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;jss-notification.0c90047aaaf78c42.webp&quot;width=&quot;720&quot; height=&quot;276&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Both postprocessors leverage the existing data provided during an autopkg run to
send data to a Hangouts Chat &lt;a href=&quot;https:&#x2F;&#x2F;developers.google.com&#x2F;hangouts&#x2F;chat&#x2F;how-tos&#x2F;webhooks&quot;&gt;incoming
webhook&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To set these up on your own G Suite domain, you&#x27;ll need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gsuite.google.com&#x2F;products&#x2F;chat&#x2F;&quot;&gt;Hangouts Chat&lt;&#x2F;a&gt; enabled for your
users&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;support.google.com&#x2F;a&#x2F;answer&#x2F;7651360&quot;&gt;Bots enabled&lt;&#x2F;a&gt; for all OUs in
your domain. If Bots are not enabled across the domain, your notifications
&lt;a href=&quot;https:&#x2F;&#x2F;developers.google.com&#x2F;hangouts&#x2F;chat&#x2F;how-tos&#x2F;webhooks#limitations&quot;&gt;will
fail&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;My &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;haircut-recipes&quot;&gt;haircut-recipes&lt;&#x2F;a&gt; autopkg
recipes present in your autopkg repository, which includes these Hangouts Chat
postprocessors&lt;&#x2F;li&gt;
&lt;li&gt;An &lt;a href=&quot;https:&#x2F;&#x2F;developers.google.com&#x2F;hangouts&#x2F;chat&#x2F;how-tos&#x2F;webhooks&quot;&gt;incoming
webhook&lt;&#x2F;a&gt;
configured for the Hangouts Chat room you wish to notify&lt;&#x2F;li&gt;
&lt;li&gt;...and of course, a working autopkg setup&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;setting-up-a-webhook&quot;&gt;Setting up a webhook&lt;&#x2F;h2&gt;
&lt;p&gt;In Hangouts Chat, open the room you&#x27;d like to notify, then click the room&#x27;s name
near to top of the screen.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;configure-webhooks.ddad3877fa52258c.webp&quot;width=&quot;720&quot; height=&quot;819&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Click &lt;em&gt;Configure webhooks&lt;&#x2F;em&gt;. Enter a name for the incoming webhook – I just
use &amp;quot;autopkg&amp;quot; – then click &lt;em&gt;Save&lt;&#x2F;em&gt;. &lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;new-webhook.fbf874c9c246bdf8.webp&quot;width=&quot;720&quot; height=&quot;401&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;You&#x27;ll see a long URL displayed representing the API endpoint we can use to send
messages to this room. Copy that URL and save it for later.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;webhook-url.ef2c86267bc2c121.webp&quot;width=&quot;720&quot; height=&quot;280&quot;&gt;&lt;&#x2F;figure&gt;&lt;h2 id=&quot;which-postprocessor-should-i-use&quot;&gt;Which postprocessor should I use?&lt;&#x2F;h2&gt;
&lt;p&gt;Whichever you like! &lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;HangoutsChatNotifier&lt;&#x2F;code&gt; sends simple messages to inform you when your autopkg
workflow has downloaded new software. The quick notifications might be useful to
send to your desktop support team Hangouts Chat room, or your QA group.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re using &lt;code&gt;JSSImporter&lt;&#x2F;code&gt; as part of your autopkg workflow, you may find the
expanded detail provided by &lt;code&gt;HangoutsChatJSSNotifier&lt;&#x2F;code&gt; useful. Setting up
&lt;code&gt;JSSImporter&lt;&#x2F;code&gt; is beyond the scope of this article – but if you&#x27;re already there,
&lt;code&gt;HangoutsChatJSSNotifier&lt;&#x2F;code&gt; will help you send notifications to Hangouts Chat.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;running-the-postprocessor&quot;&gt;Running the postprocessor&lt;&#x2F;h2&gt;
&lt;p&gt;You have two options to include the Hangouts Chat postprocessors in your autopkg
runs.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;using-a-postprocessor-at-the-command-line&quot;&gt;Using a postprocessor at the command line&lt;&#x2F;h3&gt;
&lt;p&gt;The simplest method is to include the &lt;code&gt;--post&lt;&#x2F;code&gt; flag when running autopkg at the
command line. &lt;&#x2F;p&gt;
&lt;h4 id=&quot;for-hangoutschatnotifier&quot;&gt;...for &lt;code&gt;HangoutsChatNotifier&lt;&#x2F;code&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Specify the postprocessor name
&lt;code&gt;com.github.haircut.HangoutsChatNotifier&#x2F;HangoutsChatNotifier&lt;&#x2F;code&gt; and provide a
&lt;code&gt;--key&lt;&#x2F;code&gt; in the form &lt;code&gt;--key hangoutschat_webhook_url=&amp;quot;&amp;lt;incoming webhook url&amp;gt;&amp;quot;&lt;&#x2F;code&gt;.
Replace &lt;code&gt;&amp;lt;incoming webhook url&amp;gt;&lt;&#x2F;code&gt; with the URL you noted earlier after creating
an incoming webhook in your Hangouts Chat room.&lt;&#x2F;p&gt;
&lt;p&gt;A complete command might look like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;autopkg run MyRecipe.recipe \
--post &amp;quot;com.github.haircut.HangoutsChatNotifier&#x2F;HangoutsChatNotifier&amp;quot; \
--key hangoutschat_webhook_url=&amp;quot;https:&#x2F;&#x2F;chat.googleapis.com&#x2F;v1&#x2F;spaces&#x2F;XXX&#x2F;messages?key=XXX-XXX&amp;amp;token=XXX-XXX&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;for-hangoutschatjssnotifier&quot;&gt;...for &lt;code&gt;HangoutsChatJSSNotifier&lt;&#x2F;code&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Just like the simple notifier, add a &lt;code&gt;--post&lt;&#x2F;code&gt; flag to your autopkg run and
specify &lt;code&gt;com.github.haircut.HangoutsChatNotifier&#x2F;HangoutsChatNotifier&lt;&#x2F;code&gt;, and a
&lt;code&gt;--key hangoutschatjss_webhook_url=&amp;quot;&amp;lt;incoming webhook url&amp;gt;&amp;quot;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This example might look like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;autopkg run MyRecipe.recipe \
--post &amp;quot;com.github.haircut.HangoutsChatJSSNotifier&#x2F;HangoutsChatJSSNotifier&amp;quot; \
--key hangoutschatjss_webhook_url=&amp;quot;https:&#x2F;&#x2F;chat.googleapis.com&#x2F;v1&#x2F;spaces&#x2F;XXX&#x2F;messages?key=XXX-XXX&amp;amp;token=XXX-XXX&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;with-a-recipes-text-list&quot;&gt;...with a recipes text list&lt;&#x2F;h4&gt;
&lt;p&gt;If you use a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;autopkg&#x2F;wiki&#x2F;Running-Multiple-Recipes#recipe-lists&quot;&gt;text file list of multiple
recipes&lt;&#x2F;a&gt;
the postprocessors are compatible and will send a Hangouts Chat message after
each recipe runs.&lt;&#x2F;p&gt;
&lt;p&gt;For example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;autopkg run --recipe-list &#x2F;path&#x2F;to&#x2F;recipe_list.txt \
--post &amp;quot;com.github.haircut.HangoutsChatJSSNotifier&#x2F;HangoutsChatJSSNotifier&amp;quot; \
--key hangoutschatjss_webhook_url=&amp;quot;https:&#x2F;&#x2F;chat.googleapis.com&#x2F;v1&#x2F;spaces&#x2F;XXX&#x2F;messages?key=XXX-XXX&amp;amp;token=XXX-XXX&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;using-a-postprocessor-with-a-recipe-property-list&quot;&gt;Using a postprocessor with a recipe property list&lt;&#x2F;h3&gt;
&lt;p&gt;My preferred method of running multiple autopkg recipes is using a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;autopkg&#x2F;wiki&#x2F;Running-Multiple-Recipes#plist-recipe-lists&quot;&gt;property
list
(plist)&lt;&#x2F;a&gt;.
A plist recipe list lets you set up declarative and robust autopkg
configurations that would otherwise require a messy string of command line
arguments.&lt;&#x2F;p&gt;
&lt;p&gt;To include the Hangouts Chat postprocessor, add it as an array item under the
&lt;code&gt;postprocessors&lt;&#x2F;code&gt; key. Then, add your incoming webhook url as a string under a
&lt;code&gt;hangoutschat_webhook_url&lt;&#x2F;code&gt; key.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;!DOCTYPE plist PUBLIC &amp;quot;-&#x2F;&#x2F;Apple&#x2F;&#x2F;DTD PLIST 1.0&#x2F;&#x2F;EN&amp;quot; &amp;quot;http:&#x2F;&#x2F;www.apple.com&#x2F;DTDs&#x2F;PropertyList-1.0.dtd&amp;quot;&amp;gt;
&amp;lt;plist version=&amp;quot;1.0&amp;quot;&amp;gt;
&amp;lt;dict&amp;gt;
    &amp;lt;key&amp;gt;recipes&amp;lt;&#x2F;key&amp;gt;
    &amp;lt;array&amp;gt;
        &amp;lt;string&amp;gt;MyRecipe.recipe&amp;lt;&#x2F;string&amp;gt;
        &amp;lt;string&amp;gt;AnotherRecipe.recipe&amp;lt;&#x2F;string&amp;gt;
        &amp;lt;string&amp;gt;RadicalRecipe.recipe&amp;lt;&#x2F;string&amp;gt;
    &amp;lt;&#x2F;array&amp;gt;
    &amp;lt;key&amp;gt;hangoutschat_webhook_url&amp;lt;&#x2F;key&amp;gt;
    &amp;lt;string&amp;gt;https:&#x2F;&#x2F;chat.googleapis.com&#x2F;v1&#x2F;spaces&#x2F;XXX&#x2F;messages?key=XXX-XXX&amp;amp;amp;token=XXX-XXX&amp;lt;&#x2F;string&amp;gt;
    &amp;lt;key&amp;gt;postprocessors&amp;lt;&#x2F;key&amp;gt;
    &amp;lt;array&amp;gt;
        &amp;lt;string&amp;gt;com.github.haircut.HangoutsChatNotifier&#x2F;HangoutsChatNotifier&amp;lt;&#x2F;string&amp;gt;
    &amp;lt;&#x2F;array&amp;gt;
&amp;lt;&#x2F;dict&amp;gt;
&amp;lt;&#x2F;plist&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;aside class=&quot;alert&quot;&gt;&lt;p&gt;
    &lt;strong&gt;Important!&lt;&#x2F;strong&gt; Hangouts Chat incoming webhook URLs
    include an ampersand (&lt;code&gt;&amp;&lt;&#x2F;code&gt;) in the query parameters, which
    is an illegal character within an XML &lt;code&gt;&amp;lt;string&amp;gt;&lt;&#x2F;code&gt;
    element. You &lt;strong&gt;must&lt;&#x2F;strong&gt; replace the ampersand with its
    character entity &lt;code&gt;&amp;amp;amp;&lt;&#x2F;code&gt; when including the incoming
    webhook URL in a property list file – otherwise the postprocessor
    will fail to send a notification.
  &lt;&#x2F;p&gt;
  &lt;p&gt;
    e.g. &lt;code&gt;...&#x2F;XXX&#x2F;messages?key=XXX-XXX&amp;amp;amp;token=XXX-XXX&lt;&#x2F;code&gt;
&lt;&#x2F;aside&gt;
&lt;p&gt;Now you can run your recipe list and send Hangouts Chat notifications using a
much less cumbersome command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;autopkg run --recipe-list &#x2F;path&#x2F;to&#x2F;recipe_list.plist
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;using-both-hangoutschatnotifier-and-hangoutschatjssnotifier-together&quot;&gt;Using both &lt;code&gt;HangoutsChatNotifier&lt;&#x2F;code&gt; and &lt;code&gt;HangoutsChatJSSNotifier&lt;&#x2F;code&gt; together&lt;&#x2F;h2&gt;
&lt;p&gt;The namespace for each postprocessor is distinct, so you &lt;em&gt;can&lt;&#x2F;em&gt; use both
simultaneously during a single autopkg run. For example, you might like to send
your helpdesk a brief notification that new software is available using
&lt;code&gt;HangoutsChatNotifier&lt;&#x2F;code&gt;, and your engineering team managing Jamf Pro a more
detailed note showing the changes made to your JSS.&lt;&#x2F;p&gt;
&lt;p&gt;For this example, you&#x27;d create one incoming webhook in your &amp;quot;helpdesk&amp;quot; Hangouts
Chat room and set its URL as the &lt;code&gt;hangoutschat_webhook_url&lt;&#x2F;code&gt; key. Create a second
incoming webhook in your &amp;quot;Jamf Pro&amp;quot; Hangouts Chat room and set that URL as the
&lt;code&gt;hangoutschatjss_webhook_url&lt;&#x2F;code&gt;. Add both postprocessors to your autpkg run –
done!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;&#x2F;h2&gt;
&lt;p&gt;If you have need to customize the formatting or content of the Hangouts Chat
notifications, you can fork my postprocessors found at
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;haircut-recipes&#x2F;tree&#x2F;master&#x2F;PostProcessors&quot;&gt;autopkg&#x2F;haircut-recipes&#x2F;PostProcessor&lt;&#x2F;a&gt;.
Google has &lt;a href=&quot;https:&#x2F;&#x2F;developers.google.com&#x2F;hangouts&#x2F;chat&#x2F;reference&#x2F;message-formats&#x2F;&quot;&gt;great
documentation&lt;&#x2F;a&gt;
around their message formats.&lt;&#x2F;p&gt;
&lt;p&gt;Now go forth and notify your teams!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Helping Your Users Reset TCC Privacy Policy Decisions</title>
            <pubDate>Mon, 10 Sep 2018 00:00:00 +0000</pubDate>
            <link>https://macblog.org/reset-tcc-privacy/</link>
            <guid>https://macblog.org/reset-tcc-privacy/</guid>
            <description>&lt;p&gt;Taking a cue from iOS, Mac OS X 10.8 &amp;quot;Mountain Lion&amp;quot; introduced new systems to
help users manage access requests to potentially sensitive and private personal
information. When an app required access to a user&#x27;s Contacts, for instance, a
consent prompt appeared on screen asking the user to allow or disallow this
access.&lt;&#x2F;p&gt;
&lt;p&gt;Broadly, this system is known as &lt;code&gt;TCC&lt;&#x2F;code&gt; or &lt;em&gt;transparency, consent and control&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;With each version of macOS, Apple broadens the scope of privacy controls. The
upcoming release of macOS Mojave expands these controls such that many
previously-permitted interactions will require user consent. Prompts for consent
appear &lt;em&gt;only once&lt;&#x2F;em&gt; when an action first requires approval.&lt;&#x2F;p&gt;
&lt;p&gt;With more to manage and only a single prompt to allow or disallow access, it can
be opaque for users to understand the state of their system. Actions may fail
with no clear indication as to why; a decision to disallow access is easily
forgotten after many weeks or months.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s create an easy method to reset these decisions to allow for a fresh start.&lt;&#x2F;p&gt;
&lt;p&gt;&amp;lt;!- -more --&amp;gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;background&quot;&gt;Background&lt;&#x2F;h2&gt;
&lt;p&gt;Some brief background.&lt;&#x2F;p&gt;
&lt;p&gt;The origins of &lt;code&gt;TCC&lt;&#x2F;code&gt; are explained during the &amp;quot;&lt;em&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;videos&#x2F;play&#x2F;wwdc2016&#x2F;705&#x2F;?time=674&quot;&gt;How iOS Security Really Works&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&amp;quot; session from WWDC 2016.&lt;&#x2F;p&gt;
&lt;p&gt;During WWDC 2018 Apple hosted two sessions explaining the direction of their
privacy and security posture:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;videos&#x2F;play&#x2F;wwdc2018&#x2F;702&#x2F;&quot;&gt;Your Apps and the Future of macOS Security&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;videos&#x2F;play&#x2F;wwdc2018&#x2F;718&#x2F;&quot;&gt;Better Apps through Better Privacy&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Both sessions are insightful – check them out!&lt;&#x2F;p&gt;
&lt;p&gt;For a deeper dive into changes around Privacy controls in macOS Mojave, I highly
recommend Rich Mogull&#x27;s excellent article &lt;a href=&quot;https:&#x2F;&#x2F;tidbits.com&#x2F;2018&#x2F;09&#x2F;10&#x2F;mojaves-new-security-and-privacy-protections-face-usability-challenges&#x2F;&quot;&gt;Mojave’s New Security and Privacy
Protections Face Usability
Challenges&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-issue&quot;&gt;The Issue&lt;&#x2F;h2&gt;
&lt;p&gt;When a user decides to allow or disallow an interaction via a user consent 
prompt, that decision should appear in _System Preferences &amp;gt; Security &amp;amp; Privacy&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Privacy_. In my testing of macOS Mojave, I noticed that some allowed or
disallowed interactions – namely certain &amp;quot;automation&amp;quot; decisions – did not appear
in a user-configurable capacity in &lt;em&gt;System Preferences&lt;&#x2F;em&gt;. This effectively makes
affected decisions &amp;quot;permanent&amp;quot; unless a user is comfortable using a command line
utility.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Moreover, there is no GUI-based method to reset all privacy consent decisions
and &amp;quot;start from scratch.&amp;quot; Apple does, helpfully, provide a command line utility
to programmatically un-configure consent decisions so that interactions may
prompt for approval again.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;resetting-privacy-consent-decisions&quot;&gt;Resetting Privacy Consent Decisions&lt;&#x2F;h2&gt;
&lt;p&gt;macOS includes a utility called &lt;code&gt;tccutil&lt;&#x2F;code&gt;. This tool allows you to manage the
privacy database and reset decisions you&#x27;ve made regarding TCC-protected
services.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;tccutil&lt;&#x2F;code&gt; is a simple utility, supporting one command: &lt;code&gt;reset&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Resetting decisions made for a particular service is straightforward:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;tccutil reset &amp;lt;service name&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And here&#x27;s a list of known services:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Accessibility
AddressBook
All
AppleEvents
Calendar
Camera
Facebook
LinkedIn
Liverpool
Location
MediaLibrary
Microphone
Photos
PhotosAdd
PostEvent
Reminders
ShareKit
SinaWeibo
Siri
SystemPolicyAllFiles
SystemPolicyDeveloperFiles
SystemPolicySysAdminFiles
TencentWeibo
Twitter
Ubiquity
Willow
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;opragel&quot;&gt;@opragel&lt;&#x2F;a&gt; for extracting the list of
services.)&lt;&#x2F;p&gt;
&lt;p&gt;By way of example, the following command would reset all decisions you&#x27;ve made
regarding access to your calendar events. All apps that access your calendar
would then prompt you again for consent to access the data the next time you
launch them.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;tccutil reset Calendar
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In testing this utility I developed a quick script to automate the process of
resetting &lt;strong&gt;all&lt;&#x2F;strong&gt; the above-listed services. You can find &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;haircut&#x2F;aeb22c853b0ae4b483a76320ccc8c8e9&quot;&gt;tcc-reset.py on
GitHub&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I wanted to provide the same tool to my users as an easy-to-use troubleshooting
utility, so I&#x27;ve expanded it to make it available in Jamf Self Service. This
allows users to reset privacy consent decisions without needing to contact IT.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;self-service-privacy-consent-reset&quot;&gt;Self Service Privacy Consent Reset&lt;&#x2F;h2&gt;
&lt;p&gt;The goal here is to provide a mechanism for users to reset all their decisions
to allow or disallow apps to access protected services or files. We&#x27;ll
accomplish this with a script and a policy.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-script&quot;&gt;The Script&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;haircut&#x2F;4f30c1d5bb3eafbbc74d69f4ada2b378&quot;&gt;Self-Service-Reset-Privacy-Consent.py&lt;&#x2F;a&gt;
is an expansion of my original
&lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;haircut&#x2F;aeb22c853b0ae4b483a76320ccc8c8e9&quot;&gt;tcc-reset.py&lt;&#x2F;a&gt;
script. Running the script with no parameters will reset all privacy consent
decisions for the currently-logged-in user. Optionally, you may pass the word
&lt;code&gt;all&lt;&#x2F;code&gt; as Jamf Parameter 4 to reset privacy consent decisions for all users on a
system.&lt;&#x2F;p&gt;
&lt;p&gt;Add a new Script to your JSS. Give the script a suitable name, then paste in the
contents of
&lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;haircut&#x2F;4f30c1d5bb3eafbbc74d69f4ada2b378&quot;&gt;Self-Service-Reset-Privacy-Consent.py&lt;&#x2F;a&gt;
in the &amp;quot;Script&amp;quot; tab.&lt;&#x2F;p&gt;
&lt;p&gt;Jump to the &amp;quot;Options&amp;quot; tab. Leave the Priority set to &amp;quot;After&amp;quot;, then add a label
for Parameter 4: &amp;quot;Reset all users? (Type &#x27;all&#x27;)&amp;quot;&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;reset-tcc-script-parameters.d9f4a4fb022594ca.webp&quot;width=&quot;720&quot; height=&quot;487&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Save the Script. Next, we&#x27;ll set up a policy.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-policy&quot;&gt;The Policy&lt;&#x2F;h3&gt;
&lt;p&gt;Create a new Policy. Give it an appropriate name; I&#x27;ve chosen &amp;quot;Reset Privacy
Consent Decisions&amp;quot; to be consistent with the language Apple uses to describe TCC
features. Leave all Triggers un-checked; this policy will only be available via
Self Service. I set the Execution Frequency to &amp;quot;Ongoing&amp;quot; to ensure users have
access to the utility whenever they need.&lt;&#x2F;p&gt;
&lt;p&gt;Add your &lt;code&gt;Self-Service-Reset-Privacy-Consent.py&lt;&#x2F;code&gt; script to the Scripts payload
of your policy. As mentioned, you can optionally set Parameter 4 to &lt;code&gt;all&lt;&#x2F;code&gt; so
that privacy consent is reset for all users on a system. With single-user
systems this shouldn&#x27;t be necessary. By default the script resets consent
decisions for the currently-logged-in user. However, I&#x27;ve included the option
for those managing labs or other multi-user systems.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;policy-script.0b3db74a7b853fd3.webp&quot;width=&quot;720&quot; height=&quot;400&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Set an appropriate policy scope in the &amp;quot;Scope&amp;quot; tab. I use the &amp;quot;All Managed
Clients&amp;quot; computer group so the utility is available to all users.&lt;&#x2F;p&gt;
&lt;p&gt;Next, open the &amp;quot;Self Service&amp;quot; tab and check the box to &amp;quot;Make policy available in
Self Service.&amp;quot; I set the &amp;quot;Button Name Before Initiation&amp;quot; and &amp;quot;Button Name After
Initiation&amp;quot; to &amp;quot;Reset&amp;quot; so the button always displays the same text.&lt;&#x2F;p&gt;
&lt;p&gt;I check &amp;quot;Ensure that users view the description&amp;quot; and set the following text as
the description:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Resets your Privacy Consent decisions.&lt;&#x2F;p&gt;
&lt;p&gt;If you experience application behavior where certain features like Camera, 
Microphone, or Disk Access do not work as expected, resetting your Privacy 
Consent decisions will allow applications to prompt you for consent to access
these features.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Finally, I upload an icon to spruce up the presentation of the policy when
viewed in Self Service. You&#x27;re welcome to &lt;a href=&quot;&#x2F;resources&#x2F;reset-tcc&#x2F;SS-Reset-Privacy-Consent-Decisions.png&quot;&gt;download the
icon&lt;&#x2F;a&gt; for use in
your organization.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;SS-Reset-Privacy.2b53d18795101662.webp&quot;width=&quot;720&quot; height=&quot;808&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;And there we go! Our users can now reset or &amp;quot;undo&amp;quot; all the decisions they&#x27;ve
made regarding privacy consent. Apps will once again prompt for consent when
initiating a sensitive interaction.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;&#x2F;h2&gt;
&lt;p&gt;As the release date of macOS Mojave approaches, I&#x27;m hopeful Apple will provide
more detailed documentation around these features.  While I applaud their
apparent goal of increased visibility into access of potentially-sensitive user
data, I&#x27;m concerned this current implementation will only confuse users who may
not understand the effects of allowing or disallowing certain interactions.&lt;&#x2F;p&gt;
&lt;p&gt;We shouldn&#x27;t have to engineer scripts to help users manage Privacy features. If
Apple wants users to embrace these features, they must understand them and their
implications on how their Mac functions. Explicit and concise controls provided
in the GUI should display &lt;em&gt;all&lt;&#x2F;em&gt; user decisions and allow for seamless
administration. Resetting these decisions shouldn&#x27;t be relegated to a command
line tool. Users need clarity. I mean... &amp;quot;transparency&amp;quot; is right there in the
name &amp;quot;Transparency, Consent and Control&amp;quot;, right?&lt;&#x2F;p&gt;
&lt;p&gt;For more information, please join the &lt;code&gt;#tcc&lt;&#x2F;code&gt; channel on the &lt;a href=&quot;https:&#x2F;&#x2F;macadmins.herokuapp.com&#x2F;&quot;&gt;MacAdmins Slack
Team&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Signing Configuration Profiles</title>
            <pubDate>Fri, 03 Aug 2018 00:00:00 +0000</pubDate>
            <link>https://macblog.org/sign-configuration-profiles/</link>
            <guid>https://macblog.org/sign-configuration-profiles/</guid>
            <description>&lt;p&gt;Apple has made it clear; MDM is the future.&lt;&#x2F;p&gt;
&lt;p&gt;As the preferred method of device management moves more and more to
Configuration Profiles, administrators must turn their focus toward digital
security.&lt;&#x2F;p&gt;
&lt;p&gt;Signing configuration profiles provides assurance of their origin, and an
assertion their contents have not been modified in transit.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;A profile signed with a trusted signing certificate appears in System
Preferences &amp;gt; Profiles with a green &amp;quot;Verified&amp;quot; label.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-verified.2ffcc048b38a9cf6.webp&quot;width=&quot;720&quot; height=&quot;282&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;If the profile is signed by a certificate that was not issued by a certificate
authority trusted by the operating system – as is the case with a self-signed
certificate – the profile appears with a red &amp;quot;Unverified&amp;quot; label.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-unverified.3d84929a9ad06848.webp&quot;width=&quot;720&quot; height=&quot;282&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;If the profile is not signed at all, it appears with a red &amp;quot;Unsigned&amp;quot; label.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-unsigned.dd2b1b1d00b6ca3b.webp&quot;width=&quot;720&quot; height=&quot;282&quot;&gt;&lt;&#x2F;figure&gt;&lt;aside&gt;
    &lt;p&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; While this guide focuses on signing Configuration Profiles for use with Jamf Pro, the concepts apply generally.&lt;&#x2F;p&gt;
&lt;&#x2F;aside&gt;
&lt;p&gt;Jamf Pro includes a built-in certificate authority. It&#x27;s a key piece of
functionality that allows Jamf Pro to generate digital certificates to
facilitate secure, trusted communication between your clients and your Jamf Pro
server.&lt;&#x2F;p&gt;
&lt;p&gt;During setup, the Jamf Pro built-in certificate authority generates a signing
certificate for both macOS and iOS. This signing certificate is used to
digitally sign configuration profiles deployed by your Jamf Pro server. Each
enrolled client will have the &amp;quot;JSS Built-in Signing Certificate&amp;quot; installed to
its System keychain. This certificate is issued by your Jamf Pro server&#x27;s
built-in certificate authority. Since your clients trust your Jamf Pro server&#x27;s
root certificate, the signing certificate is also trusted; the chain is
complete.&lt;&#x2F;p&gt;
&lt;p&gt;Profiles created using the Jamf Pro configuration profile interface are
automatically signed using the &amp;quot;JSS Built-in Signing Certificate&amp;quot; created during
installation of your Jamf Pro server.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-signed-inset.dcb6e69405d59798.webp&quot;width=&quot;720&quot; height=&quot;493&quot;&gt;&lt;&#x2F;figure&gt;&lt;h2 id=&quot;why-sign-your-profiles&quot;&gt;Why Sign Your Profiles?&lt;&#x2F;h2&gt;
&lt;p&gt;If you only use Jamf Pro&#x27;s configuration profile creation interface, Jamf Pro
handles all the signing for you.&lt;&#x2F;p&gt;
&lt;p&gt;However, if you create custom profiles &amp;quot;from scratch,&amp;quot; then upload them to Jamf
Pro for deployment, you should sign them.&lt;&#x2F;p&gt;
&lt;p&gt;When you upload an unsigned configuration profile, the Jamf Pro server converts
it into a format you can edit using their interface. Unfortunately, this
conversion process often results in a finished profile that incorrectly manages
the settings you specified, or even manages settings that were not included in
the original source profile at all.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s one example. Uploading a profile that manages the domain
&lt;code&gt;com.apple.security.firewall&lt;&#x2F;code&gt; and sets the key &lt;code&gt;EnableFirewall&lt;&#x2F;code&gt; to &lt;code&gt;true&lt;&#x2F;code&gt;
results in a Jamf-converted profile that sets that key to &lt;code&gt;false&lt;&#x2F;code&gt; – the exact
opposite of what you intended! This particular defect is filed as Product Issue
PI-004130, but no resolution is currently in place.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;mark&gt;Signing your custom configuration profiles before uploading them prevents
the Jamf Pro server from manipulating their contents.&lt;&#x2F;mark&gt; This ensures your
profile is delivered unaltered to your clients.&lt;&#x2F;p&gt;
&lt;p&gt;When you upload a signed configuration profile, Jamf Pro warns you that the
profile is read-only and offers you the opportunity to remove the digital
signature.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-read-only.5af14d61ec3c4a2a.webp&quot;width=&quot;720&quot; height=&quot;55&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Don&#x27;t click the &amp;quot;Remove Signature&amp;quot; button. You won&#x27;t be able to edit the profile
within the Jamf Pro web interface – but neither can Jamf! The profile is
delivered to client systems unmodified.&lt;&#x2F;p&gt;
&lt;p&gt;If you do need to make edits to the profile, you&#x27;ll need to do so in a text
editor, re-sign the profile, then upload it again to your Jamf Pro server. It&#x27;s
a minor inconvenience, but ensures you don&#x27;t accidentally manage unintended
preferences.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;signing-profiles-for-trust-by-any-client&quot;&gt;Signing Profiles for Trust by Any Client&lt;&#x2F;h2&gt;
&lt;p&gt;With an Apple Developer certificate you can easily sign profiles (and other
objects) to provide assurance of origin. So long as you abide by the terms of
the Apple Developer Program, your profiles will be trusted on any macOS or iOS
device.&lt;&#x2F;p&gt;
&lt;p&gt;If you manage more than a handful of devices, you should &lt;strong&gt;really&lt;&#x2F;strong&gt; sign up for
the &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;programs&#x2F;&quot;&gt;Apple Developer Program&lt;&#x2F;a&gt;. The
Developer Program will provide you with a number of certificates issued by Apple
that are trusted on all macOS and iOS devices. This is useful for signing your
Jamf Pro QuickAdd package, signing other installer packages, and signing
configuration profiles. When these objects are signed you avoid the hurdles of
your packages being quarantined by Gatekeeper, or your profiles appearing as
&amp;quot;unverified.&amp;quot;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Sign in to the &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;account&quot;&gt;Apple Developer Program account
portal&lt;&#x2F;a&gt;. &lt;&#x2F;li&gt;
&lt;li&gt;Click &amp;quot;Certificates, IDs &amp;amp; Profiles&amp;quot;.&lt;&#x2F;li&gt;
&lt;li&gt;Click the dropdown menu near the upper left labeled &amp;quot;iOS, tvOS, watchOS&amp;quot; then
select &amp;quot;macOS&amp;quot;.&lt;&#x2F;li&gt;
&lt;li&gt;Click &amp;quot;All&amp;quot; under the &amp;quot;Certificates&amp;quot; heading, then click the plus button near
the upper right.&lt;&#x2F;li&gt;
&lt;li&gt;When prompted &amp;quot;What type of certificate do you need?&amp;quot;, select &amp;quot;Developer ID&amp;quot;,
click Continue, then select &amp;quot;Developer ID Installer.&amp;quot; While this type of
certificate may be the best choice, other certificates will also work. See
the note below for details.&lt;&#x2F;li&gt;
&lt;li&gt;Follow Apple&#x27;s on-screen instructions to generate a Certificate Signing
Request (CSR) and install the resultant certificate in your login keychain.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;With your certificate installed in your keychain, use the &lt;code&gt;security&lt;&#x2F;code&gt; tool to
sign a profile.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;security cms -S -N &amp;quot;&amp;lt;common name of certificate&amp;gt;&amp;quot; -i &amp;lt;input path to unsigned profile&amp;gt; -o &amp;lt;output path for signed profile&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A complete example might look like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;security cms -S -N &amp;quot;Mac Developer: Matthew Warren (XXXXXXXXXX)&amp;quot; -i ~&#x2F;Documents&#x2F;Unsigned.mobileconfig -o ~&#x2F;Documents&#x2F;Signed.mobileconfig
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When signing a Profile, you&#x27;ll be asked to unlock your login keychain. Enter
your login keychain password and click &amp;quot;Allow&amp;quot;.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-keychain-unlock.b447b40bd982b4f7.webp&quot;width=&quot;720&quot; height=&quot;335&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;You could also click &amp;quot;Always Allow&amp;quot; to avoid future prompts when signing
Profiles, but I tend to err on the side of security and just enter my password
each time.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;note-what-type-of-certificate-should-you-choose&quot;&gt;&lt;em&gt;Note: What type of certificate should you choose?&lt;&#x2F;em&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Apple provides a number of different certificate types. While I recommend the
&amp;quot;Developer ID Installer,&amp;quot; most (if not all) of the options Apple provides will
produce a certificate with the correct Key Usage attributes required to sign a
Configuration Profile.&lt;&#x2F;p&gt;
&lt;p&gt;The choice is largely aesthetic, since the Common Name of the certificate will
be visible to end users when viewing a Configuration Profile in the &lt;em&gt;Profiles&lt;&#x2F;em&gt;
pane within System Preferences.&lt;&#x2F;p&gt;
&lt;p&gt;The visible name listed beside the &amp;quot;Signed&amp;quot; heading generally follows the
pattern &lt;code&gt;&amp;lt;Certificate Type&amp;gt;: &amp;lt;Company or Individual Name&amp;gt; (&amp;lt;Team ID&amp;gt;)&lt;&#x2F;code&gt;. For
example:&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-devid.f65ceca7631b8f56.webp&quot;width=&quot;720&quot; height=&quot;120&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Another consideration is the Apple ID used to create the certificate. If you&#x27;re
signed in using the &amp;quot;parent&amp;quot; Apple ID of your organization&#x27;s Apple Developer
Account you&#x27;ll have the most options available, including the recommended
&amp;quot;Developer ID Installer&amp;quot; option. Generated certificates will include your
&lt;strong&gt;company or organization&#x27;s&lt;&#x2F;strong&gt; name in their Common Name. If you&#x27;re using an
Apple ID that has been granted delegated access to your organization&#x27;s Developer
Program, generated certificates will instead have &lt;strong&gt;your name&lt;&#x2F;strong&gt; included in the
Common Name.&lt;&#x2F;p&gt;
&lt;p&gt;Again, most if not all of the Apple&#x27;s options are suitable for signing
Configuration Profiles – just keep in mind the differences in presentation.&lt;&#x2F;p&gt;
&lt;p&gt;Next, let&#x27;s take a look at an alternative way to generate a signing certificate
we can use to sign Configuration Profiles &lt;em&gt;without&lt;&#x2F;em&gt; having access to Apple&#x27;s
certificate portal.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;signing-profiles-for-trust-only-by-jamf-enrolled-clients&quot;&gt;Signing Profiles for Trust Only by Jamf-enrolled Clients&lt;&#x2F;h2&gt;
&lt;p&gt;If you do not (and&#x2F;or &lt;em&gt;cannot&lt;&#x2F;em&gt;) participate in the Apple Developer Program, you
can use Jamf Pro to generate a certificate to sign your custom configuration
profiles. Profiles signed with a Jamf Pro-generated certificate will be trusted
&lt;strong&gt;only&lt;&#x2F;strong&gt; by clients enrolled to your Jamf Pro instance; however, this is likely
sufficient for most use cases.&lt;&#x2F;p&gt;
&lt;p&gt;Jamf Pro&#x27;s Built-in CA allows you to generate arbitrary certificates of the
following types:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Client Certificate&lt;&#x2F;li&gt;
&lt;li&gt;Web Server Certificate&lt;&#x2F;li&gt;
&lt;li&gt;SSO Certificate&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;During setup, the Jamf Pro built-in certificate authority generates a signing
certificate for both macOS and iOS. This signing certificate is used to
digitally sign configuration profiles deployed by your Jamf Pro server. Each
enrolled client will have the &amp;quot;JSS Built-in Signing Certificate&amp;quot; installed to
its System keychain. This certificate is issued by your Jamf Pro server&#x27;s
built-in certificate authority. Since your clients trust your Jamf Pro server&#x27;s
root certificate, the signing certificate is also trusted; the chain is
complete.&lt;&#x2F;p&gt;
&lt;p&gt;While it might seem tempting to re-use these certificates to sign your
custom-crafted profiles, Jamf Pro does not present a GUI option to download
them. This is a good thing!&lt;&#x2F;p&gt;
&lt;p&gt;If you &lt;em&gt;could&lt;&#x2F;em&gt; download and use the private key of your &amp;quot;JSS Built-in Signing
Certificate&amp;quot; to sign arbitrary profiles it would present a larger security risk.
If that key was ever compromised, it would affect every item signed by that
certificate. This includes devices&#x27; MDM enrollment profiles. You&#x27;d have to
regenerate your Jamf Pro built-in certificate authority and re-enroll every
client. Let&#x27;s avoid that!&lt;&#x2F;p&gt;
&lt;p&gt;Instead, we&#x27;ll generate our own certificate for signing configuration profiles.
First we&#x27;ll need to generate a Certificate Signing Request (CSR) on your Mac.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;create-a-csr-on-your-mac&quot;&gt;Create A CSR on Your Mac&lt;&#x2F;h3&gt;
&lt;p&gt;Perform these steps on a client enrolled to your Jamf Pro server so that the
certificate trust chain is complete.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Open the Keychain Access app.&lt;&#x2F;li&gt;
&lt;li&gt;Click the &lt;strong&gt;Keychain Access&lt;&#x2F;strong&gt; menu in the menu bar, hover over &lt;em&gt;Certificate
Assistant&lt;&#x2F;em&gt;, then select &lt;em&gt;Request a Certificate From a Certificate
Authority...&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;In the &lt;strong&gt;Certificate Assistant&lt;&#x2F;strong&gt; window that appears enter an email address
for your organization (I use a generic one) and a suitable Common Name, such
as &amp;quot;&lt;name of your organization&gt; Profile Signing Certificate&amp;quot; or similar. For
the &amp;quot;Request is:&amp;quot; option, select &amp;quot;Saved to disk&amp;quot; then click &lt;em&gt;Continue&lt;&#x2F;em&gt;.



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-certificate-assistant1.7e021997f16719a5.webp&quot;width=&quot;720&quot; height=&quot;512&quot;&gt;&lt;&#x2F;figure&gt;&lt;&#x2F;li&gt;
&lt;li&gt;When prompted, choose a location to save the CSR.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;upload-the-csr-to-your-jamf-pro-server&quot;&gt;Upload the CSR to your Jamf Pro Server&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Open the CSR you saved to disk during the previous steps in a plain text
editor and copy the entire contents to your clipboard.



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-csr-text.e163a0e3db2e9d17.webp&quot;width=&quot;720&quot; height=&quot;495&quot;&gt;&lt;&#x2F;figure&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Sign in to your Jamf Pro server and navigate to _Settings &amp;gt; Global Management
&lt;blockquote&gt;
&lt;p&gt;PKI Certificates_.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Click the &amp;quot;Management Certificate Template&amp;quot; tab near the top of the screen.&lt;&#x2F;li&gt;
&lt;li&gt;Click the &amp;quot;Create Certificate from CSR&amp;quot; button.&lt;&#x2F;li&gt;
&lt;li&gt;In the modal window, paste the contents of your CSR, then select a
&lt;em&gt;Certificate Type&lt;&#x2F;em&gt; of &amp;quot;Web Server Certificate&amp;quot; and click the &amp;quot;Create&amp;quot; button. 



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-paste-csr.fd5b287e09ce4a15.webp&quot;width=&quot;720&quot; height=&quot;932&quot;&gt;&lt;&#x2F;figure&gt;&lt;&#x2F;li&gt;
&lt;li&gt;After clicking &amp;quot;Create&amp;quot;, a file with a name in the format of &lt;code&gt;C=US,CN=&amp;lt;common name you chose&amp;gt;,E=&amp;lt;email you specified&amp;gt;.pem&lt;&#x2F;code&gt; will automatically download. In my
experience, the Jamf Pro GUI freezes at this point; simply click any link on the
page to navigate away – we&#x27;ve already got what we came for!&lt;&#x2F;li&gt;
&lt;li&gt;Open the downloaded &lt;code&gt;.pem&lt;&#x2F;code&gt; file. When prompted, choose to install the
certificate in your login keychain. 



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-where-install.9f90bfa1f13c2772.webp&quot;width=&quot;720&quot; height=&quot;464&quot;&gt;&lt;&#x2F;figure&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The certificate is now installed to your login keychain and ready to reference
by name when signing Configuration Profiles.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;security cms -S -N &amp;quot;&amp;lt;common name of certificate you just installed&amp;gt;&amp;quot; -i &amp;lt;input path to unsigned profile&amp;gt; -o &amp;lt;output path for signed profile&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When prompted, enter unlock your login keychain to finish signing the profile.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, let&#x27;s look at a third way to generate a certificate suitable for
signing Profiles.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;signing-a-profile-the-quick-and-dirty-but-not-best-way&quot;&gt;Signing a Profile – The Quick-and-Dirty, But Not Best Way&lt;&#x2F;h2&gt;
&lt;p&gt;If for some reason you neither participate in the Apple Developer Program, nor
create a certificate within your Jamf Pro server, you do still have an option.
We can create a Self Signed Certificate suitable for signing profiles. The
resulting signed profile will not be trusted once deployed to a client system,
but its signature &lt;em&gt;will&lt;&#x2F;em&gt; prevent Jamf Pro from modifying its contents. Once
installed, if the profile is viewed in the Profiles pane of System Preferences,
it will display the red &amp;quot;Unverified&amp;quot; notice.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;create-a-self-signed-code-signing-certificate&quot;&gt;Create a Self Signed Code Signing Certificate&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Open the Keychain Access app.&lt;&#x2F;li&gt;
&lt;li&gt;Click the &lt;strong&gt;Keychain Access&lt;&#x2F;strong&gt; menu in the menu bar, hover over &lt;em&gt;Certificate
Assistant&lt;&#x2F;em&gt;, then select &lt;em&gt;Create a Certificate...&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;In the &lt;strong&gt;Certificate Assistant&lt;&#x2F;strong&gt; window that appears, enter a sensible name.
Select the &lt;em&gt;Identity Type&lt;&#x2F;em&gt; of &amp;quot;Self Signed Root&amp;quot; and &lt;em&gt;Certificate Type&lt;&#x2F;em&gt; of &amp;quot;Code
Signing&amp;quot;. Check the box beside &amp;quot;Let me override defaults&amp;quot;. 



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-create-cert-1.9a5ca98d5028fb64.webp&quot;width=&quot;720&quot; height=&quot;512&quot;&gt;&lt;&#x2F;figure&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Leave the &lt;em&gt;Serial Number&lt;&#x2F;em&gt; set to &amp;quot;1&amp;quot;, and increase the &lt;em&gt;Validity Period&lt;&#x2F;em&gt; to
something like &amp;quot;1096&amp;quot; days (3 years) for convenience.



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-create-cert-2.e1b6b3ac7c042b21.webp&quot;width=&quot;720&quot; height=&quot;512&quot;&gt;&lt;&#x2F;figure&gt;&lt;&#x2F;li&gt;
&lt;li&gt;On the next screen, enter relevant values for your organization. Make sure to
specify a descriptive &lt;em&gt;Common Name&lt;&#x2F;em&gt; for the certificate, as this will be
viewable when inspecting Configuration Profiles signed by this certificate.



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-create-cert-3.07d97f39e8db8a28.webp&quot;width=&quot;720&quot; height=&quot;512&quot;&gt;&lt;&#x2F;figure&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Leave the default values of &amp;quot;2048 bits&amp;quot; for &lt;em&gt;Key Size&lt;&#x2F;em&gt; and &amp;quot;RSA&amp;quot; for
&lt;em&gt;Algorithm&lt;&#x2F;em&gt;.



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-create-cert-4.014a55889b7c5a5c.webp&quot;width=&quot;720&quot; height=&quot;512&quot;&gt;&lt;&#x2F;figure&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Ensure &amp;quot;Signature&amp;quot; is selected for the &lt;em&gt;Key Usage Extension&lt;&#x2F;em&gt;.



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-create-cert-5.133262c138855aa3.webp&quot;width=&quot;720&quot; height=&quot;512&quot;&gt;&lt;&#x2F;figure&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Ensure &amp;quot;Code Signing&amp;quot; is selected for the &lt;em&gt;Extended Key Usage Extension&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;


    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-create-cert-6.5871b2f25f2964bd.webp&quot;width=&quot;720&quot; height=&quot;512&quot;&gt;&lt;&#x2F;figure&gt;&lt;&#x2F;li&gt;
&lt;li&gt;On the following screens, leave &amp;quot;Include Basic Contraints Extension&amp;quot; and
&amp;quot;Include Subject Alternate Name Extension&amp;quot; unchecked.&lt;&#x2F;li&gt;
&lt;li&gt;When prompted, ensure the certificate is set to be stored in your &amp;quot;login&amp;quot;
keychain.



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-create-cert-9.7c6eff1d1543c9f3.webp&quot;width=&quot;720&quot; height=&quot;512&quot;&gt;&lt;&#x2F;figure&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;After clicking &amp;quot;Done&amp;quot; you should see the new certificate listed in your login
keychain.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;signing-profiles-in-keychain.f40143a3ea9cf8cd.webp&quot;width=&quot;720&quot; height=&quot;458&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;You can now sign Configuration Profiles using the &lt;code&gt;security&lt;&#x2F;code&gt; binary by
referencing the common name of your new self-signed certificate.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;security cms -S -N &amp;quot;&amp;lt;common name of self-signed certificate&amp;gt;&amp;quot; -i &amp;lt;input path to unsigned profile&amp;gt; -o &amp;lt;output path for signed profile&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Again, keep in mind that Configuration Profiles signed with a self-signed
certificate will be listed as &amp;quot;Unverified&amp;quot; in System Preferences. While this
won&#x27;t affect the ability to install the profile, it could be a security concern
depending on your environment. &amp;quot;Unverified&amp;quot; profiles assure that their contents
have not been modified in transit, but provided no assurance of origin.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gui-tool&quot;&gt;GUI Tool&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;d prefer a graphical tool to manage signing Configuration Profiles (or
packages), check out &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;JeremyAgost&#x2F;Hancock&quot;&gt;Hancock&lt;&#x2F;a&gt;. You&#x27;ll
still need to correctly generate a signing certificate using a method outlined
above, but Hancock can save you some keystrokes if you prefer an app!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ve covered three different methods – in order of preference – to generate a
signing certificate we can use to sign Configuration Profiles.&lt;&#x2F;p&gt;
&lt;p&gt;Signing a Configuration Profile prevents an MDM system, like Jamf Pro, from
tampering with its contents; your hand-crafted profile is delivered to clients
unaltered. If your signing certificate is trusted by the client system, it also
provides verification that the Configuration Profile was created and delivered
by a trusted party.&lt;&#x2F;p&gt;
&lt;p&gt;Regardless of how you generate your signing certificate, remember the command:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;security cms -S -N &amp;quot;&amp;lt;common name of signing certificate&amp;gt;&amp;quot; -i &amp;lt;input path to unsigned profile&amp;gt; -o &amp;lt;output path for signed profile&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s it! Don&#x27;t hesitate to reach out if you have any questions, feedback, or
corrections.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Express Setup, Location Services, Time Zone, and High Sierra</title>
            <pubDate>Sun, 04 Feb 2018 00:00:00 +0000</pubDate>
            <link>https://macblog.org/express-setup-high-sierra/</link>
            <guid>https://macblog.org/express-setup-high-sierra/</guid>
            <description>&lt;p&gt;I recently ran into a snag with our Device Enrollment Program (DEP) workflow.
Users were not being prompted to enable Location Services to automatically set the time zone, nor was the explicit Time Zone selection screen displayed during Setup Assistant.&lt;&#x2F;p&gt;
&lt;p&gt;The result was that devices wound up configured with the default Cupertino, CA
location, and a Pacific time zone.
We&#x27;re on the East coast – so we&#x27;d have to script a change of settings, or worse, have the user manually modify them.&lt;&#x2F;p&gt;
&lt;p&gt;As it turns out, this is an effect of the new &amp;quot;Express Setup&amp;quot; option in macOS High Sierra.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;skipping-setup-assistant-screens&quot;&gt;Skipping Setup Assistant screens&lt;&#x2F;h2&gt;
&lt;aside&gt;
    &lt;p&gt;&lt;strong&gt;Update for macOS Monterey&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As of macOS Monterey, &lt;em&gt;Express Setup&lt;&#x2F;em&gt; will only display if the user is logged in to an Apple ID and has previously configured Siri, Location Services, and App Analytics settings while signed in to that Apple ID.&lt;&#x2F;p&gt;

&lt;&#x2F;aside&gt;
&lt;p&gt;When first booted, if a Mac has network connectivity it contacts Apple to see if it should receive an enrollment configuration from an MDM solution.&lt;&#x2F;p&gt;
&lt;p&gt;In most MDMs you can configure devices to skip any of a handful of Setup Assistant screens.
In Jamf Pro, the configuration looks like this:&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;prestage-skip-bad.2b98fbac4f0b7ab1.webp&quot;width=&quot;720&quot; height=&quot;598&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;If a screen is skipped, the default options for settings on the screen are configured.
In the case of Location Services, the default option is to &lt;strong&gt;disable&lt;&#x2F;strong&gt; Location Services.&lt;&#x2F;p&gt;
&lt;p&gt;In macOS 10.13.3 and below, running &lt;code&gt;sudo &#x2F;usr&#x2F;libexec&#x2F;mdmclient dep nag&lt;&#x2F;code&gt; will output the device&#x27;s &amp;quot;activation record.&amp;quot;&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Activation record: {
    AllowPairing = 0;
    AnchorCertificates =     (
    );
    AwaitDeviceConfigured = 1;
    ConfigurationURL = &amp;quot;&amp;lt;enrollment url&amp;gt;&amp;quot;;
    IsMDMUnremovable = 0;
    IsMandatory = 1;
    IsSupervised = 1;
    OrganizationAddress = &amp;quot;&amp;lt;organization address&amp;gt;&amp;quot;;
    OrganizationAddressLine1 = &amp;quot;&amp;lt;organization address&amp;gt;&amp;quot;;
    OrganizationCity = &amp;lt;organization city&amp;gt;;
    OrganizationCountry = &amp;lt;organization country&amp;gt;;
    OrganizationDepartment = &amp;quot;&amp;lt;organization department&amp;gt;&amp;quot;;
    OrganizationEmail = &amp;quot;&amp;lt;organization email&amp;gt;&amp;quot;;
    OrganizationMagic = &amp;lt;organization magic&amp;gt;;
    OrganizationName = &amp;quot;&amp;lt;organization name&amp;gt;&amp;quot;;
    OrganizationPhone = &amp;quot;&amp;lt;organization phone&amp;gt;&amp;quot;;
    OrganizationSupportPhone = &amp;quot;&amp;lt;organization phone&amp;gt;&amp;quot;;
    OrganizationZipCode = &amp;lt;organization zipcode&amp;gt;;
    SkipSetup =     (
        Diagnostics,
        Biometric,
        Restore,
        Registration,
        TOS,
        Payment,
        AppleID,
        iCloudDiagnostics
    );
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;aside class=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; The &lt;code&gt;mdmclient&lt;&#x2F;code&gt; command and some terminology are specific to macOS 10.13.3 and below. Future versions of macOS may change the command and&#x2F;or terminology.&lt;&#x2F;p&gt;

&lt;&#x2F;aside&gt;
&lt;p&gt;You&#x27;ll notice the &lt;code&gt;SkipSetup&lt;&#x2F;code&gt; dictionary contains the list of Setup Assistant screens to be skipped.&lt;&#x2F;p&gt;
&lt;p&gt;In troubleshooting our issue with Location Services I was perplexed!
The activation record clearly showed that Location Services was &lt;em&gt;not&lt;&#x2F;em&gt; configured to be skipped.
We should be seeing it during Setup Assistant.&lt;&#x2F;p&gt;
&lt;p&gt;A couple of colleagues on the &lt;a href=&quot;https:&#x2F;&#x2F;macadmins.org&quot;&gt;MacAdmins Slack team&lt;&#x2F;a&gt; provided me with the necessary clue to resolve the issue. 
Specifically, Nate Van Dam &lt;a href=&quot;https:&#x2F;&#x2F;macadmins.slack.com&#x2F;archives&#x2F;C19MR7EM9&#x2F;p1511797350000306&quot;&gt;noted the new behavior&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;express-setup&quot;&gt;Express Setup&lt;&#x2F;h2&gt;
&lt;p&gt;macOS High Sierra introduces a new &amp;quot;Express Setup&amp;quot; workflow during Setup
Assistant. This screen consolidates the activation of &lt;strong&gt;Siri&lt;&#x2F;strong&gt;, &lt;strong&gt;Location
Services&lt;&#x2F;strong&gt;, and &lt;strong&gt;App Analytics&lt;&#x2F;strong&gt; into one screen.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;express-setup.84103a0066fb1040.webp&quot;width=&quot;720&quot; height=&quot;540&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;All three of these screens &lt;strong&gt;must not&lt;&#x2F;strong&gt; be skipped in order for Express Setup to
appear. When you click &amp;quot;Continue&amp;quot; on the Express Setup screen, all three
settings will be activated for you.&lt;&#x2F;p&gt;
&lt;p&gt;If you do configure any of these screens to be skipped, Express Setup will not
appear and the Mac may be configured in an undesired way.&lt;&#x2F;p&gt;
&lt;p&gt;The dependency between these three settings is not currently documented in
Apple&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;library&#x2F;content&#x2F;documentation&#x2F;Miscellaneous&#x2F;Reference&#x2F;MobileDeviceManagementProtocolRef&#x2F;4-Profile_Management&#x2F;ProfileManagement.html#&#x2F;&#x2F;apple_ref&#x2F;doc&#x2F;uid&#x2F;TP40017387-CH7-SW30&quot;&gt;Device Enrollment Program Profile
details&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fixing-it&quot;&gt;Fixing it&lt;&#x2F;h2&gt;
&lt;p&gt;Simple – just make sure &lt;strong&gt;Siri&lt;&#x2F;strong&gt;, &lt;strong&gt;Location Services&lt;&#x2F;strong&gt;, and &lt;strong&gt;App Analytics&lt;&#x2F;strong&gt;
are not skipped in your DEP configurations.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;prestage-skip-good.e4ec791a420c1cd6.webp&quot;width=&quot;720&quot; height=&quot;602&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Now, when a you run through Setup Assistant the Express Setup screen will
appear. Accepting the default settings will turn Siri, Location Services, and
App Analytics on, and &lt;mark&gt;devices will be configured to use the correct time
zone of their current location.&lt;&#x2F;mark&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;disabling-undesired-settings&quot;&gt;Disabling undesired settings&lt;&#x2F;h2&gt;
&lt;p&gt;Since the new Express Setup screen &amp;quot;bundles&amp;quot; these privacy-related options, it
has the side effect of obfuscating your ability to disable them individually.&lt;&#x2F;p&gt;
&lt;p&gt;You can, however, click &amp;quot;Customize Settings&amp;quot; on the Express Setup screen to
invidually disable Siri, Location Services, or App Analytics. It&#x27;s common to
disable the App Analytics telemetry options, and unfortunately this new workflow
adds several extra clicks accomplish that result.&lt;&#x2F;p&gt;
&lt;p&gt;Hopefully Apple will document this change, and MDM solutions will update their 
interfaces to better clarify these Setup Assistant dependencies.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Automatically Renaming Computers from a Google Sheet with Jamf Pro</title>
            <pubDate>Tue, 30 Jan 2018 00:00:00 +0000</pubDate>
            <link>https://macblog.org/jamf-computer-name-google-sheet/</link>
            <guid>https://macblog.org/jamf-computer-name-google-sheet/</guid>
            <description>&lt;p&gt;In a post-imaging, DEP-only world, maintaining your organization&#x27;s computer
naming convention can be a challenge.&lt;&#x2F;p&gt;
&lt;p&gt;We can ease the pain with a little bit of Python, some clever interaction with
the &lt;code&gt;jamf&lt;&#x2F;code&gt; binary, and a remotely-hosted Google Sheet.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;the-problem&quot;&gt;The problem&lt;&#x2F;h2&gt;
&lt;p&gt;With DEP enrollments, your Macs are assigned a default computer hostname in the
format &lt;code&gt;&amp;lt;user&#x27;s first name&amp;gt;&#x27;s &amp;lt;Mac model&amp;gt;&lt;&#x2F;code&gt;. DEP provides no facility to set
computer names, and Jamf Pro&#x27;s PreStage Enrollments are similarly limited.&lt;&#x2F;p&gt;
&lt;p&gt;You wind up with your devices having very consumer-centric names like &amp;quot;Susie&#x27;s
MacBook Pro&amp;quot; and &amp;quot;Dave&#x27;s iMac&amp;quot;. Hostnames like that can cause compatibility
issues in some environments, and often don&#x27;t fit an organization&#x27;s device naming
convention.&lt;&#x2F;p&gt;
&lt;p&gt;Helpfully, the &lt;code&gt;jamf&lt;&#x2F;code&gt; binary includes a &lt;code&gt;setComputerName&lt;&#x2F;code&gt; verb to aid in – as it
says on the tin – setting the computer&#x27;s name. &lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;-name&lt;&#x2F;code&gt; flag will set the computer name to whatever you provide.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$ sudo jamf setComputerName -name ITDEPT-MAC14
Set Computer Name to ITDEPT-MAC14
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;-useSerialNumber&lt;&#x2F;code&gt; and &lt;code&gt;-useMACAddress&lt;&#x2F;code&gt; flags will set the computer name to
either of those values.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$ sudo jamf setComputerName -useMACAddress
Set Computer Name to 724f43aa12f
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can also create more complex computer names with the optional &lt;code&gt;-prefix&lt;&#x2F;code&gt; and
&lt;code&gt;-suffix&lt;&#x2F;code&gt; flags.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$ sudo jamf setComputerName -useMACAddress -prefix &amp;quot;Mac-&amp;quot; -suffix &amp;quot;-ITDEPT&amp;quot;
Set Computer Name to Mac-784f435ee12d-ITDEPT
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These options may be sufficient for you – so feel free to tune out now!&lt;&#x2F;p&gt;
&lt;p&gt;However, your organization&#x27;s naming scheme might include information that&#x27;s not
easily discernable from the device. In my case, our hostnames include the name
of the department who owns the device and the asset tag.&lt;&#x2F;p&gt;
&lt;p&gt;One workaround is to script a GUI prompt for an end user or IT staff to manually
enter the correct computer name. You can then feed this input to &lt;code&gt;jamf setComputerName -name &amp;lt;input&amp;gt;&lt;&#x2F;code&gt; – but that&#x27;s error-prone and cumbersome to the
user.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;mark&gt;I want this automated!&lt;&#x2F;mark&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-fromfile-flag&quot;&gt;The &lt;code&gt;-fromFile&lt;&#x2F;code&gt; flag&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;jamf&lt;&#x2F;code&gt; binary&#x27;s &lt;code&gt;setComputerName&lt;&#x2F;code&gt; command also includes the &lt;code&gt;-fromFile&lt;&#x2F;code&gt; flag.
From the &lt;code&gt;jamf&lt;&#x2F;code&gt; help:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;-fromFile
The path to a CSV file containing the computer&amp;#39;s MAC Address or Serial Number followed by the desired name
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This little gem allows you to provide the path to a CSV file containing device
serial numbers or MAC addresses and those devices&#x27; associated desired hostnames.&lt;&#x2F;p&gt;
&lt;p&gt;Some experimentation showed the required format of the CSV file is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;serial number or MAC address&amp;gt;,&amp;lt;desired hostname&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A complete CSV using serial numbers might look like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;C02S1234GTFZ,ACCOUNTING-123
C02S1232GTFZ,PURCHASING-432
C02S1252GTFZ,MARKETING-823
C02S1211GTFZ,PUBLICSAFETY-242
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After saving that CSV file to &lt;code&gt;&#x2F;var&#x2F;tmp&#x2F;serials.csv&lt;&#x2F;code&gt; for example, you can then 
run:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo jamf setComputerName -fromFile &#x2F;var&#x2F;tmp&#x2F;serials.csv
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If the device running this command has a serial number listed in the specified
CSV file, the &lt;code&gt;jamf&lt;&#x2F;code&gt; binary will find it and set the computer name to the
provided value. If the serial number (or MAC address) of the device is &lt;em&gt;not&lt;&#x2F;em&gt;
found in the specific CSV file, the &lt;code&gt;jamf&lt;&#x2F;code&gt; binary will print an error and the
computer name remains unchanged.&lt;&#x2F;p&gt;
&lt;p&gt;Using the CSV file allows you to assign more complex hostnames to your devices,
but that CSV file must exist on the client in order to be used. You could create
a policy to install the file on your fleet, but this is &lt;strong&gt;very&lt;&#x2F;strong&gt; messy and would
quickly lead to stale data.&lt;&#x2F;p&gt;
&lt;p&gt;Instead, we&#x27;ll host the CSV on a web server in a central location. This way, you
can easily update the data without having to re-install any files on your
clients.&lt;&#x2F;p&gt;
&lt;p&gt;For ease, we&#x27;ll use a Google Sheet.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;create-a-google-sheet&quot;&gt;Create a Google Sheet&lt;&#x2F;h2&gt;
&lt;p&gt;You&#x27;ll need a Google account with the Drive service available. If your
organization uses G Suite, you&#x27;re good to go, though any Google account will
work.&lt;&#x2F;p&gt;
&lt;p&gt;Create a new Google Sheet document. Populate column A with your computer serial
numbers or MAC address, and column B with their associated desired hostnames.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;google-sheet.91a1564b1c79f662.webp&quot;width=&quot;720&quot; height=&quot;356&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Click &amp;quot;Share&amp;quot; in the upper right corner, then click &amp;quot;Advanced&amp;quot; in the lower
right of the modal Share window. Under the &amp;quot;Who has access&amp;quot; heading, you&#x27;ll
likey see &amp;quot;Private - Only you can access&amp;quot;. &lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;who-has-access.61cca98f03ed8ea4.webp&quot;width=&quot;720&quot; height=&quot;124&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Click the &amp;quot;Change...&amp;quot; link here, then select the Link Sharing option &amp;quot;On -
Anyone with the link&amp;quot;. Confirm the Access is set to &amp;quot;Anyone &lt;strong&gt;Can view&lt;&#x2F;strong&gt;&amp;quot;, then
click Save.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;link-sharing.8f9564475c9074d0.webp&quot;width=&quot;720&quot; height=&quot;535&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Since serial numbers and MAC addresses could be considered somewhat sensitive
information, these settings will reduce the availablity of the data while still
allowing your clients to access the sheet.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, note your Google Sheet&#x27;s document ID. It&#x27;s the long string of
seemingly-random characters in the URL shown when editing the Sheet.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;document-id.e27948c205e8a48e.webp&quot;width=&quot;720&quot; height=&quot;34&quot;&gt;&lt;&#x2F;figure&gt;&lt;h2 id=&quot;add-a-script-to-jamf-pro&quot;&gt;Add a script to Jamf Pro&lt;&#x2F;h2&gt;
&lt;p&gt;In your Jamf Pro server, visit &lt;em&gt;Management Settings &amp;gt; Computer Management &amp;gt;
Scripts&lt;&#x2F;em&gt; and create a new script.&lt;&#x2F;p&gt;
&lt;p&gt;Paste the contents of &lt;code&gt;rename-computer.py&lt;&#x2F;code&gt; into the Script Contents area.&lt;&#x2F;p&gt;
&lt;script src=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;haircut&#x2F;1debf91078ce75612bf2f0c3b3d99f03.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;p&gt;Under the Options tab, set Parameter 4 to &amp;quot;CSV URL&amp;quot;.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;parameter-label.2f5acfbe478966e0.webp&quot;width=&quot;720&quot; height=&quot;276&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;The &lt;code&gt;rename-computer.py&lt;&#x2F;code&gt; script downloads the CSV file from Google Sheets (or
any other web server you where you host it), saves it to a temporary location on
the client, then runs the &lt;code&gt;jamf setComputerName...&lt;&#x2F;code&gt; command with the &lt;code&gt;-fromFile&lt;&#x2F;code&gt;
flag.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;create-a-policy-to-rename-computers&quot;&gt;Create a policy to rename computers&lt;&#x2F;h2&gt;
&lt;p&gt;Create a new policy to run the &lt;code&gt;rename-computer.py&lt;&#x2F;code&gt; script. Give the policy an
appropriate name, like &amp;quot;Rename Computer&amp;quot;. Configure the &amp;quot;Scripts&amp;quot; payload by
adding the &lt;code&gt;rename-computer.py&lt;&#x2F;code&gt; script. We&#x27;ll set the &amp;quot;CSV URL&amp;quot; parameter to
point to your remote-hosted CSV file.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re using the Google Sheet outlined above, we need to construct a URL to
output the Sheet in CSV format.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;https:&#x2F;&#x2F;docs.google.com&#x2F;spreadsheets&#x2F;u&#x2F;0&#x2F;d&#x2F;&amp;lt;document ID&amp;gt;&#x2F;export?format=csv&amp;amp;id=&amp;lt;document ID&amp;gt;&amp;amp;gid=0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Remember the Google Sheet document ID we noted earlier? Insert it in the URL
above to replace both &lt;code&gt;&amp;lt;document ID&amp;gt;&lt;&#x2F;code&gt; placeholders. Paste this URL into the &amp;quot;CSV
URL&amp;quot; field of the policy&#x27;s script configuration. &lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;script-config.28e959b3f768b1cb.webp&quot;width=&quot;720&quot; height=&quot;219&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Configure the &amp;quot;Maintenance&amp;quot; policy payload to &amp;quot;Update Inventory&amp;quot; so the new
computer name is reflected in your inventory.&lt;&#x2F;p&gt;
&lt;p&gt;Set an appropriate scope for the policy, and a pertinent policy trigger. You
could make the policy available in Self Service, or set it to run once at
startup – whatever makes sense for your environment. &lt;mark&gt;I&#x27;m running the
script at the end of a DEP enrollment to automatically rename the computer after
Setup Assistant completes.&lt;&#x2F;mark&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When a client runs the script, if its serial number or MAC address is found in
the CSV file, the device&#x27;s name will be updated to match the provided value. If
the device&#x27;s serial is not found, the script returns a non-zero exit code and
Jamf Pro will record a policy failure. The logs for that policy failure should
report exactly why it failed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-word-on-sensitive-data&quot;&gt;A word on sensitive data&lt;&#x2F;h2&gt;
&lt;p&gt;As mentioned, you may classify device serial numbers or MAC addresses as
sensitive data. If this is a concern for you or your environment, you should
forego the Google Sheet option and instead host your CSV on a web server you
control.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Presto – that&#x27;s it!&lt;&#x2F;p&gt;
&lt;p&gt;When you add new devices to your inventory, or need to reassign hostnames,
simply update your Google Sheet (or self-hosted CSV file). No need to change
anything in your Jamf Pro server – since our script references the external CSV
it&#x27;s always up to date.&lt;&#x2F;p&gt;
&lt;p&gt;I hope you find this workflow helpful.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Wait, is my Mac Up to Date?</title>
            <pubDate>Mon, 08 Jan 2018 00:00:00 +0000</pubDate>
            <link>https://macblog.org/up-to-date/</link>
            <guid>https://macblog.org/up-to-date/</guid>
            <description>&lt;p&gt;So you&#x27;ve trained your users to use Jamf Pro&#x27;s Self Service to install
third-party software, but how can we encourage users to self-manage macOS
operating system updates?&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s create a user-centric, Self Service workflow for checking the status of
available software updates.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;aside class=&quot;alert&quot;&gt;&lt;p class=&quot;alert-title&quot;&gt;Update for 2022&lt;&#x2F;p&gt;&lt;p&gt;&lt;strong&gt;Do not follow these instructions&lt;&#x2F;strong&gt;. I wrote this post in 2018 when this was
better advice. Changes in recent versions of macOS obviate some of the methods
discussed in the post, and other areas are simply bad or incomplete advice with
the advent of Apple Silicon chips.&lt;&#x2F;p&gt;

&lt;&#x2F;aside&gt;&lt;h2 id=&quot;background&quot;&gt;Background&lt;&#x2F;h2&gt;
&lt;p&gt;In my shop we support users at all positions of the &amp;quot;technical literacy&amp;quot;
spectrum. Some users may not have familiarity with the Mac App Store or
installing operating system updates. We want to provide a &amp;quot;single place&amp;quot; to
point users for all their computer needs, so we really push Self Service as
&lt;em&gt;&lt;strong&gt;the&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; place to go for software. We&#x27;ve built a strong &amp;quot;Self Service&amp;quot; culture,
so that often means we need to provide information directly in Self Service.&lt;&#x2F;p&gt;
&lt;p&gt;The most common question we want to answer is &amp;quot;Hey, is my Mac up to date?&amp;quot;&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;img&amp;#x2F;wait-is-my-mac-up-to-date&amp;#x2F;ss-anim.gif&quot;width=&quot;868&quot; height=&quot;517&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;With a handful of policies, Smart Groups, and some clever scoping, we can help
users answer this question.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;collecting-available-software-updates&quot;&gt;Collecting Available Software Updates&lt;&#x2F;h2&gt;
&lt;p&gt;For this workflow, we need to enable the Jamf Pro option to collect available
Software Updates during recon on our clients. This option is found at
&lt;em&gt;Management Settings &amp;gt; Inventory Collection&lt;&#x2F;em&gt;; place a check by &amp;quot;Collect
available software updates&amp;quot;.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;inventory-collection.e8a56f7af4b063cf.webp&quot;width=&quot;720&quot; height=&quot;170&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;A colleague at another organization cautioned me that collecting available
software updates can lead to database bloat. In my case, we have 500 clients and
the associated &lt;code&gt;available_software_updates&lt;&#x2F;code&gt; table in our Jamf database is only
64 KB. In my experience, this workflow encourages users to install available
updates, so the database never has to track a large amount of pending updates
across our fleet. &lt;&#x2F;p&gt;
&lt;p&gt;You mileage will vary depending on your environment so make sure you monitor
your database!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;software-update-smart-groups&quot;&gt;Software Update Smart Groups&lt;&#x2F;h2&gt;
&lt;p&gt;Once you&#x27;ve enabled collection of available Software Updates, new criteria are
available for your Smart Groups. Here, we&#x27;re concerned with the &amp;quot;Number of
Available Software Updates&amp;quot; criterion.&lt;&#x2F;p&gt;
&lt;p&gt;Create a new Smart Group named &amp;quot;Software Update - Updates Available&amp;quot; with the
single criterion &amp;quot;Number of Available Updates &lt;strong&gt;more than&lt;&#x2F;strong&gt; &lt;code&gt;0&lt;&#x2F;code&gt;&amp;quot;.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;sg-updates-available.9945df1491b3aa10.webp&quot;width=&quot;720&quot; height=&quot;241&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Any client with any number of Software Updates available will fall into this
Smart Group.&lt;&#x2F;p&gt;
&lt;p&gt;Next, create another new Smart Group named &amp;quot;Software Update - No Updates
Available&amp;quot;. This will be – as you might guess – the inverse of the &amp;quot;Software
Update - No Updates Available&amp;quot; group you just created. Give it the single
criterion &amp;quot;Number of Available Updates &lt;strong&gt;is&lt;&#x2F;strong&gt; &lt;code&gt;0&lt;&#x2F;code&gt;&amp;quot;.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;sg-no-updates-available.c43d0fe1a7e46d08.webp&quot;width=&quot;720&quot; height=&quot;247&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Clients that are completely up-to-date will fall into this Smart Group.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;self-service-policies&quot;&gt;Self Service Policies&lt;&#x2F;h2&gt;
&lt;p&gt;Now we&#x27;ll build the two policies a user might see in Self Service.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;no-macos-updates-available-policy&quot;&gt;&amp;quot;No macOS Updates Available&amp;quot; Policy&lt;&#x2F;h3&gt;
&lt;p&gt;First, we&#x27;ll create a very simple policy to communicate to your users that no
macOS Software Updates are available. This policy is informational only and is,
more or less, a &amp;quot;dummy&amp;quot; policy. We&#x27;re just giving users a simple and definitive
confirmation their Mac is up to date.&lt;&#x2F;p&gt;
&lt;p&gt;Create a new policy named &amp;quot;No macOS Updates Available&amp;quot;. We set the Execution
Frequency to &amp;quot;Ongoing&amp;quot; because this policy will be situationally displayed
multiple times over the life of a device. Do not configure any Triggers since
this policy will only ever be available in Self Service.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;p-no-updates-ss-config.5e4b3fc941772c68.webp&quot;width=&quot;720&quot; height=&quot;472&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Next, set the scope of the policy to your &amp;quot;Software Update - No Updates
Available&amp;quot; Smart Group.&lt;&#x2F;p&gt;
&lt;p&gt;Under the Self Service options, ensure &amp;quot;Make the policy available in Self
Service&amp;quot; is checked. Set the &amp;quot;Self Service Display Name&amp;quot; to &amp;quot;No macOS Updates
Available&amp;quot;. Both the &amp;quot;Button Name Before Initiation&amp;quot; and &amp;quot;Button Name After
Initiation&amp;quot; should be set, simply, to &amp;quot;Info&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Spend some time crafting an appropriate message for the Self Service
Description. We need to indicate to the user that their Mac is updated and there
is no need to do anything further. Here&#x27;s an approximation of what I&#x27;m using.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Your computer is up to date, and no &lt;strong&gt;macOS updates&lt;&#x2F;strong&gt; are available or required.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;There is no need to click the &amp;quot;Info&amp;quot; button – this message is purely informational.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Third-party applications may still require updates. You can check for non-operating-system updates under the &amp;quot;Available Updates&amp;quot; category in Self Service, or by running an application&#x27;s &amp;quot;Check for Updates&amp;quot; function.&lt;&#x2F;p&gt;
&lt;p&gt;If you feel this message is in error or you require additional assistance, please contact the helpdesk at &amp;lt;phone number&amp;gt; or &amp;lt;email address&amp;gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Make sure you enable the &amp;quot;Ensure that users view the description&amp;quot; option. If
your users do click the &amp;quot;Info&amp;quot; button for this policy, we want them to see our
helpful description.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;ss-no-updates-description.067108602e41f32a.webp&quot;width=&quot;720&quot; height=&quot;496&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Upload a suitable icon for the policy. I&#x27;ve provided the icons shown here as
free-as-in-beer images under the &amp;quot;Resources&amp;quot; heading of this article, but feel
free to use your own.&lt;&#x2F;p&gt;
&lt;p&gt;I check the box to &amp;quot;Include the policy in the Featured category&amp;quot;. This puts the
policy front-and-center when a user opens Self Service.&lt;&#x2F;p&gt;
&lt;p&gt;Save the policy. &lt;&#x2F;p&gt;
&lt;p&gt;Finally, users &lt;strong&gt;will&lt;&#x2F;strong&gt; try to click &amp;quot;Info&amp;quot; again and run the policy no matter
how clear your messaging is. I have the policy logs to prove it! We&#x27;ll add a
simple feedback script to provide a bit of clarity.&lt;&#x2F;p&gt;
&lt;p&gt;Add the following Script to your Jamf Pro Server:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#!&#x2F;bin&#x2F;bash
&#x2F;usr&#x2F;bin&#x2F;osascript -e &amp;#39;tell application &amp;quot;Self Service&amp;quot; to display dialog &amp;quot;No macOS updates available.&amp;quot; buttons {&amp;quot;Okay&amp;quot;} with icon caution giving up after 120&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In case a user clicks &amp;quot;Info&amp;quot; to run the policy – and they will! – they&#x27;ll
receive a quick secondary confirmation dialog to let them know that no updates
are available.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;dialog-no-updates.ef515e6f13a2e1ad.webp&quot;width=&quot;720&quot; height=&quot;215&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Go back to your &amp;quot;No macOS Updates Available&amp;quot; policy and add this script.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;install-macos-updates-policy&quot;&gt;&amp;quot;Install macOS Updates&amp;quot; Policy&lt;&#x2F;h3&gt;
&lt;p&gt;Now we&#x27;ll handle devices that &lt;em&gt;do&lt;&#x2F;em&gt; have updates available. Create a new policy
named &amp;quot;Install macOS Updates&amp;quot;. This policy will also be configured with an
&amp;quot;Ongoing&amp;quot; Execution Frequency, but no Triggers.&lt;&#x2F;p&gt;
&lt;p&gt;Configure the &amp;quot;Software Updates&amp;quot; policy payload to install updates from &amp;quot;Each
computer&#x27;s default software update server&amp;quot; or &amp;quot;Apple&#x27;s Software Update server&amp;quot;
as appropriate for your environment. Unless you run a local Software Update
Server, the &amp;quot;Apple&#x27;s Software Update server&amp;quot; is fine.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;p-updates-swu.f6ce21f03e55845a.webp&quot;width=&quot;720&quot; height=&quot;120&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Since some updates will require rebooting the computer, configure the &amp;quot;Restart
Options&amp;quot; policy payload. Set the Startup Disk to &amp;quot;Current Startup Disk (No
Bless)&amp;quot;, the No User Logged In Action to &amp;quot;Restart if a package or updates
requires it&amp;quot;, and the User Logged In Action to &amp;quot;Restart if a package or updates
requires it&amp;quot;. Leave restart Delay as the default &lt;code&gt;5&lt;&#x2F;code&gt; minutes, or set a value of
your preference.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;p-updates-restart-options-nb.5df4e19a78cbed04.webp&quot;width=&quot;720&quot; height=&quot;359&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;With these options, if none of the available Software Updates require a restart
they will simply be installed. But, if one or more updates do require a restart,
the policy will take care of it.&lt;&#x2F;p&gt;
&lt;article class=&quot;message is-warning&quot;&gt;
	&lt;div class=&quot;message-body&quot;&gt;
	  &lt;strong&gt;Update 2018-01-15:&lt;&#x2F;strong&gt; 
	  &lt;p&gt;A previous version of this article advised using the &quot;Current Startup Disk&quot; setting within the Restart Options payload.&lt;&#x2F;p&gt;
	  &lt;p&gt;Shortly after this article was published, Apple released &lt;a href=&quot;https:&#x2F;&#x2F;support.apple.com&#x2F;en-us&#x2F;HT208397&quot;&gt;macOS High Sierra 10.13.2 Supplemental Update&lt;&#x2F;a&gt;. In testing, the &lt;code&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;legacy&#x2F;library&#x2F;documentation&#x2F;Darwin&#x2F;Reference&#x2F;ManPages&#x2F;man8&#x2F;bless.8.html&quot;&gt;bless&lt;&#x2F;a&gt;&lt;&#x2F;code&gt; issued by Jamf can cause a Mac to restart to the incorrect volume after installing the supplemental update.&lt;&#x2F;p&gt;
	  &lt;p&gt;Selecting the &quot;Current Startup Disk (No Bless)&quot; option avoids this issue.&lt;&#x2F;p&gt;
	&lt;&#x2F;div&gt;
&lt;&#x2F;article&gt;
&lt;p&gt;Configure the &amp;quot;Maintenance&amp;quot; policy payload, and ensure &amp;quot;Update Inventory&amp;quot; is
checked. This will make sure that, once the available updates are installed, a
new inventory report is collected for the device. This will update the inventory
record to show that no updates are required. &lt;&#x2F;p&gt;
&lt;p&gt;Set the Scope of the policy to your &amp;quot;Software Update - Updates Available&amp;quot; Smart
Group.&lt;&#x2F;p&gt;
&lt;p&gt;Under the Self Service policy options, ensure &amp;quot;Make the policy available in Self
Service&amp;quot; is checked.&lt;&#x2F;p&gt;
&lt;p&gt;Set the Self Service Display Name to &amp;quot;Install macOS Updates&amp;quot;, and both the
&amp;quot;Button Name Before Initiation&amp;quot; and &amp;quot;Button Name After Initiation&amp;quot; to &amp;quot;Update&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Provide a helpful description, and check &amp;quot;Ensure that users view the
description&amp;quot;. My verbiage is:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Installs all available Apple software updates for macOS.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Warning&lt;&#x2F;strong&gt;: You must close all applications to install this system update, and will be required to restart the computer to complete installation. Please save your work before installing updates.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;p-updates-ss-config.fb11cfaf9f263405.webp&quot;width=&quot;720&quot; height=&quot;367&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Finally, we&#x27;ll add some messaging to guide users through the process. Under the
User Interaction section of the policy, configure a suitable &amp;quot;Start Message&amp;quot;;
something simple to let the user know the process has begun.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;macOS Software Updates are downloading now and will be installed soon. Please
save your work.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Set a Restart Message to inform users their Mac must restart if required by an
update. This message will only display if one or more updates requires a
restart.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Software Updates have been installed and this Mac will restart in 5 minutes.
Please save anything you are working on and log out by choosing Log Out from
the bottom of the Apple menu. If you have any questions, please contact the
helpdesk at &lt;phone number&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;p-updates-interaction.b04e16394654e55f.webp&quot;width=&quot;720&quot; height=&quot;363&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Save your policy and we&#x27;re ready to test!&lt;&#x2F;p&gt;
&lt;p&gt;When users run the &amp;quot;Install macOS Updates&amp;quot; policy, Jamf Pro will instruct the
client to download and install any available Apple Software Updates. If any of
those updates require a system restart, the user will be alerted and system will
restart as required.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;end-result&quot;&gt;End Result&lt;&#x2F;h2&gt;
&lt;p&gt;If a device has any available Software Updates, the &amp;quot;Install macOS Updates&amp;quot;
policy will be visible in Self Service. Users can run this policy to install all
available updates.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;self-service-available.30b6bcd76fc14f1d.webp&quot;width=&quot;720&quot; height=&quot;428&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Once updates are installed, the device will fall &lt;em&gt;out&lt;&#x2F;em&gt; of the &amp;quot;Software Update -
Updates Available&amp;quot; Smart Group and &lt;em&gt;into&lt;&#x2F;em&gt; the &amp;quot;Software Update - No Updates
Available&amp;quot; group. Then, the &amp;quot;No macOS Updates Available&amp;quot; informational policy
will be visible in Self Service, and the &amp;quot;Install macOS Updates&amp;quot; will no longer
appear until Apple releases new updates.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;self-service-none-available.77be3930b40202e8.webp&quot;width=&quot;720&quot; height=&quot;428&quot;&gt;&lt;&#x2F;figure&gt;&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;&#x2F;h2&gt;
&lt;p&gt;If you like my giant bright Self Service icons, feel free to use them.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;install-macos-updates.8d7f0cb6b691ba64.webp&quot;width=&quot;256&quot; height=&quot;256&quot;&gt;&lt;&#x2F;figure&gt;


    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;no-macos-updates-available.f794bbedf76bdde5.webp&quot;width=&quot;256&quot; height=&quot;256&quot;&gt;&lt;&#x2F;figure&gt;</description>
        </item>
        <item>
            <title>Integrating DetectX Swift with Jamf Pro for Scheduled Malware Scanning</title>
            <pubDate>Tue, 12 Dec 2017 00:00:00 +0000</pubDate>
            <link>https://macblog.org/detectx-jamf/</link>
            <guid>https://macblog.org/detectx-jamf/</guid>
            <description>&lt;p&gt;Sqwarq&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;sqwarq.com&#x2F;detectx&#x2F;&quot;&gt;DetectX&lt;&#x2F;a&gt; is an amazing shareware security tool that checks your Mac for malware, keyloggers, adware and potentially unwanted programs.&lt;&#x2F;p&gt;
&lt;p&gt;Recent updates to DetectX add the ability for administrators to initiate a scheduled scan from a management platform.&lt;&#x2F;p&gt;
&lt;p&gt;Neat! Let&#x27;s integrate it with Jamf Pro to scan and report on your fleet.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;aside class=&quot;alert&quot;&gt;&lt;p&gt;
    &lt;strong&gt;FYI!&lt;&#x2F;strong&gt; As of March 2020 it seems like changes are coming with DetectX Swift, and Sqwarq is no longer selling management licenses. Instead, you can &lt;a href=&quot;https:&#x2F;&#x2F;sqwarq.com&#x2F;detectx&#x2F;&quot;&gt;view a free license key on their site&lt;&#x2F;a&gt;.
  &lt;&#x2F;p&gt;
&lt;&#x2F;aside&gt;
&lt;p&gt;Developer Phil Stokes is currently working on a Swift re-write of the app named, appropriately, &lt;a href=&quot;https:&#x2F;&#x2F;sqwarq.com&#x2F;detectx&#x2F;detectx-swift-beta&#x2F;&quot;&gt;DetectX Swift&lt;&#x2F;a&gt;. To quote Phil,&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;DetectX Swift is an on-demand security and troubleshooting tool that uses a combination of hardcoded search definitions along with live updates and predictive heuristics to detect both known and unknown threats and issues.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;After a feature request and some discussion, Phil was kind enough to add a command-line interface for DetectX Swift, allowing administrators to run non-interactive scans on their devices. The initial command-line interface was added in v0.108 of DetectX Swift. The latest release, v.110, expands the capabilities of the non-interactive scan to search for suspect files in &lt;strong&gt;all&lt;&#x2F;strong&gt; users&#x27; home directories and elsewhere on the system.&lt;&#x2F;p&gt;
&lt;p&gt;As root (via sudo), you can initiate an administrative scan for all users from the command line by using the &lt;code&gt;-a&lt;&#x2F;code&gt; flag. For example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo &#x2F;Applications&#x2F;DetectX\ Swift.app&#x2F;Contents&#x2F;MacOS&#x2F;DetectX\ Swift search -a
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You&#x27;ll get back a nicely-formatted scan result to &lt;code&gt;stdout&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;DetectX Swift
Mon 11 Dec 2017, 09:26:52 -0500
Searching...

Search includes users:
	haircut
	studentuser
	testuser

&#x2F;Users&#x2F;haircut&#x2F;MacKeeper Backups
&#x2F;Users&#x2F;haircut&#x2F;Library&#x2F;Preferences&#x2F;.3FAD0F65-FC6E-4889-B975-B96CBF807B78
&#x2F;Users&#x2F;haircut&#x2F;Library&#x2F;Logs&#x2F;MacKeeper.log.signed
&#x2F;Users&#x2F;haircut&#x2F;Library&#x2F;Logs&#x2F;MacKeeper.log
&#x2F;Users&#x2F;haircut&#x2F;Downloads&#x2F;MacKeeper.pkg
&#x2F;tmp&#x2F;com.mackeeper.MacKeeper.Installer.config
&#x2F;private&#x2F;tmp&#x2F;com.mackeeper.MacKeeper.Installer.config
&#x2F;Library&#x2F;Preferences&#x2F;.3FAD0F65-FC6E-4889-B975-B96CBF807B78

8 files found.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Uh-oh – looks like I picked up MacKeeper!&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll set up two policies, a script, a Smart Group and an Extension Attribute to generate and collect these scan results and make them available within Jamf Pro.&lt;&#x2F;p&gt;
&lt;aside class=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;DetectX Swift&lt;&#x2F;strong&gt; is currently beta software and may behave in unexpected ways. Use of the software, or integrating it with your Jamf Pro Server, is at your own risk!&lt;&#x2F;p&gt;
&lt;&#x2F;aside&gt;&lt;h2 id=&quot;integration-support-files&quot;&gt;Integration Support Files&lt;&#x2F;h2&gt;
&lt;p&gt;All the files necessary for integration with Jamf Pro are available in my &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;haircut&#x2F;detectx-jamf&quot;&gt;detectx-jamf repo on GitHub&lt;&#x2F;a&gt;. Go ahead and download these files so you can follow along.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;package-detectx-swift-for-deployment&quot;&gt;Package DetectX Swift for Deployment&lt;&#x2F;h2&gt;
&lt;p&gt;Download the &lt;a href=&quot;https:&#x2F;&#x2F;sqwarq.com&#x2F;detectx&#x2F;detectx-swift-beta&#x2F;&quot;&gt;latest DetectX Swift beta&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;DetectX Swift is delivered as a disk image containing the &lt;code&gt;DetectX Swift.app&lt;&#x2F;code&gt; bundle. You&#x27;ll need to package that up to install the app to a known location. It&#x27;s up to you where to put it. &lt;code&gt;&#x2F;Applications&#x2F;Utilities&lt;&#x2F;code&gt; is a good place which will allow your users to easily find DetectX Swift if they&#x27;d like to run it themselves.&lt;&#x2F;p&gt;
&lt;p&gt;While specifics on packaging apps is outside the scope of this guide, I like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;munki&#x2F;munki-pkg&quot;&gt;munkipkg&lt;&#x2F;a&gt; for packaging apps. Any tool – including Jamf Composer – will work.&lt;&#x2F;p&gt;
&lt;p&gt;Once packaged, upload your DetectX Swift package to your Jamf Pro distribution points.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;create-a-policy-to-install-detectx-swift&quot;&gt;Create a Policy to Install DetectX Swift&lt;&#x2F;h2&gt;
&lt;p&gt;Rather than blindly deploy DetectX Swift to all my clients, I prefer to install it on demand, when a client needs it. The &lt;code&gt;run-detectx-search.py&lt;&#x2F;code&gt; script in my &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;haircut&#x2F;detectx-jamf&quot;&gt;detectx-jamf repo&lt;&#x2F;a&gt; will take care of this dependency resolution.&lt;&#x2F;p&gt;
&lt;p&gt;Create a new policy and name it &lt;strong&gt;Install - DetectX Swift&lt;&#x2F;strong&gt;. Set the only trigger to &amp;quot;Custom&amp;quot; and enter the custom trigger &amp;quot;install_detectx&amp;quot;. Set the Frequency to &amp;quot;Ongoing&amp;quot;, since we want this policy to be available whenever we need it.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;detectx-p-general.f75d1169ee0b5562.webp&quot;width=&quot;720&quot; height=&quot;375&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;In the Packages tab, add your DetectX Swift package. Do not enable the &amp;quot;Update Inventory&amp;quot; option in the Maintenance tab – we&#x27;ll handle that later.&lt;&#x2F;p&gt;
&lt;p&gt;Set an appropriate Scope; I make the policy available to all my managed clients but your use case may differ.&lt;&#x2F;p&gt;
&lt;p&gt;Save the policy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;add-the-detectx-script-to-your-jamf-pro-server&quot;&gt;Add the DetectX Script to your Jamf Pro Server&lt;&#x2F;h2&gt;
&lt;p&gt;Open the &lt;code&gt;run-detectx-search.py&lt;&#x2F;code&gt; script downloaded from my &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;haircut&#x2F;detectx-jamf&quot;&gt;detectx-jamf repo&lt;&#x2F;a&gt;. The included variable values on lines 14-23 should serve as suitable defaults.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;detectx-scriptvars.5651bb62c7102da1.webp&quot;width=&quot;720&quot; height=&quot;221&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;If you&#x27;ve changed the installation location of DetectX Swift, or configured a different custom trigger for your &amp;quot;Install - DetectX Swift&amp;quot; policy, make sure to set those values in the script.&lt;&#x2F;p&gt;
&lt;p&gt;By default, &lt;code&gt;run-detectx-search.py&lt;&#x2F;code&gt; uses DetectX Swift&#x27;s &lt;code&gt;-j&lt;&#x2F;code&gt; flag to output the results of the search in JSON format to &lt;code&gt;&#x2F;Library&#x2F;Application Support&#x2F;JAMF&#x2F;Addons&#x2F;DetectX&#x2F;results.json&lt;&#x2F;code&gt;. Placing the results file within &lt;code&gt;&#x2F;Library&#x2F;Application Support&#x2F;JAMF&#x2F;&lt;&#x2F;code&gt; is a best practice, as it will ensure the file is deleted if you ever need to remove the Jamf framework.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;run-detectx-search.py&lt;&#x2F;code&gt; will determine if DetectX Swift is installed at the specified location. If not, it will attempt to install the app by calling the custom trigger you provide. Building dependency resolution into the script helps ensure it is able to run correctly in case a user – or malicious app! – removes DetectX Swift.&lt;&#x2F;p&gt;
&lt;p&gt;The script will also verify that the installed version of DetectX Swift is at least 0.110.&lt;&#x2F;p&gt;
&lt;p&gt;After making any customizations, add a new script to your Jamf Pro Server. Use the filename, &lt;code&gt;run-detectx-search.py&lt;&#x2F;code&gt;, as the &amp;quot;Display Name&amp;quot; of the script. Copy the contents of your &lt;code&gt;run-detectx-search.py&lt;&#x2F;code&gt; file into the Script Contents textbox.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;detectx-script-contents.94b094190426a588.webp&quot;width=&quot;720&quot; height=&quot;472&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Save the script.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;add-an-extension-attribute-to-collect-detectx-search-results&quot;&gt;Add an Extension Attribute to Collect DetectX Search Results&lt;&#x2F;h2&gt;
&lt;p&gt;After running a scan, we need to collect the results and associate them to a computer record within Jamf Pro. We&#x27;ll use an Extension Attribute to read the &lt;code&gt;&#x2F;Library&#x2F;Application Support&#x2F;JAMF&#x2F;Addons&#x2F;DetectX&#x2F;results.json&lt;&#x2F;code&gt; file generated by &lt;code&gt;run-detectx-search.py&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Included in the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;haircut&#x2F;detectx-jamf&quot;&gt;detectx-jamf repo&lt;&#x2F;a&gt; is the &lt;code&gt;DetectX Issues.xml&lt;&#x2F;code&gt; file, which is a ready-to-upload Extension Attribute. Simply navigate to &lt;em&gt;Management Settings &amp;gt; Computer Management &amp;gt; Extension Attributes&lt;&#x2F;em&gt; then click the Upload button. Select the &lt;code&gt;DetectX Issues.xml&lt;&#x2F;code&gt; file on your computer and upload it. Review the settings for the Extension Attribute, particularly &amp;quot;Inventory Display&amp;quot; categoy which controls where the Extension Attribute results are displayed when viewing a computer object.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;detectx-ea-setup.c384c7be17cab06f.webp&quot;width=&quot;720&quot; height=&quot;335&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Save the Extension Attribute.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;mark&gt;If you&#x27;ve changed the default location of the search results file&lt;&#x2F;mark&gt; in &lt;code&gt;run-detectx-search.py&lt;&#x2F;code&gt;, or prefer to create and configure the Extension Attribute manually, &lt;code&gt;EA-DetectX-Issues.py&lt;&#x2F;code&gt; is included in the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;haircut&#x2F;detectx-jamf&quot;&gt;detectx-jamf repo&lt;&#x2F;a&gt;. Edit the script and copy it to an Extension Attribute.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;create-a-policy-to-run-detectx-swift-searches&quot;&gt;Create a Policy to Run DetectX Swift Searches&lt;&#x2F;h2&gt;
&lt;p&gt;With the script in place, we need to create one more policy to schedule DetectX scans on your fleet.&lt;&#x2F;p&gt;
&lt;p&gt;Create a new policy and give it a suitable name, like &amp;quot;Run DetectX Search.&amp;quot;&lt;&#x2F;p&gt;
&lt;p&gt;Set the Trigger to &amp;quot;Recurring Check-in,&amp;quot; and the Frequency to &amp;quot;Once per week.&amp;quot; If your environment demands more frequent or less frequent scanning, adjust the frequency accordingly. I will, however, caution against an &amp;quot;Ongoing&amp;quot; frequency so as not to inflate your Jamf Pro database with excessive inventory reports.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;detectx-rp-general.7d4351fc96a00d20.webp&quot;width=&quot;720&quot; height=&quot;407&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;In the Scripts tab, add the &lt;code&gt;run-detectx-search.py&lt;&#x2F;code&gt; script. No parameters are necessary. Since the script is the only action of the policy, the default priority of &amp;quot;After&amp;quot; is sufficient.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;detectx-rp-scripts.6c7071c24b61fd1a.webp&quot;width=&quot;720&quot; height=&quot;188&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;In the Maintenance tab, ensure &amp;quot;Update Inventory&amp;quot; is &lt;strong&gt;checked&lt;&#x2F;strong&gt;. This will ensure the computer inventory is updated – and the &amp;quot;DetectX Issues&amp;quot; Extension Attribute is populated – after the search is complete.&lt;&#x2F;p&gt;
&lt;p&gt;Set a Scope for the policy. &amp;quot;All Managed Clients&amp;quot; works well, but you may desire to further restrict the availability depending on your needs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;create-a-smart-group-of-infected-machines-for-alerts&quot;&gt;Create a Smart Group of Infected Machines for Alerts&lt;&#x2F;h2&gt;
&lt;p&gt;Finally, we&#x27;ll create a Smart Group to alert us when a DetectX search finds issues on a computer.&lt;&#x2F;p&gt;
&lt;p&gt;Add a new Smart Group named &amp;quot;DetectX - Issues Found.&amp;quot; I enable the &amp;quot;Send email notification on membership change&amp;quot; option so that I&#x27;m emailed when DetectX finds issues on a client.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;detectx-sg-name.78d242f07f1b0295.webp&quot;width=&quot;720&quot; height=&quot;124&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Add two criteria:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;div class=&quot;tags has-addons&quot;&gt;
    &lt;span class=&quot;tag is-size-6&quot;&gt;DetectX Issues&lt;&#x2F;span&gt;
    &lt;span class=&quot;tag is-warning is-size-6&quot;&gt;is not&lt;&#x2F;span&gt;
    &lt;span class=&quot;tag is-size-6&quot;&gt;&amp;lt;blank&amp;gt;&lt;&#x2F;span&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;div class=&quot;tags has-addons&quot;&gt;
    &lt;span class=&quot;tag is-size-6&quot;&gt;DetectX Issues&lt;&#x2F;span&gt;
    &lt;span class=&quot;tag is-warning is-size-6&quot;&gt;is not&lt;&#x2F;span&gt;
    &lt;span class=&quot;tag is-size-6&quot;&gt;None&lt;&#x2F;span&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You may need to click &amp;quot;Show Advanced Criteria&amp;quot; to display the &amp;quot;DetectX Issues&amp;quot; Extension Attribute.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;detectx-sg-criteria.48707c48afa05864.webp&quot;width=&quot;720&quot; height=&quot;119&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Save the Smart Group.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;interpreting-the-extension-attribute&quot;&gt;Interpreting the Extension Attribute&lt;&#x2F;h2&gt;
&lt;p&gt;If DetectX finds potentially malicious files, they will be listed in the &amp;quot;DetectX Issues&amp;quot; Extension Attribute.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;detectx-ea-results.3e115bd50e54a99a.webp&quot;width=&quot;720&quot; height=&quot;320&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;If the search completes but no issues are found, the Extension Attribute will be set to &lt;code&gt;None&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If the search has not yet completed, or an issue occurred when attempting a search, the Extension Attribute will be blank.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;That&#x27;s it! You should now have your clients running background DetectX searches on a regular schedule. When results are found, the infected clients will be added to the &amp;quot;DetectX - Issues Found&amp;quot; Smart Group for reporting.&lt;&#x2F;p&gt;
&lt;p&gt;From here, you have a number of options. Here are a few ideas:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Integrate the Smart Group membership change emails with your ticketing system for technicians to assist with remediation.&lt;&#x2F;li&gt;
&lt;li&gt;Scope a Configuration Profile to the &amp;quot;DetectX - Issues Found&amp;quot; Smart Group to migrate infected machines to a different network that disallows access to sensitive corporate systems.&lt;&#x2F;li&gt;
&lt;li&gt;Scope a Policy to the affected computers that uses jamfHelper to alert the user and guide them through removing malicious files with the DetectX Swift GUI. Be conscious of &amp;quot;&lt;a href=&quot;https:&#x2F;&#x2F;www.nist.gov&#x2F;news-events&#x2F;news&#x2F;2016&#x2F;10&#x2F;security-fatigue-can-cause-computer-users-feel-hopeless-and-act-recklessly&quot;&gt;security fatigue&lt;&#x2F;a&gt;&amp;quot; – users often respond better to direct communication.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Or, just periodically check the group membership and remediate as you see fit.&lt;&#x2F;p&gt;
&lt;p&gt;Hopefully the increased visibility into malicious files on your fleet will prove useful!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Creating a Naming Scheme for Jamf Pro</title>
            <pubDate>Wed, 06 Dec 2017 00:00:00 +0000</pubDate>
            <link>https://macblog.org/naming-scheme/</link>
            <guid>https://macblog.org/naming-scheme/</guid>
            <description>&lt;p&gt;For maintaining a consistent, repeatable and intuitive administrative workflow,
you need a naming scheme for objects in your Jamf Pro Server.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s my take on a good strategy.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;As I add more policies, Smart Groups, configuration profiles and packages to my
Jamf Pro Server, a consistent naming scheme provides clarity. If a quick glance
tells me most of what I need to know about an object, my tasks become
&lt;mark&gt;quicker&lt;&#x2F;mark&gt; and &lt;mark&gt;less error-prone.&lt;&#x2F;mark&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;focus-on-function-and-semantics&quot;&gt;Focus on Function and Semantics&lt;&#x2F;h2&gt;
&lt;p&gt;The name of any JPS object should quickly describe &lt;em&gt;what it does&lt;&#x2F;em&gt; or &lt;em&gt;what it&#x27;s
for&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I use prefix &amp;quot;tags&amp;quot; for most object names. Policies that install apps are
prefixed &lt;code&gt;Install - &lt;&#x2F;code&gt;. Smart Groups containing computers that have a certain app
installed are prefixed &lt;code&gt;Has App - &lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This prefix tag visually gathers similar groups in the alphabetically-sorted JPS
web interface. All my Smart Computer Groups prefixed &amp;quot;Has App - &amp;quot; appear
together when browsing the list.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;namingscheme-prefixgrouping.2441836b532bb4b1.webp&quot;width=&quot;720&quot; height=&quot;579&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Using prefixes also provides the fringe benefit of making complex API operations
easier to handle. For example, I can query a particular computer and quickly
filter the &lt;code&gt;computer_group_memberships&lt;&#x2F;code&gt; array for items that begin with
&lt;code&gt;Outdated App - &lt;&#x2F;code&gt; for a simple way to list which apps on a computer are out of
date.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;allowed-characters-in-jamf-object-names&quot;&gt;Allowed Characters in Jamf Object Names&lt;&#x2F;h3&gt;
&lt;p&gt;Per Jamf support, the following special characters are allowed in object names:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;!@#$%^&amp;amp;*()_+-={}|[]\:&amp;quot;;&#x27;&amp;lt;&amp;gt;?,.&#x2F;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As always, be conservative, and test!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;groups&quot;&gt;Groups&lt;&#x2F;h2&gt;
&lt;p&gt;I name most computer and user groups &lt;mark&gt;based on what policies or profiles I
might scope to them.&lt;&#x2F;mark&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Group Name&lt;&#x2F;th&gt;&lt;th&gt;Scoping Intention&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Does Not Have App - Firefox&lt;&#x2F;td&gt;&lt;td&gt;A policy to install Firefox&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Outdated App - Firefox&lt;&#x2F;td&gt;&lt;td&gt;A policy to update Firefox to the latest version&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Has App - NoMAD&lt;&#x2F;td&gt;&lt;td&gt;A configuration profile to deliver configuration settings for NoMAD&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Software Update - Updates Available&lt;&#x2F;td&gt;&lt;td&gt;A policy to install all available Apple Software Updates&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Reject - Microsoft Office 2016&lt;&#x2F;td&gt;&lt;td&gt;Users who prefer LibreOffice or OpenOffice and do not want Microsoft Office on their Mac&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Licensed - Adobe Creative Cloud&lt;&#x2F;td&gt;&lt;td&gt;Users with an Adobe CC Subscription&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Prefixing group names with descriptive &amp;quot;tags&amp;quot; makes for a very readable and
functional policy list.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;namingscheme-policy-list.01224c9b2af9cd95.webp&quot;width=&quot;720&quot; height=&quot;232&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;The displayed information shows exactly which subset of your inventory a policy
applies to.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;mark&gt;Avoid using Smart Groups to build reports on your inventory.&lt;&#x2F;mark&gt; This
is more appropriate for saved Advanced Searches. In most cases I avoid creating
a Smart Group unless I intend to use it in scoping. Smart Group calculation is
an expensive database operation within the JPS, so limit your total number of
Smart Groups.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;policies&quot;&gt;Policies&lt;&#x2F;h2&gt;
&lt;p&gt;Jamf Pro 10 adds the much-welcomed ability to set both an internal policy name
and a user-facing &amp;quot;Display Name&amp;quot; shown in Self Service.&lt;&#x2F;p&gt;
&lt;p&gt;I name policies based on what they do.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Policy Name&lt;&#x2F;th&gt;&lt;th&gt;Display Name&lt;&#x2F;th&gt;&lt;th&gt;Action&lt;&#x2F;th&gt;&lt;th&gt;Scope&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Install - Firefox&lt;&#x2F;td&gt;&lt;td&gt;Firefox&lt;&#x2F;td&gt;&lt;td&gt;Installs Firefox if not present on system&lt;&#x2F;td&gt;&lt;td&gt;Does Not Have App - Firefox&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Update - Firefox&lt;&#x2F;td&gt;&lt;td&gt;Update Firefox&lt;&#x2F;td&gt;&lt;td&gt;Updates Firefox to latest version if currently installed version is outdated&lt;&#x2F;td&gt;&lt;td&gt;Outdated App - Firefox&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Remove - Firefox&lt;&#x2F;td&gt;&lt;td&gt;Remove Firefox&lt;&#x2F;td&gt;&lt;td&gt;Removes Firefox if installed on system&lt;&#x2F;td&gt;&lt;td&gt;Has App - Firefox&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;With a sensible naming scheme, a single policy can provide clarity for your
users and sanity for you as an administrator.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;namingscheme-flow.c11bf05b15b1ff3a.webp&quot;width=&quot;720&quot; height=&quot;539&quot;&gt;&lt;&#x2F;figure&gt;&lt;h2 id=&quot;configuration-profiles&quot;&gt;Configuration Profiles&lt;&#x2F;h2&gt;
&lt;p&gt;I name configuration profiles based on what they do or affect.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Profile Name&lt;&#x2F;th&gt;&lt;th&gt;Purpose&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;App Defaults - Microsoft Office&lt;&#x2F;td&gt;&lt;td&gt;Initial settings for Microsoft Office&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Security - Login Window&lt;&#x2F;td&gt;&lt;td&gt;A profile to disable automatic login and set the &lt;code&gt;LoginwindowText&lt;&#x2F;code&gt; banner&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;packages&quot;&gt;Packages&lt;&#x2F;h2&gt;
&lt;p&gt;Most of my packages are built via &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autopkg&#x2F;autopkg&quot;&gt;autopkg&lt;&#x2F;a&gt;
recipes, and follow a general &lt;code&gt;&amp;lt;name&amp;gt;-&amp;lt;version&amp;gt;.pkg&lt;&#x2F;code&gt; pattern. If a
vendor-provided or autopkg-created package deviates from this pattern I&#x27;ll
rename it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Microsoft_Word-15.40.171108_Installer.pkg&lt;&#x2F;code&gt; is a lot more descriptive than &lt;code&gt;Word2016.pkg&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Most of the specifics are personal choices; if you prefer a prefix of &lt;code&gt;App Installed: &amp;lt;name&amp;gt;&lt;&#x2F;code&gt; over &lt;code&gt;Has App - &amp;lt;name&amp;gt;&lt;&#x2F;code&gt;, go for it! The takeaway point is to
&lt;mark&gt;leverage patterns&lt;&#x2F;mark&gt; in whatever nomenclature you develop. The less
you have to hunt for a policy or scope, the more attention you can pay to the
details of accomplishing your goals with Jamf Pro.&lt;&#x2F;p&gt;
&lt;p&gt;These are my suggestions, and they work for me and my organization. Hopefully
the thinking behind why I&#x27;ve made certain choices is informative and helpful!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>How to Manage Only FileVault Recovery Key Escrow with Jamf Pro</title>
            <pubDate>Thu, 14 Sep 2017 00:00:00 +0000</pubDate>
            <link>https://macblog.org/jamf-filevault-escrow/</link>
            <guid>https://macblog.org/jamf-filevault-escrow/</guid>
            <description>&lt;p&gt;The Jamf Pro GUI allows you to automatically set up the necessary payloads to
manage the FileVault 2 Recovery Key Escrow process for macOS 10.13+.&lt;&#x2F;p&gt;
&lt;p&gt;However, the settings reside in the &amp;quot;Security &amp;amp; Privacy&amp;quot; grouping within the
Jamf Pro GUI. Configuring only Recovery Key Escrow settings within the &amp;quot;Security
&amp;amp; Privacy&amp;quot; tab will effectively &lt;strong&gt;enforce&lt;&#x2F;strong&gt; the default settings for all other
preferences within the grouping. Using the built-in options, you may
inadvertently enforce settings you don&#x27;t intend. &lt;mark&gt;This may lock your users
out of being able to make changes to the firewall, analytics settings, screen
saver password requirement, and other settings.&lt;&#x2F;p&gt;
&lt;p&gt;You can upload a custom profile to the Jamf Pro Server that manages &lt;strong&gt;only&lt;&#x2F;strong&gt; FDE
Recover Key Escrow preferences, but it takes a little work.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;&lt;mark&gt;You&#x27;ll also need to sign your resultant configuration profile to prevent
the Jamf Pro Server from manipulating its contents or preventing
deployment.&lt;&#x2F;mark&gt; You can use an Apple Developer certificate, or your Jamf Pro
Server&#x27;s CA (if self signed).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;filevault2-recovery-key-escrow-in-macos-high-sierra-and-later&quot;&gt;FileVault2 Recovery Key Escrow in macOS High Sierra (and later)&lt;&#x2F;h2&gt;
&lt;p&gt;FileVault 2 Recovery Key Escrow requires installing a Configuration Profile on
your endpoints with a &lt;code&gt;com.apple.security.FDERecoveryKeyEscrow&lt;&#x2F;code&gt; payload.
Automaticlly escrowing a Personal Recovery Key to Jamf Pro &lt;mark&gt;&lt;strong&gt;requires&lt;&#x2F;strong&gt;
working MDM to function.&lt;&#x2F;mark&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Recovery Key Escrow works by encrypting the Personal Recovery Key with a known
signing certificate. macOS writes the encryped recovery key to
&lt;code&gt;&#x2F;var&#x2F;db&#x2F;FileVaultPRK.dat&lt;&#x2F;code&gt;, which is made available to your MDM server when it
sends a &lt;code&gt;SecurityInfo&lt;&#x2F;code&gt; command. Jamf Pro takes care of these implementation
details for you, including scheduling regular &lt;code&gt;SecurityInfo&lt;&#x2F;code&gt; MDM commands.&lt;&#x2F;p&gt;
&lt;p&gt;The Recovery Key Escrow policy must be present on the system &lt;em&gt;before&lt;&#x2F;em&gt; it is
encrypted in order for the key to be written to &lt;code&gt;&#x2F;var&#x2F;db&#x2F;FileVaultPRK.dat&lt;&#x2F;code&gt;. If
the machine is encrypted prior to installation of the Escrow profile, you will
need to change the recovery key to have &lt;code&gt;&#x2F;var&#x2F;db&#x2F;FileVaultPRK.dat&lt;&#x2F;code&gt; updated, and
the key subsequently available for Jamf Pro. Elliot Jordan&#x27;s
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;homebysix&#x2F;jss-filevault-reissue&quot;&gt;jss-filevault-reissue&lt;&#x2F;a&gt; can
assist with rotating Personal Recovery Keys. I contributed the initial code to
support Recovery Key Escrow in High Sierra and can confirm this process works.&lt;&#x2F;p&gt;
&lt;p&gt;Full details are available in Apple&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;library&#x2F;content&#x2F;featuredarticles&#x2F;iPhoneConfigurationProfileRef&#x2F;Introduction&#x2F;Introduction.html#&#x2F;&#x2F;apple_ref&#x2F;doc&#x2F;uid&#x2F;TP40010206-CH1-SW42&quot;&gt;Configuration Profile
Reference&lt;&#x2F;a&gt;
document.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;filevault2comm-signing-certificate&quot;&gt;FileVault2Comm Signing Certificate&lt;&#x2F;h2&gt;
&lt;p&gt;When you install Jamf Pro, the built-in certificate authority issues a signing
certificate with subject &lt;code&gt;CN=JSS Built-In Signing Certificate,OU=FILEVAULT2COMM&lt;&#x2F;code&gt;, which is used for FileVault 2 Recovery Key
Escrow. We need that certificate for inclusion in the custom profile we&#x27;re
building.&lt;&#x2F;p&gt;
&lt;p&gt;Since the Jamf Pro Server&#x27;s built-in certificate authority issues the
FileVault2Comm signing certificate, it holds the private key necessary to decypt
data that&#x27;s been encrypted using it.&lt;&#x2F;p&gt;
&lt;p&gt;The Jamf Pro GUI does not provide a facility to download it directly, so we&#x27;ll
need to employ a workaround by building a temporary profile.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;create-a-temporary-configuration-profile-in-the-jamf-pro-server&quot;&gt;Create a Temporary Configuration Profile in the Jamf Pro Server&lt;&#x2F;h2&gt;
&lt;p&gt;To generate an appropriate encryption certificate, we&#x27;ll create a temporary
configuration profile within the JPS. Name it something disposable – you&#x27;ll
delete it when done. &amp;quot;TEMP - FDERKE Setup&amp;quot; works. Set the level to &amp;quot;Computer
level.&amp;quot; Make sure you &lt;strong&gt;do not add a scope&lt;&#x2F;strong&gt; to the profile; we&#x27;re not deploying
it.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;fderke-temppolicy1.6878662999b05553.webp&quot;width=&quot;720&quot; height=&quot;427&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Click the &amp;quot;Security &amp;amp; Privacy&amp;quot; group on the left, then click &amp;quot;Configure.&amp;quot; Select
the &amp;quot;FileVault&amp;quot; tab. Apply these preferences:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Checked: &lt;strong&gt;Enable Escrow Personal Recovery Key&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Escrow Location Description&lt;&#x2F;strong&gt;: Describe where the recovery key is being
shipped. This is visible to the end-user, so &amp;quot;My Company IT&amp;quot; or whatever is
appropriate. We&#x27;ll edit this elsewhere, so you can leave it blank.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Device Key for Escrowed FileVault Recovery Key&lt;&#x2F;strong&gt;: Text displayed at the
FileVault unlock screen when a user has apparently forgotten their password.
Despite the help text, you should leave this blank. By default it will be
replaced with the device&#x27;s serial number which will aid your technicians in
recovering the correct key. You might think to put your IT department&#x27;s
support phone number or similar here; that&#x27;s not the intention of this field.
Per Apple:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;An optional string that will be included in help text if the user appears to
have forgotten the password. Can be used by a site admin to look up the
escrowed key for the particular machine.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Personal Recovery Key Encryption Certificate&lt;&#x2F;strong&gt;: Set to &amp;quot;Automatically
encrypt and decrypt recovery key.&amp;quot; This tells Jamf Pro to generate a signing
certificate for use encrypting a device&#x27;s Person Recovery Key. Selecting this
option ensures Jamf Pro has the appropriate private key to decrypt the
recovery key when collected by an MDM command.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;fderke-temppolicy2.bdc71faae3e22c79.webp&quot;width=&quot;720&quot; height=&quot;516&quot;&gt;&lt;&#x2F;figure&gt;
&lt;p&gt;Save the profile, then click the &amp;quot;Download&amp;quot; button.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;grabbing-the-signing-certificate&quot;&gt;Grabbing the Signing Certificate&lt;&#x2F;h2&gt;
&lt;p&gt;Next we&#x27;ll convert the profile to a readable format so we can access the
encryption certificate provided by Jamf. In Terminal, run these commands:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;security cms -D -i &#x2F;path&#x2F;to&#x2F;downloaded&#x2F;profile.mobileconfig -o &#x2F;path&#x2F;to&#x2F;de-signed.mobileconfig
plutil -convert xml1 &#x2F;path&#x2F;to&#x2F;de-signed.mobileconfig
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Copy
&lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;haircut&#x2F;b4fb2a102b7e25ef35b0826922967fb3#file-template-fde-recovery-key-escrow-mobileconfig&quot;&gt;template-fde-recovery-key-escrow.mobileconfig&lt;&#x2F;a&gt;
to a new file in your favorite text editor. Change the values of
&lt;code&gt;PayloadOrganization&lt;&#x2F;code&gt; and &lt;code&gt;Location&lt;&#x2F;code&gt; as needed to match your organization. There
are several instances of each key in the profile so be sure to change them all.&lt;&#x2F;p&gt;
&lt;p&gt;Open the de-signed profile originally downloaded from the Jamf Pro Server in
your text editor. Find the &lt;code&gt;PayloadContent&lt;&#x2F;code&gt; below &lt;code&gt;PayloadCertificateFileName&lt;&#x2F;code&gt; –
it&#x27;s the big, obvious block of certificate data.&lt;&#x2F;p&gt;



    
    

&lt;figure&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;macblog.org&amp;#x2F;processed_images&amp;#x2F;fderke-certfake.3b5bc85835859faa.webp&quot;width=&quot;720&quot; height=&quot;704&quot;&gt;&lt;&#x2F;figure&gt;&lt;aside&gt;
    &lt;p&gt;&lt;strong&gt;Pro Tip!&lt;&#x2F;strong&gt; You can quickly copy the DER-encoded certificate data from a Terminal session – assuming you&#x27;ve created your temporary profile &lt;em&gt;exactly&lt;&#x2F;em&gt; as described – thusly:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;`&#x2F;usr&#x2F;libexec&#x2F;PlistBuddy -c &amp;quot;Print :PayloadContent:10:PayloadContent&amp;quot; ~&#x2F;Downloads&#x2F;testfv-unsigned.mobileconfig |base64`&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;aside&gt;
&lt;p&gt;Copy and paste this to the same location in your edited
&lt;code&gt;template-fde-recovery-key-escrow.mobileconfig&lt;&#x2F;code&gt; file, making sure you get the
indentation correct. Save this file with a suitable name like &lt;code&gt;FileVault Recovery Key Escrow.mobileconfig&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Sign the new profile thusly:&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;security cms -S -N &amp;quot;Common Name of signing certificate in your keychain&amp;quot; -i &#x2F;path&#x2F;to&#x2F;FileVault\ Recovery\ Key Escrow.mobileconfig -o &#x2F;path&#x2F;to&#x2F;Signed-FileVault\ Recovery\ Key\ Escrow.mobileconfig
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Delete the temporary configuration profile from your Jamf Pro Server.&lt;&#x2F;li&gt;
&lt;li&gt;Upload your completed &lt;code&gt;Signed-FileVault Recovery Key Escrow.mobileconfig&lt;&#x2F;code&gt;
profile to your Jamf Pro Server, then set an appropriate scope and deploy it.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;references&quot;&gt;References&lt;&#x2F;h4&gt;
&lt;p&gt;This article was originally published as a
&lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;haircut&#x2F;b4fb2a102b7e25ef35b0826922967fb3&quot;&gt;Gist&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;opragel&quot;&gt;@opragel&lt;&#x2F;a&gt; for the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;opragel&#x2F;profiles&#x2F;blob&#x2F;master&#x2F;macOS%20-%20Escrow%20FileVault%202%20Recovery%20Keys.mobileconfig&quot;&gt;template&#x2F;example configuration profile&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
        </item>
    </channel>
</rss>