Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions Jamf-Device-Compliance-Prompt/Jamf Device Compliance Prompt.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#!/bin/zsh
# shellcheck shell=bash

# Mobile Device Apps Report
# Inetum Polska Sp. z o.o.
# Author: Dawid Konopnicki
# Revision: 20260119

# ===============================================================
# Jamf Pro – Prompt user to run Self Service policy
# ===============================================================
#
# This script displays a macOS dialog to the currently logged-in user
# and, after confirmation, opens Jamf Self Service directly to a
# specific policy using a deep link.
#
# Typical use cases:
# - Device compliance registration (Azure AD / Entra ID)
# - Required post-enrollment setup steps
# - User-driven remediation workflows
#
# The script is intended to be executed from Jamf Pro as part of a
# policy, where the policy ID to open is provided as a script parameter.
#
# ---------------------------------------------------------------
# Requirements:
# - macOS
# - Jamf Pro–managed device
# - Jamf Self Service installed
#
# Jamf Script Parameters:
# Parameter 4 = POLICY_ID (required)
# ---------------------------------------------------------------
#

# REQUIRED:
# The ID of the Jamf Pro policy that should be opened in Self Service.
# This value must be provided as Script Parameter 4 in Jamf Pro.
POLICY_ID="${4:-}"

# Customize this text to match your organization’s wording.
DIALOG="Please finish setting up your computer by running the Register Mac Device with Entra ID in Self Service. Click OK to get started!"

# Abort early if the required parameter is missing.
if [[ -z "${POLICY_ID}" ]]; then
echo "ERROR: POLICY_ID not provided. Set Script Parameter 4 in Jamf Pro."
exit 1
fi

# Identify the currently logged-in GUI user.
LOGGED_IN_USER="$(scutil <<<"show State:/Users/ConsoleUser" | awk '/Name :/ && !/loginwindow/ { print $3 }')"

if [[ -z "${LOGGED_IN_USER}" ]]; then
echo "ERROR: Unable to determine logged-in user."
exit 1
fi

# Path to the Self Service branding image.
ICON="/Users/${LOGGED_IN_USER}/Library/Application Support/com.jamfsoftware.selfservice.mac/Documents/Images/brandingimage.png"

# Jamf stores the Self Service app path in its preferences.
# This allows support for renamed or relocated Self Service apps.
SELF_SERVICE_PATH="$(/usr/bin/defaults read /Library/Preferences/com.jamfsoftware.jamf.plist self_service_app_path 2>/dev/null)"

if [[ -z "${SELF_SERVICE_PATH}" ]]; then
SELF_SERVICE_PATH="$(/usr/bin/defaults read /Library/Preferences/com.jamfsoftware.jamf.plist self_service_plus_path 2>/dev/null)"
if [[ -z "${SELF_SERVICE_PATH}" ]]; then
echo "Couldn't extract Self Service path."
exit 1
fi
fi

# Read the bundle display name from the app’s Info.plist.
# Self Service vs Self Service+ variant.
SELF_SERVICE_VARIANT="$(/usr/bin/defaults read "${SELF_SERVICE_PATH}/Contents/Info.plist" CFBundleName 2>/dev/null)"

#If a branded icon exists, include it in the dialog.
#Otherwise, fall back to a standard dialog to avoid errors.
if [[ -f "${ICON}" ]]; then
ANSWER=$(
osascript <<EOF
button returned of (display dialog "$DIALOG" buttons {"OK"} default button 1 with icon POSIX file "$ICON")
EOF
)
else
ANSWER="$(
/usr/bin/osascript <<EOF
button returned of (display dialog "${DIALOG}" buttons {"OK"} default button 1)
EOF
)"
fi

if [[ "${ANSWER}" == "OK" ]]; then

# If Self Service is already running, terminate it.
# This ensures the deep link opens reliably
if [[ $(pgrep "Self Service" | grep -c .) -gt 2 ]]; then
/usr/bin/pkill "Self Service"
fi

# Determine which URL scheme to use as it differs depending on Self Service Variant.
if [[ "$SELF_SERVICE_VARIANT" == *"+"* ]]; then
URL_SCHEME="selfservicecapability"
else
URL_SCHEME="jamfselfservice"
fi

# Open Self Service directly to the specified policy.
/usr/bin/su "${LOGGED_IN_USER}" -c "/usr/bin/open \"${URL_SCHEME}://content?entity=policy&id=${POLICY_ID}&action=view\""
fi

exit 0
68 changes: 68 additions & 0 deletions Jamf-Device-Compliance-Prompt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)
![Platform](https://img.shields.io/badge/platform-macOS-lightgrey)
![Jamf](https://img.shields.io/badge/managed%20by-Jamf-black)
![Shell](https://img.shields.io/badge/shell-zsh-green)

# Jamf Pro – Device Compliance Prompt

A super simple zsh script for Jamf Pro that prompts the currently logged-in macOS user with a dialog, and (after they click **OK**) opens **Jamf Self Service** directly to a specific **policy** using a deep link.

# Jamf Pro – Device Compliance Prompt

A super simple zsh script for Jamf Pro that prompts the currently logged-in macOS user with a dialog, and (after they click **OK**) opens **Jamf Self Service** directly to a specific **policy** using a deep link.

## What this can be used for

Typical use cases:
- Device compliance / registration workflows (Azure AD / Entra ID)
- Required post-enrollment steps
- User-driven remediation (e.g., “click here to run the fix”)

## How it works (high level)

1. Jamf Pro runs the script (via policy).
2. The script detects the currently logged-in GUI user.
3. It displays a macOS dialog (optionally with the Self Service branding image if available).
4. When the user clicks **OK**, it opens Self Service (or Self Service+) to a specific policy ID via deep link.

<img width="488" height="232" alt="image" src="https://github.com/user-attachments/assets/51fa5dc0-69fb-4fb7-8ed4-d8fa4b4dca74" />


## Requirements

- macOS
- Jamf Pro–managed device
- Jamf Self Service installed (Self Service or Self Service+)

## Jamf Script Parameters

- **Parameter 4**: `POLICY_ID` *(required)*
This is the Jamf Pro Policy ID you want to open in Self Service.

If Parameter 4 is missing, the script exits with an error.

## Setup (Jamf Pro)

1. Upload the script to **Settings → Computer Management → Scripts**
2. In the policy where you run this script, set:
- **Script Parameter 4** = the target **Policy ID**
3. (Optional) Customize the dialog text by editing the `DIALOG` variable in the script.

## Notes

- The script reads the Self Service app path from:
- `/Library/Preferences/com.jamfsoftware.jamf.plist` (`self_service_app_path` or `self_service_plus_path`)
- It automatically selects the correct URL scheme depending on whether the app is **Self Service** or **Self Service+**
- If Self Service appears to be running, the script may terminate it first to make the deep link open reliably

## Example deep link behavior

When the user clicks **OK**, Self Service opens to:

`...://content?entity=policy&id=<POLICY_ID>&action=view`

## License

Licensed under the Apache License, Version 2.0.
Copyright © 2026 Inetum Poland.
Authored by Dawid Konopnicki.
Loading