Deploying Apple beta program tokens using Blueprints in Jamf Pro

As discussed in a previous post, Apple provides tokens which allow devices to be enrolled in Apple’s beta programs without the need for the user to sign in with an Apple Account on the device.

You can use Blueprints in Jamf Pro to distribute these tokens, using the Software Update Settings component in Blueprints. Let’s see how this works using the following software update configuration as an example:

  • Macs are enrolled in the macOS Tahoe beta program.
  • Macs cannot opt out of participating in the macOS Tahoe beta program.

For more details, please see below the jump.

Pre-requisites:

 

As of Jamf Pro 11.23.1, there is not a Blueprints template available for creating blueprints which manage software updates so the blueprint will need to be configured manually. To do this, use the following procedure:

1. Log into Jamf Pro.

2. Select Blueprints

3. Click the Create blueprint button.

 

4. You should see an unconfigured Blueprint. Click where it says Untitled blueprint and provide a name.

 

For this example, I’m using Apple Beta Tokens.

 

5. Scroll down in the list on the left-hand side of the browser window to locate the Software Update Settings component.

 

6. Click on the Software Update Settings component and drag the Software Update Settings component to the Declaration group section.

Drag software update settings component.

 

7. Once added to the Declaration group section, click anywhere on the Software Update Settings component to open it for editing.

8. At this point, you will see all available Software Update settings which are available for all Apple platforms. To apply the desired beta program settings, select the following option:

Beta Updates

Click the associated Configure button.

In the Program enrollment section, select the following:

  • Check the checkbox for Program enrollment
  • Select the Always option

Once the Always option is selected, two additional options should appear:

  • Require program
  • Offer programs

Select the Require program option.

Once the Require program option has been selected, a new set of entry blanks should appear:

  • Apple Business Manager or Apple School Manager beta enrollment token
  • Description

For the Apple Business Manager or Apple School Manager beta enrollment token entry, enter the token for the macOS Tahoe beta program.

For the Description entry, enter whatever you want in plain text. For this example, I’m entering the following text:

macOS Tahoe beta program

Once all choices have been made and verified, click the Update button.

 

9. Once all the settings choices have been made and verified, click the Save button.

 

10. At this point, you should have a blueprint which has all settings configured but where no target scope has been set. To scope this blueprint, go to the Scope section and click the arrow button.

 

For this example, I’m selecting a static group named Beta Software Deployment Group. Once the desired smart and/or static groups have been set and verified for the scope, click the Save button.

 

11. Once everything has been configured, click the Deploy button to deploy the changes to the Macs you want to manage.

 

12. Once deployed, the Blueprints screen in Jamf Pro should show the newly-created Apple Beta Tokens Blueprint as being deployed.

 

You can also check on the managed device’s end by opening System Settings: General: Device Management, locating the MDM enrollment profile in the list of profiles and double-clicking on it. When you scroll to the bottom of the enrollment profile’s window, you should see a Device Declarations section.

If you’re deploying a software update settings configuration via Blueprints, you should see a Software Update Settings listing for Software Update in the Device Declarations section.

 

If you click on the Software Update Settings listing, it should report the following for the beta program settings:

  • Beta program enrollment: AlwaysOn
  • Require Specific Beta Program: macOS Tahoe beta program

You can also see the details of what’s configured in System Settings: General: Software Update. In this case, it’s showing the latest macOS Tahoe beta version available for installation.

 

You can also click on the ( i ) button next to the Beta Updates section and see the settings which have been applied, as well as a notification that the settings are managed.

Obtaining Apple beta program tokens

As discussed in an earlier post, you can sign up for Apple’s AppleSeed for IT program using a user with the Administrator role in Apple Business Manager or Apple School Manager and subsequently obtain tokens which allow devices to be enrolled in Apple’s beta programs without the need for the user to sign in with an Apple Account on the device.

Apple has documentation available on how to obtain these tokens using an API call to the following endpoint:

https://mdmenrollment.apple.com/os-beta-enrollment/tokens

However, the documentation does not include the specifics on how to set up the API call or the necessary OAuth authentication for it. Fortunately, the folks at HCS Technology Group have published a technical article showing how to obtain the necessary tokens using the following:

For more details, please see below the jump.

I’m going to be using the process described in the HCS technical article to do the following:

1. Set up a new Device Management Services server in Apple Business Manager.
2. Use the getBetaTokens script to do the following:

  • Generate a public key for the new Device Management Services server.
  • Use the ADE token from the new Device Management Services server as a source for the necessary OAuth credentials for the API call to the https://mdmenrollment.apple.com/os-beta-enrollment/tokens endpoint
  • Authenticate to the API endpoint and fetch all available Apple beta tokens associated with an organization’s AppleSeed for IT program.
  • Display all available beta tokens

Pre-requisites:

1. Log into Apple Business Manager using a managed Apple Account with the Administrator or Device Manager role. In the case of my example, I am using an account with the Administrator role.
2. At the bottom left corner of the browser, click on the menu and select Preferences.

3. Click the Add button for the Device Management Services section.

4. Name the new Device Management Services server. For this example, I’m choosing to name it as Apple Beta Tokens.

Note: You will not be able to save changes to the new Device Management Services server until a public key is uploaded.

5. Launch the getBetaTokens script. You should see output similar to this:


[INFO] No .p7m found in ./abm_auth.
[ACTION] A certificate will be generated – upload the PEM to ABM, then
download the issued *.p7m token (it usually lands in ~/Downloads).
[INFO] No .p7m found: generating key + self-signed cert…
Generating RSA private key, 2048 bit long modulus
.+++++
…………………………………………+++++
e is 65537 (0x10001)
Signature ok
subject=/CN=Your MDM Server
Getting Private key
[ACTION] Upload this PEM to Apple Business Manager (Settings → MDM Servers)
────────────────────────────────────────────────────────────────
—–BEGIN CERTIFICATE—–
MIICsDCCAZgCCQD5GClF1eAa6DANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9Z
b3VyIE1ETSBTZXJ2ZXIwHhcNMjYwMTA2MTQxMzI5WhcNMjcwMTA2MTQxMzI5WjAa
MRgwFgYDVQQDDA9Zb3VyIE1ETSBTZXJ2ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQDPVjJynmJ3QJNTwrMACJ467WB1zvASfJWKIXFzKKIhdXZBgAXi
FqlLgXUi3J0sai9mrfbVI0yfnlOpaGws/t3lZ/4riKyfTj8IxSHSebwdDzHQR/8Q
5+B884wXdxs9FuWodvQ0EdGHMKkm5HaEc//m261JvadoT0LhScq1DT3Izv8Gd8k1
v5HjshNxZLSkqj4La7phb++bGem+nDXtItyykY7D5310xYl7XT6bGgM/s7QbvObj
BuIKTkKLwtmlfU+Di4acqJ89VjuX6gnUxmn4YmNTCCWiT5v6GxvSbtzHQsLSD6Qk
mac43pbeG/NFwSjR+YoyYLkdFuB0BUDcC0glAgMBAAEwDQYJKoZIhvcNAQELBQAD
ggEBAIMUxul28kUTmFN8NT6bbjXPweORwtqiqEi3Y36ti2ING6Q2g+F29O7w5hrj
bweGIHvON8V+oEzKWCQIDboCCD5iPa/EEaFhsy9/v/4jvPlrtW6c9eU8QOzCupSY
Gyxfhg70M4cQCOl2G1eXsbzroLtJKmFMkpy8rCdMrFgaHW2/Xvw/cLDgQryDBSu3
Z7RAGRB+0QtG/qpMG/8oFhc32ZqdqPa+8L1HvxILYqf7zDRXrfyA1peI5dsmiPB2
X+2BWL5iAO/vl86XD8NO+ZKO82AzZXRVbTNRb0lSrweWMlbrC3u/plL2hiPDp6bj
wBLo/hybOuVUGFmbPvTbjHMZdis=
—–END CERTIFICATE—–
────────────────────────────────────────────────────────────────
After ABM issues you a *.p7m server token, drop it into this directory.
[INFO] Watching /Users/username/Downloads for NEW *.p7m files (every 5s)…

view raw

gistfile1.txt

hosted with ❤ by GitHub

Note: Leave the script running, as it is watching for the ADE token which will be downloaded from Apple Business Manager later in this process.

In the directory you’re currently in for running the script, you should see a new abm_auth directory. This was created by the getBetaTokens script for storing the public key needed for the new Device Management Services server which was just created in Apple Business Manager.

Inside the abm_auth directory, there should be a file named mdm_public_cert.pem. This is the public key you need to upload to the new Device Management Services server in Apple Business Manager.

6. Get the mdm_public_cert.pem file and upload it to the Apple Beta Tokens Device Management Services server in Apple Business Manager.
7. Once the mdm_public_cert.pem file gas been uploaded to the Apple Beta Tokens server, click the Save button to save the changes.

8. Verify that the changes were saved successfully and that there is now an Apple Beta Tokens server appearing in Apple Business Manager.
9. In the Apple Beta Tokens server listing, click the Download Token button to download the ADE token associated with the Apple Beta Tokens server.

10. Confirm that you want to download the ADE token by clicking the Download Token button in the confirmation window.

11. The getBetaTokens script should detect the downloaded ADE token and then take the following actions automatically:

  • Use the ADE token as a source for the necessary OAuth credentials for the API call to the https://mdmenrollment.apple.com/os-beta-enrollment/tokens endpoint.
  • Authenticate to the API endpoint and fetch all available Apple beta tokens associated with an organization’s AppleSeed for IT program.
  • Display all available beta tokens.

Once the script has completed running, you should see output similar to this:


[INFO] No .p7m found in ./abm_auth.
[ACTION] A certificate will be generated – upload the PEM to ABM, then
download the issued *.p7m token (it usually lands in ~/Downloads).
[INFO] No .p7m found: generating key + self-signed cert…
Generating RSA private key, 2048 bit long modulus
.+++++
…………………………………………+++++
e is 65537 (0x10001)
Signature ok
subject=/CN=Your MDM Server
Getting Private key
[ACTION] Upload this PEM to Apple Business Manager (Settings → MDM Servers)
────────────────────────────────────────────────────────────────
—–BEGIN CERTIFICATE—–
MIICsDCCAZgCCQD5GClF1eAa6DANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9Z
b3VyIE1ETSBTZXJ2ZXIwHhcNMjYwMTA2MTQxMzI5WhcNMjcwMTA2MTQxMzI5WjAa
MRgwFgYDVQQDDA9Zb3VyIE1ETSBTZXJ2ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQDPVjJynmJ3QJNTwrMACJ467WB1zvASfJWKIXFzKKIhdXZBgAXi
FqlLgXUi3J0sai9mrfbVI0yfnlOpaGws/t3lZ/4riKyfTj8IxSHSebwdDzHQR/8Q
5+B884wXdxs9FuWodvQ0EdGHMKkm5HaEc//m261JvadoT0LhScq1DT3Izv8Gd8k1
v5HjshNxZLSkqj4La7phb++bGem+nDXtItyykY7D5310xYl7XT6bGgM/s7QbvObj
BuIKTkKLwtmlfU+Di4acqJ89VjuX6gnUxmn4YmNTCCWiT5v6GxvSbtzHQsLSD6Qk
mac43pbeG/NFwSjR+YoyYLkdFuB0BUDcC0glAgMBAAEwDQYJKoZIhvcNAQELBQAD
ggEBAIMUxul28kUTmFN8NT6bbjXPweORwtqiqEi3Y36ti2ING6Q2g+F29O7w5hrj
bweGIHvON8V+oEzKWCQIDboCCD5iPa/EEaFhsy9/v/4jvPlrtW6c9eU8QOzCupSY
Gyxfhg70M4cQCOl2G1eXsbzroLtJKmFMkpy8rCdMrFgaHW2/Xvw/cLDgQryDBSu3
Z7RAGRB+0QtG/qpMG/8oFhc32ZqdqPa+8L1HvxILYqf7zDRXrfyA1peI5dsmiPB2
X+2BWL5iAO/vl86XD8NO+ZKO82AzZXRVbTNRb0lSrweWMlbrC3u/plL2hiPDp6bj
wBLo/hybOuVUGFmbPvTbjHMZdis=
—–END CERTIFICATE—–
────────────────────────────────────────────────────────────────
After ABM issues you a *.p7m server token, drop it into this directory.
[INFO] Watching /Users/username/Downloads for NEW *.p7m files (every 5s)…
[INFO] New token detected in Downloads: Apple Beta Tokens_Token_2026-01-06T14-34-12Z_smime.p7m
[INFO] Using token: Apple Beta Tokens_Token_2026-01-06T14-34-12Z_smime.p7m
[INFO] Using server token file: Apple Beta Tokens_Token_2026-01-06T14-34-12Z_smime.p7m
[INFO] Stripping S/MIME wrapper…
[INFO] Got credentials:
consumer_key: CK_1e4d6861e5128e0c09442ee391372853b632f86f0a0dbcbdb529f027b41b1640bb44f070927ac8ef6b9ce4945d511bef
consumer_secret: CS_9b17c3892bdd3e7e8034463a9b304e86df8eaddd
access_token: AT_d0716b39b2873fd7cd7e343b5f6a9219a84809fba44c6288280fc23148ab09834b7
access_secret: AS_6c4fedc231c3926f977a8e86f7581a8f593ac1aa
access_expires: 2027-01-06T14:34:12Z
[INFO] Building OAuth header for session request…
[INFO] Requesting session token…
[INFO] Got session token.
[INFO] Fetching beta-enrollment tokens…
[INFO] Available beta programs:
┌-────────────────────────────────────────────-┬-───────────-┬-──────────────────────────────────────────────────────────────────-┐
│ Title │ OS │ Token │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ HomePod Software Version 26 AppleSeed Beta │ homePodOS │ 9d35ff2ca4e2492152d04031d630469391637958491c83e1c1539c48b5cf5c06 │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ iOS 17 AppleSeed Beta │ iOS │ 24e356c81d8a098e04d3bf82779d67a28e305d4e24cd1a9546d251994e32b1da │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ iOS 18 AppleSeed Beta │ iOS │ 1c6fe5f0634e68febfef70ae4626b78c100ed296427fbd9a1dad67ab6392bad2 │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ iOS 26 AppleSeed Beta │ iOS │ 61050ef1a94375ff11a3e2f9ff99ef5dbc7bea2dfe668c37860e4e71b0b093c9 │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ macOS Sequoia AppleSeed Beta │ OSX │ b4e921e359674c25c2f817492165c69038e9958c545e89e9bbfe6b20d02f40c8 │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ macOS Sonoma AppleSeed Beta │ OSX │ 34dd8dc5d19041ac63a31ebf92181420daeca9e5aa6046aa0afcfdd784353668 │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ macOS Tahoe 26 AppleSeed Beta │ OSX │ 70c8dbad03ceebea86740896534f5a8c2c642aeda1a88da761624191eb645bcf │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ macOS Ventura AppleSeed Beta │ OSX │ 030f48e140fd2a56746110cce9ea9e28f6de77b88db97f0017268a81a35ee566 │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ tvOS 18 AppleSeed Beta │ tvOS │ 2f7c8e19f55074aaf51777c24095ecb2769a33fa4780ad455f17b063decb6b59 │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ tvOS 26 AppleSeed Beta │ tvOS │ 401524581deff669552b54c0453bfe239b2805c4dd020bf13febc76952b2d79b │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ visionOS 2 AppleSeed Beta │ visionOS │ baaf1821c91089bae867fb8b818d05294a4792727e0397bc330c45a7307246c9 │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ visionOS 26 AppleSeed Beta │ visionOS │ 052a00ee15378a0dbfbd39aeb56b0bdbdc6045158eed66e89ad783dc54e43b77 │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ visionOS Developer Beta │ visionOS │ 22de2a21e91429784629b57ff799517a4e17e2f32ef57070eda2bfb6b2d50d01 │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ watchOS 10 AppleSeed Beta │ watchOS │ a65af647ba503701ddabea524268024054a8ae0dade489c840e76f699c25171f │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ watchOS 11 AppleSeed Beta │ watchOS │ 70f21b58c49a912b001b1be48577209f9fe85daec53771723eef26115f2f64b2 │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ watchOS 26 AppleSeed Beta │ watchOS │ bd3f1eb7389456276f683c08dc325e74aa2ee4c8c65a6e8549a444b2f51f31c6 │
├-────────────────────────────────────────────-┼-───────────-┼-──────────────────────────────────────────────────────────────────-┤
│ watchOS 9 AppleSeed Beta │ watchOS │ 749eeac5442b5d5b66ea2aeaf029ec15eb30a380ebc759b108018830042b3682 │
└-────────────────────────────────────────────-┴-───────────-┴-──────────────────────────────────────────────────────────────────-┘

view raw

gistfile1.txt

hosted with ❤ by GitHub

The token(s) for the Apple platform(s) you want to run beta testing for should be identifiable from the script output.

Note: All OAuth credential and token information in the output shown above have been replaced with non-working randomly generated values.

Signing up for AppleSeed for IT using Apple Business Manager

Apple’s AppleSeed for IT program is designed to help enterprise and education customers test beta versions of Apple’s software.

To assist with making it easier to test these beta versions on devices, it’s possible for a user with the Administrator role in Apple Business Manager or Apple School Manager to accept the AppleSeed program’s terms and conditions on behalf of their organization. In turn, this will enable devices to be enrolled in Apple’s beta programs without the need for the user to sign in with an Apple Account on the device. For more details on how to do this, please see below the jump.

Pre-requisites:

  • Apple Business Manager or Apple School Manager instance for your organization
  • Managed Apple Account with the Administrator role for that Apple Business Manager or Apple School Manager instance

1. Sign into the Apple Business Manager or Apple School Manager instance via a web browser using a managed Apple Account with the Administrator role.
2. At the bottom left corner of the browser, click on the menu and select Preferences.

3. Select Beta Features.
4. Click the Begin Enrollment button.

5. At the Agreement window, read through the Apple Beta Software Program Agreement agreement.
6. Once you’ve read through the agreement, click the Agree button.

7. At the Program window, click the Join button for the AppleSeed for IT program.

8. At the Agreement window, read through the AppleSeed for IT agreement.
9. Once you’ve read through the agreement, click the Agree button.

Once you’ve agreed to the AppleSeed for IT agreement, you should now be signed into the AppleSeed for IT website.

With this program signup completed, you should now be able to enroll devices in an Apple beta program using a token. The token-based enrollment method removes the need to sign into the device using an Apple Account. For more details on how to do this, please see the link below:

https://support.apple.com/guide/deployment/test-software-updates-appleseed-beta-program-depe8583cf10/web

Why macOS 26 build numbers begin with 25

A question I’ve seen pop up in the Mac Admins Slack since the release of macOS Tahoe 26.x goes something like this:

Why does macOS 26 have a build number that starts with 25?

The answer has to do with Darwin, the core operating system that is the foundation for all of the following Apple operating systems:

For more details, please see below the jump.

The Darwin operating system has its own version number which is separate from the version number of the other Apple operating systems. In the case of macOS, Apple includes Darwin’s version number in the macOS build number. For example, the build number for macOS Tahoe 26.2.0 is the following:

25C56

The 25 part refers to the major version number for the current Darwin release. Beginning in 2011, the major version numbers of the Darwin operating system have coincided with the last two digits of the year it was released:



Darwin Version Release Date
11.0.0 July 20 2011
12.0.0 February 16 2012
13.0.0 June 11 2013
14.0.0 September 18 2014
15.0.0 September 16 2015
16.0.0 September 13 2016
17.0.0 September 19 2017
18.0.0 September 24 2018
19.0.0 September 19 2019
20.0.0 June 22 2020
21.0.0 June 7 2021
22.0.0 June 6 2022
23.0.0 September 18 2023
24.0.0 September 16 2024
25.0.0 September 15 2025

The current Darwin operating system release is 25.2.0 as of macOS Tahoe 26.2.0, so macOS Tahoe build numbers start with 25. Unless Apple decides to change Darwin’s version numbering system, this will mean that future macOS releases will continue to have build numbers that will start with a two digit number that is one number less than the macOS major version number.

Using printf to write variable values to JSON strings in Bash scripts

As part of my personal changeover from using the Jamf Pro Classic API to using the Jamf Pro API, I’ve needed to change from using XML for the Jamf Pro Classic API to now using JSON for the Jamf Pro API. In particular, one of my issues has been figuring out how to properly write variables to JSON when updating something on the Jamf Pro server using the Jamf Pro API. As always when writing scripts, there’s usually multiple ways to solve a problem and I figured out a solution to mine using the printf command. For more details, please see below the jump.

As an example, I had written a post a while back about updating the asset tag number of a Jamf Pro computer inventory record using a script. As part of that script, I was using a command similar to the one below to send the updated asset tag information to the Jamf Pro server, defined in a variable named asset_tag_number_goes_here.


/usr/bin/curl -s –header "Authorization: Bearer api_token_goes_here" "https://jamf.pro.server.here/JSSResource/computers/serialnumber/serial_number_goes_here&quot; -H "Content-Type: application/xml" -X PUT -d "<computer><general><asset_tag>${asset_tag_number_goes_here}</asset_tag></general></computer>"

view raw

gistfile1.txt

hosted with ❤ by GitHub

As part of that command, the following XML string is being sent with the asset_tag_number_goes_here variable being included:


"<computer><general><asset_tag>${asset_tag_number_goes_here}</asset_tag></general></computer>"

view raw

gistfile1.txt

hosted with ❤ by GitHub

The XML string is double quoted, so my script knows to read in the value from the asset_tag_number_goes_here variable because the variable is referenced using the $ character.

When I updated my script to use the Jamf Pro API and JSON, my command now looked similar to this:


/usr/bin/curl -s –header "Authorization: Bearer api_token_goes_here" "https://jamf.pro.server.here/api/v3/computers-inventory-detail/jamf_pro_id_goes_here&quot; -H "Content-Type: application/xml" -X PATCH -d '{"general":{"assetTag":"$asset_tag_number_goes_here"}}'

view raw

gistfile1.txt

hosted with ❤ by GitHub

My JSON string looked like this:


'{"general":{"assetTag":"${asset_tag_number_goes_here}"}}'

view raw

gistfile1.txt

hosted with ❤ by GitHub

However, that didn’t work right and the asset_tag_number_goes_here variable’s value wasn’t being read correctly. Why? Because the JSON string uses single quotes to enclose it and in Bash, enclosing characters in single quotes means every character is being sent exactly as it is written.

How to fix this? The printf command was my eventual solution to the problem because in Bash, you can use printf to write a variable using what’s known as a format specifier. In this case, I needed to use the s format specifier because that will allow a string of characters to be used. To call the s format specifier for printf, %s% should be used.

To set it up, I needed to do the following in my script:

  1. Create the JSON string with %s% in place of ${asset_tag_number_goes_here} and store that JSON string as a variable.
  2. Use printf in a separate variable to create the JSON string and use the s format specifier to substitute the %s  with the value of the asset_tag_number_goes_here variable in the correct place inside the JSON string.
  3. Send the API command and include the JSON string created by printf.

The end result looks similar to this:


# Format a block of JSON and use %s to specify where printf should print a specified variable.
JSONBlockFormat='{"general":{"assetTag":"%s"}}'
# Use printf to create the needed JSON block and write the asset_tag_number_goes_here variable in the correct place in the JSON block.
JSONBlock=$(printf "$JSONBlockFormat" "$asset_tag_number_goes_here")
# Send an API command to update the computer inventory record with the specified asset tag information
/usr/bin/curl -s –header "Authorization: Bearer api_token_goes_here" "https://jamf.pro.server.here/api/v3/computers-inventory-detail/jamf_pro_id_goes_here&quot; -H "Content-Type: application/xml" -X PATCH -d "$JSONBlock"

view raw

gistfile1.txt

hosted with ❤ by GitHub

Reading DDM-managed Apple Software Update settings from the command line on macOS Tahoe 26.2.0

One of the challenges with reporting on DDM settings is that as of macOS Tahoe 26.2.0 there aren’t currently command line tools available which can report back on settings which are managed via DDM declarations. You can see the settings which have been applied on the managed Mac via System Settings, but so far that’s about it. However, in some cases, Apple is writing information for some DDM declarations to files which are readable by command line tools. I recently discovered that one of those declarations was the com.apple.configuration.softwareupdate.settings Software Update Settings declaration. For more details, please see below the jump.

I have an earlier post on the Software Update Settings declaration and how it is used by Jamf Pro’s Blueprints. Using that information, I built and deployed a Software Update Settings declaration which has the following settings:

  • Standard users can’t install Apple software updates
  • Logged-in users will see all software update notifications
  • OS updates will be automatically downloaded
  • OS updates will be automatically installed
  • Security updates will be automatically installed
  • Rapid Security Response updates will be installed
  • Rapid Security Response updates can be removed

Once deployed to managed Macs, you should be able to verify these settings by looking at the Software Update Settings declaration’s listing in System Settings.

You can also verify them by checking the following file:

/var/db/softwareupdate/SoftwareUpdateDDMStatePersistence.plist

On a managed Mac with those DDM settings running macOS Tahoe 26.2.0, the SoftwareUpdateDDMStatePersistence.plist file should show information similar to what’s shown below:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
<plist version="1.0">
<dict>
<key>SUCorePersistedStateContentsType</key>
<string>SoftwareUpdateCorePersistedStateFile</string>
<key>SUCorePersistedStateCoreFields</key>
<dict/>
<key>SUCorePersistedStateCoreSecureCodedObjectsFields</key>
<dict/>
<key>SUCorePersistedStateCoreVersion</key>
<string>2.1.0</string>
<key>SUCorePersistedStatePolicyFields</key>
<dict>
<key>SUCoreDDMDeclarationGlobalSettings</key>
<dict>
<key>adminInstallRequired</key>
<integer>1</integer>
<key>automaticallyDownload</key>
<integer>1</integer>
<key>automaticallyInstallOSUpdates</key>
<integer>1</integer>
<key>automaticallyInstallSystemAndSecurityUpdates</key>
<integer>1</integer>
<key>enableGlobalNotifications</key>
<true/>
<key>enableRapidSecurityResponse</key>
<true/>
<key>enableRapidSecurityResponseRollback</key>
<true/>
<key>serializedKeys</key>
<array>
<string>com.apple.RemoteManagement.SoftwareUpdateExtension.GlobalSettings/811362F1-10F1-4D2F-BFB7-F97393F3F44C:Qmx1ZXByaW50XzM3MTllZWRlLTI0MjUtNGE2ZC04YjljLTIyMGViMzMwYWQ2NF9zMV9jMV9zeXNfY2ZnMQ==.NDg5NTdiNjZkYmUwMWM3YzM2MzcwMTJjNTkxZTg4MWM1ZDk3YTNkMWUxZTI1MjI0NTYwMmJlNjQ0MTFmYjdkOA==</string>
</array>
</dict>
</dict>
<key>SUCorePersistedStatePolicySecureCodedObjectsFields</key>
<dict/>
<key>SUCorePersistedStatePolicyVersion</key>
<string>1.0</string>
</dict>
</plist>

From there, you can use tools like PlistBuddy to read the values stored in the /var/db/softwareupdate/SoftwareUpdateDDMStatePersistence.plist file. For example, the following command should read the value for the enableRapidSecurityResponse key from the SoftwareUpdateDDMStatePersistence.plist file.


/usr/libexec/PlistBuddy -c "Print :SUCorePersistedStatePolicyFields:SUCoreDDMDeclarationGlobalSettings:enableRapidSecurityResponse" /var/db/softwareupdate/SoftwareUpdateDDMStatePersistence.plist

view raw

gistfile1.txt

hosted with ❤ by GitHub

If Rapid Security Response updates are set to be installed, that should give you a value of true:


username@Z6WCW076MR ~ % /usr/libexec/PlistBuddy -c "Print :SUCorePersistedStatePolicyFields:SUCoreDDMDeclarationGlobalSettings:enableRapidSecurityResponse" /var/db/softwareupdate/SoftwareUpdateDDMStatePersistence.plist
true
username@Z6WCW076MR ~ %

view raw

gistfile1.txt

hosted with ❤ by GitHub

To the best of my knowledge, this method of verification is undocumented by Apple and they could choose to change it at any time. That said, if you’re looking for a way to report on Software Update Settings declaration settings, this is a way to do it as of macOS Tahoe 26.2.0.

PPPC device management settings visible in System Settings on macOS Tahoe 26.2.0

As part of the What’s new for enterprise in macOS Tahoe 26 release notes for macOS Tahoe 26.2.0, there’s this note:

App privacy permissions configured by device management are now shown in System Settings > Privacy & Security.

What this indicates is that a long-standing feature request by Mac admins has been fulfilled by Apple. For more details, please see below the jump.

As part of macOS 10.14 Mojave, Apple introduced a number of privacy controls for user data. At the same time, Apple also introduced device management options to allow authorized applications to access data protected by those privacy controls. These permissions are referred to collectively as Privacy Preferences Policy Control (PPPC) and are deployed via management profiles from an MDM server. However, up until macOS Tahoe 26.2, there was no way to see in the Privacy & Security section of System Settings which applications had which permissions granted via PPPC management profiles.

As an example, by default, Macs managed by Jamf Pro will get a management profile which allows the Jamf agent permission to access data stored in the user home folder via the PPPC permission known as full disk access. Here’s how this looks on macOS Tahoe 26.1.0:

Privacy Preferences Policy Control profile installed which enables full disk access to the Jamf agent.

No mention of the full disk access permissions granted to the Jamf agent in the Privacy & Security section of System Settings.

How this looks on macOS Tahoe 26.2.0:

Privacy Preferences Policy Control profile installed which enables full disk access for the Jamf agent.

Full disk access permissions granted to the Jamf agent are disclosed in the Privacy & Security section of System Settings. It is also disclosed that the permissions setting is configured by a profile.

Updating management status in Jamf Pro computer inventory records using the Jamf Pro API

A while back, I wrote a post on how to set Jamf Pro computer inventory records to be managed using a script. I recently revisited this script as part of a general effort on my part to update scripts which have been using the now-deprecated computers Classic API endpoint, to now use the Jamf Pro API’s computers-inventory-detail API endpoint.

As part of this effort, I decided to not only update my existing script for setting the management status in Jamf Pro computer inventory records to be managed but also write a second script for setting the management status to be unmanaged. For more details, please see below the jump.

You can set the management status in a Jamf Pro computer inventory record using the computers-inventory-detail endpoint for the Jamf Pro API. The API command to change the management status in a Jamf Pro computer inventory record to Managed should look similar to this:


/usr/bin/curl -H "Content-Type: application/json" "https://jamf.pro.server.here/api/v3/computers-inventory-detail/jamf_pro_computer_ID_goes_here&quot; –header "Authorization: Bearer api_token_goes_here" -X PATCH -d '{"general":{"managed":"true"}}'

view raw

gistfile1.txt

hosted with ❤ by GitHub

It’s sending the following JSON block to update the relevant computer inventory record and make the management change:


{
"general": {
"managed": "true"
}
}

view raw

gistfile1.txt

hosted with ❤ by GitHub

The API command to change the management status in a Jamf Pro computer inventory record to Not Managed should look similar to this:


/usr/bin/curl -H "Content-Type: application/json" "https://jamf.pro.server.here/api/v3/computers-inventory-detail/jamf_pro_computer_ID_goes_here&quot; –header "Authorization: Bearer api_token_goes_here" -X PATCH -d '{"general":{"managed":"false"}}'

view raw

gistfile1.txt

hosted with ❤ by GitHub

It’s sending the following JSON block to update the relevant computer inventory record and make the management change:


{
"general": {
"managed": "false"
}
}

view raw

gistfile1.txt

hosted with ❤ by GitHub

I was able to use the API information discussed above to create a couple of scripts which a) update the management status in specified computer inventory records and b) generates a report of the Macs whose computer inventory records were updated.

The scripts are named Set_Jamf_Pro_Computers_To_Managed_Status.sh and Set_Jamf_Pro_Computers_To_Unmanaged_Status.sh and are available via the links below:

https://github.com/rtrouton/rtrouton_scripts/tree/main/rtrouton_scripts/Casper_Scripts/Set_Jamf_Pro_Computers_To_Managed
https://github.com/rtrouton/rtrouton_scripts/tree/main/rtrouton_scripts/Casper_Scripts/Set_Jamf_Pro_Computers_To_Unmanaged

Both scripts are designed to take in a set of Jamf Pro ID numbers in a plaintext file, where the Jamf Pro ID numbers correspond the Macs where you want to change the management status in their Jamf Pro computer inventory records. The plaintext file should look similar to this:


416462
842736
434703
338517
481915
596669

view raw

gistfile1.txt

hosted with ❤ by GitHub

Four items are required to use these scripts:

  • A text file containing the Jamf Pro IDs of the computer(s) you wish to delete.
  • The URL of the appropriate Jamf Pro server.
  • The username of an account on the Jamf Pro server with sufficient privileges to delete computers from the Jamf Pro server.
  • The password for the relevant account on the Jamf Pro server.
  • Jamf Pro account privileges required by the Jamf Pro server account referenced above:

Jamf Pro Server Objects:

  • Computers: Read, Update
  • Users: Update

Once the four specified items are available, the scripts can be run using the following commands:

For Set_Jamf_Pro_Computers_To_Managed_Status.sh:


/path/to/Set_Jamf_Pro_Computers_To_Managed_Status.sh /path/to/plaintext_filename_here.txt

view raw

gistfile1.txt

hosted with ❤ by GitHub

For Set_Jamf_Pro_Computers_To_Unmanaged_Status.sh:


/path/to/Set_Jamf_Pro_Computers_To_Unmanaged_Status.sh /path/to/plaintext_filename_here.txt

view raw

gistfile1.txt

hosted with ❤ by GitHub

For Set_Jamf_Pro_Computers_To_Managed_Status.sh, you should see output that looks like this:


username@computername ~ % /Users/Shared/Set_Jamf_Pro_Computers_To_Managed/Set_Jamf_Pro_Computers_To_Managed_Status.sh /Users/Shared/jamfpro_computer_ids.txt
Please enter your Jamf Pro server URL : https://jamf.pro.server.here
Please enter your Jamf Pro user account : username_goes_here
Please enter the password for the username_goes_here account:
Report being generated. File location will appear below once ready.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=416462 from unmanaged to managed.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=842736 from unmanaged to managed.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=434703 from unmanaged to managed.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=338517 from unmanaged to managed.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=481915 from unmanaged to managed.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=596669 from unmanaged to managed.
Report on Macs available here: /var/folders/ps/2_yw29gj711c9d7c5w5jhyv80000gp/T/tmp.eFStgTqa5l.tsv
username@computername ~ %

view raw

gistfile1.txt

hosted with ❤ by GitHub

As part of the script’s run, a report will be generated and you’ll be notified of where it is stored. The report will be in TSV format and appear similar to what’s shown below:



Jamf Pro ID Number Make Model Serial Number UDID Computer Management Status Jamf Pro URL
416462 Apple MacBook Pro (16-inch, 2019) WD8JB8F49YS4 4D8CD419-1892-4CFE-8D18-D1DD53CC7970 Managed https://jamf.pro.server.here/computers.html?id=416462
842736 Apple MacBook Pro (16-inch, 2019) R6JG7GYVNORW 904418F7-3695-44BF-9A00-74F5CF617377 Managed https://jamf.pro.server.here/computers.html?id=842736
434703 Apple MacBook Pro (16-inch, 2019) FWPATJHWC92O 5CF418CE-3E46-481C-A171-7ACC9E1E2E7A Managed https://jamf.pro.server.here/computers.html?id=434703
338517 Apple MacBook Pro (16-inch, 2019) CVZVJ8R55467 E82C6C63-5F49-4DD3-90A0-E01EC11F6954 Managed https://jamf.pro.server.here/computers.html?id=338517
481915 Apple MacBook Pro (13-inch, M1, 2020) QL6ROPPB1SK5 CBC87B4C-28DA-417F-8790-411AF9F105AD Managed https://jamf.pro.server.here/computers.html?id=481915
596669 Apple MacBook Pro (16-inch, 2021) CNA11CBMJSNI 72811617-8C97-4EB6-BC4B-B9FA9C87B259 Managed https://jamf.pro.server.here/computers.html?id=596669

For Set_Jamf_Pro_Computers_To_Unmanaged_Status.sh, you should see output that looks like this:


username@computername ~ % /Users/Shared/Set_Jamf_Pro_Computers_To_Unmanaged/Set_Jamf_Pro_Computers_To_Unmanaged_Status.sh /Users/Shared/jamfpro_computer_ids.txt
Please enter your Jamf Pro server URL : https://jamf.pro.server.here
Please enter your Jamf Pro user account : username_goes_here
Please enter the password for the username_goes_here account:
Report being generated. File location will appear below once ready.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=416462 from managed to unmanaged.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=842736 from managed to unmanaged.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=434703 from managed to unmanaged.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=338517 from managed to unmanaged.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=481915 from managed to unmanaged.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=596669 from managed to unmanaged.
Report on Macs available here: /var/folders/ps/2_yw29gj711c9d7c5w5jhyv80000gp/T/tmp.6Ic4bx2sT8.tsv
username@computername ~ %

view raw

gistfile1.txt

hosted with ❤ by GitHub

As part of the script’s run, a report will be generated and you’ll be notified of where it is stored. The report will be in TSV format and appear similar to what’s shown below:



Jamf Pro ID Number Make Model Serial Number UDID Computer Management Status Jamf Pro URL
416462 Apple MacBook Pro (16-inch, 2019) WD8JB8F49YS4 4D8CD419-1892-4CFE-8D18-D1DD53CC7970 Unmanaged https://jamf.pro.server.here/computers.html?id=416462
842736 Apple MacBook Pro (16-inch, 2019) R6JG7GYVNORW 904418F7-3695-44BF-9A00-74F5CF617377 Unmanaged https://jamf.pro.server.here/computers.html?id=842736
434703 Apple MacBook Pro (16-inch, 2019) FWPATJHWC92O 5CF418CE-3E46-481C-A171-7ACC9E1E2E7A Unmanaged https://jamf.pro.server.here/computers.html?id=434703
338517 Apple MacBook Pro (16-inch, 2019) CVZVJ8R55467 E82C6C63-5F49-4DD3-90A0-E01EC11F6954 Unmanaged https://jamf.pro.server.here/computers.html?id=338517
481915 Apple MacBook Pro (13-inch, M1, 2020) QL6ROPPB1SK5 CBC87B4C-28DA-417F-8790-411AF9F105AD Unmanaged https://jamf.pro.server.here/computers.html?id=481915
596669 Apple MacBook Pro (16-inch, 2021) CNA11CBMJSNI 72811617-8C97-4EB6-BC4B-B9FA9C87B259 Unmanaged https://jamf.pro.server.here/computers.html?id=596669

In addition to the scripts described above which use user accounts for authentication, there are also matching scripts which use API client authentication available on GitHub via the links above. If setting up an API client with limited rights, here are the required API role privileges for the API client on the Jamf Pro server:

  • Computers Read
  • Computers Update
  • Users Update

New application version smart group and advanced computer search criteria available as of Jamf Pro 11.23.0

In macOS, applications record version information in the Information Property List file. This file is stored inside the Contents directory of the application bundle and is named Info.plist.

There are two keys inside the Info.plist file for an application which store version information:

What’s the difference between the two?

  • CFBundleVersion: This is the version information used by macOS to determine which version is the most recent version of an application.
  • CFBundleShortVersionString: This is the version information which is displayed to the user in a Finder window or a Get Info window.

There is no requirement in macOS that both the CFBundleVersion and CFBundleShortVersionString keys in the Info.plist file contain the same version information. What can happen as a result? Let’s take a look at that the context of some Microsoft applications which record different information in the Info.plist file for those two keys. For more details, please see below the jump.

For this example, I installed the following Microsoft apps on a macOS 26.1.0 VM:

  • Microsoft Excel.app
  • Microsoft PowerPoint.app
  • Microsoft OneNote.app
  • Microsoft Outlook.app
  • Microsoft Word.app
  • OneDrive.app
  • Windows App.app

For each app, I checked the following:

  • CFBundleShortVersionString
  • CFBundleVersion
  • Reported version on the Mac

Microsoft Excel.app

  • CFBundleShortVersionString: 16.103.3
  • CFBundleVersion: 16.103.25113013
  • Reported version on the Mac: 16.103.3

Microsoft PowerPoint.app

  • CFBundleShortVersionString: 16.103.3
  • CFBundleVersion: 16.103.25113013
  • Reported version on the Mac: 16.103.3

Microsoft OneNote.app

  • CFBundleShortVersionString: 16.103.3
  • CFBundleVersion: 16.103.25113013
  • Reported version on the Mac: 16.103.3

Microsoft Outlook.app

  • CFBundleShortVersionString: 16.103.3
  • CFBundleVersion: 16.103.25113013
  • Reported version on the Mac: 16.103.3

Microsoft Word.app

  • CFBundleShortVersionString: 16.103.3
  • CFBundleVersion: 16.103.25113013
  • Reported version on the Mac: 16.103.3

OneDrive.app

  • CFBundleShortVersionString: 25.209.1026
  • CFBundleVersion: 25209.1026.0002
  • Reported version on the Mac: 25.209.1026

Windows App.app

  • CFBundleShortVersionString: 11.2.9
  • CFBundleVersion: 2810
  • Reported version on the Mac: 11.2.9

As you can observe, what’s reported in these two fields can be very different. How does this affect Jamf Pro? Up until Jamf Pro 11.23.0, only one of those keys in the Info.plist file was being used to get version information for a macOS application:

CFBundleShortVersionString

This was reported as part of a computer inventory record as the following field:

  • Version

The Version reporting also has matching smart group and advanced computer search criteria:

  • Application Version

However, version information for Microsoft applications in particular were often being reported in Jamf Pro using the information contained in the following key:

  • CFBundleVersion

If CFBundleVersion and CFBundleShortVersionString did not have the same version information, now you have a problem because what you see in Jamf Pro for version information for that Microsoft app and what you’re seeing reported in a Finder window for version infomation are two different things. To help address this, as of Jamf Pro 11.23 two new reporting fields as well as matching smart group and advanced computer search criteria have been added:

  • Bundle Short Version
  • Bundle Version

Here’s how they’re mapping to the keys in the application’s Info.plist file:

  • Bundle Short Version: CFBundleShortVersionString
  • Bundle Version: CFBundleVersion

The existing Version reporting field and matching Application Version smart group and advanced computer search criteria have not gone away, since up until Jamf Pro 11.23 it was your only option. The new reporting information has been added and does not replace previously gathered data, so nothing in anyone’s existing version reporting setup should break.

Here’s how it should look as of Jamf Pro 11.23.0 for a computer inventory record’s application listing:

  • Name
  • Version
  • Bundle Short Version
  • Bundle Version
  • Path
  • App Store

Note: The Bundle Short Version and Bundle Version fields may initially be blank for devices which have not sent in an inventory update since Jamf Pro was upgraded to 11.23.

The matching smart group and advanced computer search criteria are as follows:

  • Applications inventory listing: Bundle Short Version
  • Smart and advanced computer search criteria: Application Bundle Short Version

  • Applications inventory listing: Bundle Version
  • Smart and advanced computer search criteria: Application Bundle Version

Suppressing the Welcome to macOS Tahoe 26 screen with a configuration profile on macOS Tahoe 26.1.0

Over the years, Apple has introduced a number of screens which appear the first time you log into a Mac. Among those which appear following an upgrade to macOS Tahoe 26 is the Welcome to macOS Tahoe 26 screen, which provides a walkthrough of selected new features available in macOS Tahoe.

I have not found a way to suppress this screen using a defaults command, but it is possible to suppress the Welcome to macOS Tahoe 26 screen on macOS Tahoe 26.1.0 using a configuration profile. For more details, please see below the jump.

The relevant preference domain and key values are below:

  • Preference domain: com.apple.SetupAssistant.managed
  • Key: SkipSetupItems
  • Value: OSShowcase

The profile is available on GitHub via the link below:

https://github.com/rtrouton/profiles/blob/main/SkipOSShowcaseSetup