Deploying service background tasks using Blueprints in Jamf Pro
苹果宣布macOS 15 Sequoia及后续版本支持通过Declarative Device Management (DDM) 管理防篡改文件以运行后台服务任务。这些任务可由LoginAgents或LoginDaemons触发,并可通过Jamf Pro的Blueprints进行部署和管理。 2025-6-10 17:30:46 Author: derflounder.wordpress.com(查看原文) 阅读量:7 收藏

As part of Apple’s discussion of Declarative Device Management (DDM) at WWDC 2024, Apple announced that DDM management on macOS 15 Sequoia and later now included the ability to manage sets of tamper-resistant files which run tasks either on behalf of the logged-in user or which run with root privileges to provide services in the background. Running these tasks may involve any of the following:

  • Executable binaries
  • Scripts
  • Configuration files for the tools being used

In turn, these tools are triggered by the following LaunchD items:

  • Launch agents – to run the task for the logged-in user
  • Launch daemons – to run the task with root privileges

Jamf Pro’s Blueprints supports deploying and managing these service background tasks via the Service background tasks component. Let’s see how this looks, using the following example:

Goal

Using a service background task to run a Jamf Pro inventory update each time the managed Mac starts up.

Tools used

  • A script to run a Jamf Pro inventory update using the Jamf agent
  • A LaunchDaemon to run the script when the Mac starts up.

For more details, please see below the jump.

To deploy this script and LaunchDaemon with Blueprints as a service background task, several things are needed. To start with, we need the following:

  1. The script
  2. The LaunchDaemon

The script is named runjamfproinventoryupdate.sh and is available below:


#!/bin/zsh –no-rcs
# This script runs the following actions:
#
# 1. Verifies that it can connect to the Jamf Pro server which manages this Mac.
# 2. Once verification is successful, an inventory update is sent to the Jamf Pro server
/usr/local/jamf/bin/jamf checkJSSConnection -retry 60 && /usr/local/jamf/bin/jamf recon
exit 0

The LaunchDaemon file is named com.github.runjamfproinventoryupdate.plist and is available below:

One thing to note is that the LaunchDaemon is running the runjamfproinventoryupdate.sh script at the following location:

/private/var/db/ManagedConfigurationFiles/BackgroundTaskServices/Services/com.github.runjamfproinventoryupdate/runjamfproinventoryupdate.sh

/private/var/db/ManagedConfigurationFiles/BackgroundTaskServices/Services is the tamper-resistant directory where macOS is storing the executable binaries, scripts, etc. it uses to run service background tasks. The LaunchAgents and LaunchDaemons are stored in separate tamper-resistant directories within /private/var/db/ManagedConfigurationFiles/BackgroundTaskServices:

  • LaunchAgents: /private/var/db/ManagedConfigurationFiles/BackgroundTaskServices/LaunchAgents
  • LaunchDaemons: /private/var/db/ManagedConfigurationFiles/BackgroundTaskServices/LaunchDaemons

Meanwhile, the runjamfproinventoryupdate.sh script is itself being stored inside a com.github.runjamfproinventoryupdate directory. This directory is named to match the label of the LaunchDaemon being deployed to run this service background task: com.github.runjamfproinventoryupdate

Once you have the script and the LaunchDaemon available, the following items are needed:

1. A zip file which contains both the directory and file structure of the script in question.

The script is stored in a directory named com.github.runjamfproinventoryupdate and the file is named runjamfproinventoryupdate.sh, so a zip file containing a directory named com.github.runjamfproinventoryupdate, with the script set to be executable and named runjamfproinventoryupdate.sh inside the com.github.runjamfproinventoryupdate directory, is needed for this.

For this example, we’ll name the zip file as com.github.runjamfproinventoryupdate.zip.

2. The SHA-256 hash of the zip file.

You can use the sha256sum command line tool to get the SHA-256 hash of the zip file, so using a command similar to the one shown below should provide that information:


sha256sum /path/to/filename_goes_here

Assuming our SHA-256 hash is 48fa6c5e25590536970e71ae4bdf02c5153dbcb12ae5a3c2c7682ac94e065582, you should see output like this when you run the command above:


username@ZWCM2JG74W ~ % sha256sum /Users/username/Desktop/com.github.runjamfproinventoryupdate.zip
48fa6c5e25590536970e71ae4bdf02c5153dbcb12ae5a3c2c7682ac94e065582 /Users/username/Desktop/com.github.runjamfproinventoryupdate.zip
username@ZWCM2JG74W ~ %

3. The SHA-256 hash of the LaunchDaemon file

Assuming our SHA-256 hash is d913416e04862a8dfa5d58ba9ca045bc8527da7e40b9cdee608d4dcbd4104183, you should see output like this when you run the command above:


username@ZWCM2JG74W ~ % sha256sum /Users/username/Desktop/com.github.runjamfproinventoryupdate.plist
d913416e04862a8dfa5d58ba9ca045bc8527da7e40b9cdee608d4dcbd4104183 /Users/username/Desktop/com.github.runjamfproinventoryupdate.plist
username@ZWCM2JG74W ~ %

4. A place to download the zip and LaunchDaemon files from, which allows downloading without authentication.

For this example, I’ve set up an S3 bucket in Amazon Web Services named 75d831079efb4d02ada44eed4f8ae093 and uploaded the .zip and LaunchDaemon files. Once uploaded, the following files were set to be publicly accessible from that S3 bucket:

  • com.github.runjamfproinventoryupdate.zip
  • com.github.runjamfproinventoryupdate.plist

Once I have all the above available, I can set up a Blueprint in Jamf Pro to deploy the sudo configuration file as a Service configuration file.

1. Log into Jamf Pro.

2. Select Blueprints

3. Click the Open button for Service background tasks.

4. Give it a name when prompted. For this example, I’m using Run Jamf Pro Inventory at Startup.

5. Select a Jamf Pro smart or static group. For this example, I’m selecting a static group named Service Background Task Deployment Group.

6. Provide the necessary information to download the com.github.runjamfproinventoryupdate.zip and com.github.runjamfproinventoryupdate.plist files.

Task Type:

The name provided here must exactly match the label of the LaunchDaemon being deployed to run this service background task. In this case, this means that the name used here is the following:

com.github.runjamfproinventoryupdate

Description:

This is optional, you may fill this in or not as desired.

Executable asset:

This is the zip file with the runjamfproinventoryupdate.sh script inside. For this example, the following information is being used:

Launchd asset #1:

This is the com.github.runjamfproinventoryupdate.plist LaunchDaemon which is triggering the runjamfproinventoryupdate.sh script to run. For this example, the following information is being used:

Important Note

Wherever you’re downloading the LaunchDaemon file from, it’s important that the content headers being provided for that file match what is set for the content type in the service background task’s configuration. Otherwise, what will occur is that the service configuration task will not install on your managed Macs.

While testing this on my end, I initially could not get the configuration to work and couldn’t figure out why until I checked the headers I was getting from Amazon’s S3 service. Those headers looked similar to this:


username@computername ~ % curl -I https://75d831079efb4d02ada44eed4f8ae093.s3.us-east-1.amazonaws.com/com.github.runjamfproinventoryupdate.plist
HTTP/1.1 200 OK
x-amz-id-2: bXMExGDQxfF5mgBiaHklA8LPNrOBqpB10r1GPygtJgNmg6L7vDNFS9wNJ41/Z9H3U8SwXKqcoQk=
x-amz-request-id: QENYC85SCPY6EA41
Date: Mon, 09 Jun 2025 15:14:33 GMT
Last-Modified: Mon, 09 Jun 2025 15:10:39 GMT
ETag: "1d92da3d92ac98519e1574b2fa56f5af"
x-amz-server-side-encryption: AES256
Accept-Ranges: bytes
Content-Type: binary/octet-stream
Content-Length: 521
Server: AmazonS3
username@computername ~ %

The Content-Type header was reporting the following:

Content-Type: binary/octet-stream

Fortunately, I was able to change the content type by using the AWS CLI tool to run the following command to force the content-header I wanted for the com.github.runjamfproinventoryupdate.plist LaunchDaemon file:


aws s3 cp s3://S3_BUCKET_HERE/ s3://S3_BUCKET_HERE/ –exclude '*' –include 'com.github.runjamfproinventoryupdate.plist' –no-guess-mime-type –content-type="application/xml" –metadata-directive="REPLACE" –recursive

Note: S3_BUCKET_HERE is a placeholder for the name of the actual S3 bucket being used.

Once that was done, the headers now looked like this:


username@computername ~ % curl -I https://75d831079efb4d02ada44eed4f8ae093.s3.us-east-1.amazonaws.com/com.github.runjamfproinventoryupdate.plist
HTTP/1.1 200 OK
x-amz-id-2: bXMExGDQxfF5mgBiaHklA8LPNrOBqpB10r1GPygtJgNmg6L7vDNFS9wNJ41/Z9H3U8SwXKqcoQk=
x-amz-request-id: QENYC85SCPY6EA41
Date: Mon, 09 Jun 2025 16:43:13 GMT
Last-Modified: Mon, 09 Jun 2025 16:10:33 GMT
ETag: "1d92da3d92ac98519e1574b2fa56f5af"
x-amz-server-side-encryption: AES256
Accept-Ranges: bytes
Content-Type: application/xml
Content-Length: 521
Server: AmazonS3
username@computername ~ %

Now that the Content-Type header was reporting the following to match the application/xml content type set for my configuration, the configuration applied successfully:

Content-Type: application/xml

Returning to our example, once all the information has been entered and verified to be correct, click the Save button.

Once everything has been configured, Jamf Pro should inform you that you have undeployed changes. Click the Deploy button to deploy the changes to the Macs you want to manage.

Once deployed, the Blueprints screen in Jamf Pro should show the newly-created Run Jamf Pro Inventory at Startup blueprint as being deployed.

On your managed devices, you can verify that the new service background task configuration has been deployed by clicking on the enrollment profile, then scrolling to the bottom.

In the case of this example, you should see a Device Declarations section with a listing for Background Tasks: com.github.runjamfproinventoryupdate.

If you click on the Background Tasks: com.github.runjamfproinventoryupdate listing, it should report the following:

  • It has an executable file – this is the runjamfproinventoryupdate.sh script
  • The count of Daemon plist files – This reflects that only the com.github.runjamfproinventoryupdate.plist LaunchDaemon was deployed.
  • The count of Agent plist files – This reflects that no LaunchAgents were deployed.


文章来源: https://derflounder.wordpress.com/2025/06/10/deploying-service-background-tasks-using-blueprints-in-jamf-pro/
如有侵权请联系:admin#unsafe.sh