Skip to content

The Ultimate SentinelOne Deployment Guide for Kandji

Published: at 05:41 PM

Working in IT and Security is ever-evolving. You are always being introduced to new problems, daunting projects, and emerging threats. Fortunately, at times you come across a way to simplify your life.

In my previous SentinelOne posts (Here and Here), I walked you through how to use Kandji to deploy SentinelOne and a few profiles. It was an easy enough process but after a recent chat with a fellow IT Guru (thanks Campbell) I was able to make the process a little easier to manage and maintain.

So, are you ready to make SentinelOne deployments and upkeep fade into the background in your already busy life? Me too, let’s jump in!


What changed?

The major changes to the process are as follows:


Step 1: Creating and Uploading the Configuration Profiles

Before installing SentinelOne, you need to deploy six essential configuration profiles to each Mac device:

  1. S1 - Service Management
  2. S1 - Full Disk Access
  3. S1 - Network Filtering
  4. S1 - Network Monitoring
  5. S1 - Notifications
  6. S1 - Token

These profiles grant SentinelOne the permissions it needs to monitor and protect your devices effectively. Skipping this step will most likely lead to issues down the road. For instance, if you don’t have the Network Filtering and Monitoring profiles installed prior to installing the SentinelOne PKG, you’ll most likely run into connectivity issues on the device and/or annoying pop-ups.

Below are the XML contents for each profile. Each one can be found on GitHub where all you’ll need to do is download them and make a minor change for the Token profile prior to uplodading into Kandji. If you prefer the manual path, just copy and paste these into a text document, save them as a .mobileconfig and upload them.

1. S1 - Service Management.mobileconfig

Grab on GitHub

This profile manages components that run at startup, ensuring SentinelOne’s services are not removed.

<?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">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadIdentifier</key>
<string>com.apple.servicemanagement.E01FDD5D-6953-4F89-AE9C-98EC6AF31483</string>
<key>PayloadType</key>
<string>com.apple.servicemanagement</string>
<key>PayloadUUID</key>
<string>E01FDD5D-6953-4F89-AE9C-98EC6AF31483</string>
<key>Rules</key>
<array>
<dict>
<key>Comment</key>
<string>Prevent removal of SentinelOne Launch Agents and Launch Daemons</string>
<key>RuleType</key>
<string>LabelPrefix</string>
<key>RuleValue</key>
<string>com.sentinelone.</string>
</dict>
<dict>
<key>Comment</key>
<string>Prevent removal of SentinelOne Launch Agents and Launch Daemons</string>
<key>RuleType</key>
<string>BundleIdentifierPrefix</string>
<key>RuleValue</key>
<string>com.sentinelone.</string>
</dict>
</array>
</dict>
</array>
<key>PayloadDescription</key>
<string>Manage components that run at start up</string>
<key>PayloadDisplayName</key>
<string>S1 - Service Management</string>
<key>PayloadIdentifier</key>
<string>com.kandji.profile.custom.171d06c6-d781-4756-9371-fbd5f91b23e5</string>
<key>PayloadOrganization</key>
<string>Sentinel Labs, Inc.</string>
<key>PayloadRemovalDisallowed</key>
<true/>
<key>PayloadScope</key>
<string>System</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>998ba1a8-d0f9-5b57-bb75-967dc12f9799</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist>

2. S1 - Full Disk Access.mobileconfig

Grab on GitHub

This profile grants SentinelOne full disk access.

<?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">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadDescription</key>
<string></string>
<key>PayloadDisplayName</key>
<string>Privacy Preferences Policy Control</string>
<key>PayloadIdentifier</key>
<string>236FFBB3-159D-4A5F-B146-AAA7BBA11FF0</string>
<key>PayloadOrganization</key>
<string>Your Company</string>
<key>PayloadType</key>
<string>com.apple.TCC.configuration-profile-policy</string>
<key>PayloadUUID</key>
<string>236FFBB3-159D-4A5F-B146-AAA7BBA11FF0</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>Services</key>
<dict>
<key>SystemPolicyAllFiles</key>
<array>
<dict>
<key>Allowed</key>
<integer>1</integer>
<key>CodeRequirement</key>
<string>anchor apple generic and identifier "com.sentinelone.sentineld" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = "4AYE5J54KN")</string>
<key>Identifier</key>
<string>com.sentinelone.sentineld</string>
<key>IdentifierType</key>
<string>bundleID</string>
<key>StaticCode</key>
<integer>0</integer>
</dict>
<dict>
<key>Allowed</key>
<integer>1</integer>
<key>CodeRequirement</key>
<string>anchor apple generic and identifier "com.sentinelone.sentineld-helper" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = "4AYE5J54KN")</string>
<key>Identifier</key>
<string>com.sentinelone.sentineld-helper</string>
<key>IdentifierType</key>
<string>bundleID</string>
<key>StaticCode</key>
<integer>0</integer>
</dict>
<dict>
<key>Allowed</key>
<integer>1</integer>
<key>CodeRequirement</key>
<string>anchor apple generic and identifier "com.sentinelone.sentineld-shell" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = "4AYE5J54KN")</string>
<key>Identifier</key>
<string>com.sentinelone.sentineld-shell</string>
<key>IdentifierType</key>
<string>bundleID</string>
<key>StaticCode</key>
<integer>0</integer>
</dict>
</array>
</dict>
</dict>
</array>
<key>PayloadDescription</key>
<string>Provides access to all disk to Sentinel One processes</string>
<key>PayloadDisplayName</key>
<string>S1 - Full Disk Access</string>
<key>PayloadIdentifier</key>
<string>com.kandji.profile.custom.c8e2c703-2228-4b77-a251-b488b4e36104</string>
<key>PayloadOrganization</key>
<string>Sentinel Labs, Inc.</string>
<key>PayloadRemovalDisallowed</key>
<true/>
<key>PayloadScope</key>
<string>System</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>d7da0976-c4e7-5a82-8c3e-c3853cb51a85</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist>

3. S1 - Network Filtering.mobileconfig

Grab on GitHub

This profile authorizes automatic validation of SentinelOne network filtering.

<?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">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>FilterDataProviderBundleIdentifier</key>
<string>com.sentinelone.network-monitoring</string>
<key>FilterDataProviderDesignatedRequirement</key>
<string>identifier "com.sentinelone.network-monitoring" and anchor apple generic and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = "4AYE5J54KN")</string>
<key>FilterGrade</key>
<string>firewall</string>
<key>FilterPackets</key>
<false/>
<key>FilterSockets</key>
<true/>
<key>FilterType</key>
<string>Plugin</string>
<key>PayloadDisplayName</key>
<string>Web Content Filter Payload</string>
<key>PayloadIdentifier</key>
<string>14DDD990-E2D8-4DD1-8CC6-72FEFB5F252B</string>
<key>PayloadOrganization</key>
<string>JAMF Software</string>
<key>PayloadType</key>
<string>com.apple.webcontent-filter</string>
<key>PayloadUUID</key>
<string>14DDD990-E2D8-4DD1-8CC6-72FEFB5F252B</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PluginBundleID</key>
<string>com.sentinelone.extensions-wrapper</string>
<key>UserDefinedName</key>
<string>SentinelOne Extensions</string>
</dict>
</array>
<key>PayloadDescription</key>
<string>Authorizes SentinelOne Network Filter automatic validation.</string>
<key>PayloadDisplayName</key>
<string>S1 - Network Filtering</string>
<key>PayloadIdentifier</key>
<string>com.kandji.profile.custom.b2733b15-44c2-41e0-a958-08dc2086b1d4</string>
<key>PayloadOrganization</key>
<string>Sentinel Labs, Inc.</string>
<key>PayloadRemovalDisallowed</key>
<true/>
<key>PayloadScope</key>
<string>System</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>c44d89ec-1790-5c05-a407-590166aeeb68</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist>

4. S1 - Network Monitoring.mobileconfig

Grab on GitHub

This profile enables automatic loading of SentinelOne’s system extension for network monitoring.

NOTE: It is possible to replace this profile within Kandji by using a System Extension versus a custom profile.

<?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">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>AllowUserOverrides</key>
<true/>
<key>AllowedSystemExtensions</key>
<dict>
<key>4AYE5J54KN</key>
<array>
<string>com.sentinelone.network-monitoring</string>
</array>
</dict>
<key>PayloadDescription</key>
<string></string>
<key>PayloadDisplayName</key>
<string>System Extensions</string>
<key>PayloadIdentifier</key>
<string>1BDD5153-6C81-4E0F-B409-1C321FF5E251</string>
<key>PayloadOrganization</key>
<string>Gete.Net Consulting</string>
<key>PayloadType</key>
<string>com.apple.system-extension-policy</string>
<key>PayloadUUID</key>
<string>1BDD5153-6C81-4E0F-B409-1C321FF5E251</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</array>
<key>PayloadDescription</key>
<string>Enables automatic loading of SentinelOne System Extension.</string>
<key>PayloadDisplayName</key>
<string>S1 - Network Monitoring</string>
<key>PayloadIdentifier</key>
<string>com.kandji.profile.custom.91444b37-8d15-46e9-a689-a52d526671c9</string>
<key>PayloadOrganization</key>
<string>Sentinel Labs, Inc.</string>
<key>PayloadRemovalDisallowed</key>
<true/>
<key>PayloadScope</key>
<string>System</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>e392826e-b758-5e39-959a-ed4f813ab1d9</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist>

5. S1 - Notifications.mobileconfig

Grab on GitHub

Lastly, this profile forces acceptance of all notifications from the SentinelOne agent.

<?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">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>NotificationSettings</key>
<array>
<dict>
<key>AlertType</key>
<integer>1</integer>
<key>BadgesEnabled</key>
<true/>
<key>BundleIdentifier</key>
<string>com.sentinelone.SentinelAgent</string>
<key>CriticalAlertEnabled</key>
<true/>
<key>GroupingType</key>
<integer>0</integer>
<key>NotificationsEnabled</key>
<true/>
<key>ShowInCarPlay</key>
<false/>
<key>ShowInLockScreen</key>
<true/>
<key>ShowInNotificationCenter</key>
<true/>
<key>SoundsEnabled</key>
<true/>
</dict>
</array>
<key>PayloadDisplayName</key>
<string>Notifications</string>
<key>PayloadIdentifier</key>
<string>com.apple.notificationsettings.406D4B22-BE3A-4361-8C7B-B8ECE25BC8D6</string>
<key>PayloadType</key>
<string>com.apple.notificationsettings</string>
<key>PayloadUUID</key>
<string>2EA2BDB3-83CE-40DB-B3DF-33BD0094F0DF</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</array>
<key>PayloadDescription</key>
<string>Forces notifications for SentinelOne Agent</string>
<key>PayloadDisplayName</key>
<string>S1 - Notifications</string>
<key>PayloadEnabled</key>
<true/>
<key>PayloadIdentifier</key>
<string>com.kandji.profile.custom.26783496-95e2-48d9-949b-d71a37181592</string>
<key>PayloadOrganization</key>
<string>Sentinel Labs, Inc.</string>
<key>PayloadScope</key>
<string>System</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>cbcf5c85-c136-5cbd-b69a-2ce35ffd00d3</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>TargetDeviceType</key>
<integer>5</integer>
</dict>
</plist>

6. S1 - Token.mobileconfig

Grab on GitHub

Lastly, this profile forces acceptance of all notifications from the SentinelOne agent.

NOTE: You need to replace the string “SITE OR GROUP TOKEN HERE” in the xml to get this to work properly. You can get your Site or Group Token from the SentinelOne admin console.

Something to be mindful of with this method over the old method: This will make the Site or Group token viewable in plain text if someone were to open the profile in the System Settings app. Some may see this as a security risk. If you do, just refer back to my previous guides to inject the Token using a Pre-Install script that you can delete after the installation is complete. I plan on creating a method to encrypt the profile to prevent this but that is a ways off.

<?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">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadType</key>
<string>com.sentinelone.registration-token</string>
<key>PayloadIdentifier</key>
<string>1908502B-DFFE-43A8-ABEC-E0830251CB67</string>
<key>PayloadUUID</key>
<string>1908502B-DFFE-43A8-ABEC-E0830251CBF5</string>
<key>S1InstallRegistrationToken</key>
<string>SITE OR GROUP TOKEN HERE</string>
</dict>
</array>
<key>PayloadDescription</key>
<string>SentinelOne agent registration token</string>
<key>PayloadDisplayName</key>
<string>S1 - Token</string>
<key>PayloadIdentifier</key>
<string>CF822211-476A-47D6-BA6F-0A3333804A49</string>
<key>PayloadOrganization</key>
<string>SentinelOne</string>
<key>PayloadRemovalDisallowed</key>
<true/>
<key>PayloadScope</key>
<string>System</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>1908502B-DFFE-43A8-ABEC-E0830251CB53</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist>

Uploading Profiles to Kandji

Here’s how to get these profiles into Kandji:

  1. Upload to Kandji:
    • Log in to your Kandji dashboard.
    • Navigate to Library > Add New > Configuration Profile.
    • Create and Upload each .mobileconfig file separately.
  2. Assign Profiles to Devices:
    • Add the profiles to the relevant Blueprints or Assignment Maps.
    • Ensure these profiles are deployed before installing SentinelOne.

Important Notes about Profiles

Step 2: Adding SentinelOne as a Custom App

We’ll be using Kandji’s Custom App Library item to deploy SentinelOne. The process involves:

  1. Creating your audit script: Ensures that all the profiles are properly installed prior to installing SentinelOne.
  2. Setting up the Custom App in Kandji: Configuring the installation details and uploading your packaged file.
  3. Add Custom app to your Assignment Maps or Blueprints.

1. Audit Script

The audit script checks if the required profiles are installed on the device. If they aren’t, the script exits, preventing the installation from proceeding. This ensures that SentinelOne doesn’t get installed without the necessary profiles, which could cause issues like loss of internet connectivity.

Grab on GitHub

#!/bin/bash
# Array of required profiles
REQUIRED_PROFILES=(
"S1 - Full Disk Access"
"S1 - Network Filtering"
"S1 - Network Monitoring"
"S1 - Notifications"
"S1 - Service Management"
"S1 - Token"
)
# Function to check if a profile is installed
check_profile_installed() {
local profile_name=$1
profiles_list=$(profiles -C -v | awk -F: '/attribute: name/{print $NF}')
if echo "$profiles_list" | grep -F -q "$profile_name"; then
return 0
else
return 1
fi
}
# Check each required profile
for profile in "${REQUIRED_PROFILES[@]}"; do
if ! check_profile_installed "$profile"; then
echo "Error: $profile is not installed."
exit 0
fi
done
echo "All required profiles are installed. Proceeding to check for SentinelOne..."
# Check if SentinelOne is installed
if [ -d "/Library/Sentinel/sentinel-agent.bundle/Contents/MacOS/SentinelAgent.app" ]; then
echo "SentinelOne is installed."
exit 0
else
echo "SentinelOne is not installed. Starting install process."
exit 1
fi

What This Script Does:

2. Set Up the Custom App in Kandji

Let’s configure the Custom App in Kandji.

  1. Create a New Library Item:
    • Go to your Kandji dashboard and add a new Custom App library item.
    • Select Audit and Enforce for the installation method.
  2. Add the Audit Script from Step 1.
  3. Configure Installation Details:
    • Deployment Type: Uncheck Self Service to deploy silently.
    • Installation Type: Select Installer Package.
    • Upload Latest SentinelOne pkg File: You can find the latest package inside the SentinelOne management console. Go to Endpoints > Packages > and grab the latest macOS version.
    • Optional: Select Restart after successful install if you’d like to make sure everything is installed properly and reporting back to SentinelOne.

3. Deploying your Custom App

With everything set up:

Final Thoughts

I developed this method because there didn’t seem to be a reliable guide that covered all the nuances of deploying SentinelOne with Kandji. By sharing my scripts and process, I hope to save you time and headaches.

Feedback Welcome!

If you have suggestions to improve these scripts or the deployment process, I’d love to hear them. Collaboration makes us all better at what we do.

Happy deploying!

If you found this guide helpful or have questions, don’t hesitate to reach out. Managing a Mac environment can be challenging, but with the right tools and shared knowledge, we can make it a smoother experience for everyone.

Thanks for reading (not) Your IT Guru! Make sure you Subscribe to my Substack to get the latest updates from me.


Previous Post
Creating a GCal Event Subscription Form - Part 1
Next Post
Deploying SentinelOne Profiles for Mac