Self Service policy to display a list of Static Groups and prompt for Mac serial number to add to one of them

sdagley
Esteemed Contributor II

I'm looking for a simple way to allow members of my org's Field Support group to enable software in Self Service for any of our managed Macs without actually giving them access to our JSS. I use a Static Group as a target for each installation Policy that isn't scoped to all computers, so what I'm envisioning is a shell script that will run an AppleScript to display a popup listing the available titles, and then prompt for the serial number of the computer to be added to the appropriate Static Group using the Classic API (that's the easy part).

I thought I'd seen something along these lines posted on Jamf Nation before (looking at you @dan-snelson), but darn if I can find it now. Before I re-invent the wheel I figured I'd see if it rang a bell with anyone else. Please post a reference if it does

Thanks!

2 ACCEPTED SOLUTIONS

jcarr
Release Candidate Programs Tester

Having the Jamf Pro username and password in the script might not be the best idea.

Have you thought about a Self Service policy that simply executes a command the touch a file in /var/db (e.g. 'touch /var/db/.myconfig1')? Have the policy update inventory and set up an EA that looks for the presence of this file. You could then create a smart group for devices that have this file. You can have as many of these as you have different configs. You could also take it a step further and have a script that checks if the file is present, and if it is removes it, if not places it (so that it acts as a toggle).

Just a thought. Not exactly what you asked, but this may get you the same result.

View solution in original post

sdagley
Esteemed Contributor II

@cwaldrip Actually I did end up implementing a solution like @jcarr suggested, but I never closed the loop and updated this thread, so thanks for the reminder. Here's the template for the solution I implemented (it's not exactly a solution to the problem in my post to start the thread, but it does address the issue of using the API to add computers to a static group).

 

#!/bin/sh

# Utility - Create Flag File.sh
#
# This script is intended to be used as a script in a Jamf Pro Policy. It will create a
# flag file on a Mac that can be read by an Extended Attribute script which in turn can
# be used as a Smart Group Criteria. This was created to allow Self Service initiated
# scoping of Configuration Profile deployments.
#
# $4 - Path of directory to save Flag File in (will be created if needed)
# $5 - Name of Flag File to create

FlagFilePath="$4"
FlagFileName="$5"

if [ -z "${FlagFilePath}" ] || [ -z "${FlagFileName}" ]; then
    echo "Both the path to the flag file and the flag file name must be provided"
    exit 1
fi

if [ ! -d "${FlagFilePath}" ]; then
    /bin/mkdir "${FlagFilePath}"
fi

/usr/bin/touch "${FlagFilePath}${FlagFileName}"

/usr/local/bin/jamf recon

exit 0
#!/bin/sh

# EA - Template Check For Flag File.sh
#
# One strategy for enabling a Jamf Pro Policy or Configuration Profile is using a Smart Group
# to identify Macs that the Policy or Profile should be deployed to. Some criteria is
# needed to identify a Mac as a member of the target Smart Group. This EA template is a
# mechanism for doing that. If a file exists with the specified name at the specified path
# it will return True, otherwise it returns False. 

FlagFilePath="/Library/SomeOrg/"
FlagFileName="flagfile"
result="False"

if [ -e "${FlagFilePath}${FlagFileName}" ]; then
    result="True"
fi

echo "<result>$result</result>"

 

 

View solution in original post

9 REPLIES 9

dan-snelson
Valued Contributor II

Thanks for the shout-out, @sdagley.

While I haven't tackled your exact use-case — nor seemingly a use-case in its ballpark — the following may prove helpful:
- Your Internal Beta Test Program: Opt-in / Opt-out via Self Service
- Jamf Pro Policy Editor Lite


Proof-of-concept Script

#!/bin/bash

# Proof-of-concept to add computers to a Static Group via the API, based on the computer's serial number
# By: Leslie N. Helou & Dan K. Snelson

jssURL="https://jamfpro.company.com"
jssUser="apiUsernameWithReadWritePrivileges"
jssPass="SuperSecretPassword"
groupName="Group_Name_Without_Spaces"
serialNumber="C03DJ1XYH7WK"

#Submit to Jamf Pro server
echo "Adding Serial Number ${serialNumber} to ${groupName} ..."

/usr/bin/curl -sku ${jssUser}:${jssPass} ${jssURL}/JSSResource/computergroups/name/${groupName} -d "<computer_group><computer_additions><computer><serial_number>${serialNumber}</serial_number></computer></computer_additions></computer_group>" -X PUT -H "Content-Type: text/xml"


exit 0

jcarr
Release Candidate Programs Tester

Having the Jamf Pro username and password in the script might not be the best idea.

Have you thought about a Self Service policy that simply executes a command the touch a file in /var/db (e.g. 'touch /var/db/.myconfig1')? Have the policy update inventory and set up an EA that looks for the presence of this file. You could then create a smart group for devices that have this file. You can have as many of these as you have different configs. You could also take it a step further and have a script that checks if the file is present, and if it is removes it, if not places it (so that it acts as a toggle).

Just a thought. Not exactly what you asked, but this may get you the same result.

mm2270
Legendary Contributor III

I think what you're looking for @sdagley is something like this?

#!/bin/bash

APIUSER="apiusername" ## Or replace with $4 to pass in as parameter
APIPASS="apipassword" ## Or replace with $5 to pass in as parameter
JSSURL="https://your.jamf.server.com"

STATIC_COMPUTER_GROUPS=$(curl -H "Accept: application/xml" -su "${APIUSER}:${APIPASS}" ${JSSURL}/JSSResource/computergroups | xmllint --format - | grep -B1 "<is_smart>false</is_smart>" | awk -F'>|<' '/<name>/{print $3}')

SELECTION=$(/usr/bin/osascript << EOD
tell application "System Events"
activate
set GroupList to do shell script "echo "$STATIC_COMPUTER_GROUPS""
set SelectionList to paragraphs of GroupList
choose from list SelectionList with prompt "Choose a group:"
end tell
EOD)

echo "$SELECTION"

## The rest of your script code goes here

The above will pull a list of your static groups from your server using the API, then pass that into an AppleScript call (converting it to a list) so it can be brought up in a dialog for someone to select.

The only thing about my code as is, is that it may not work without running the entire osascript part as the logged in user. Meaning you might have to throw in a launchctl asuser syntax as shown on many other threads to get it to work correctly. But since this is being run from Self Service, it also may just work as is.

sdagley
Esteemed Contributor II

@dan-snelson Thanks! It may have been your Jamf Pro Policy Editor Lite post I was thinking of, and that will make a good building block to start from.

@jcarr Thanks for the thought, but I specifically need to add a computer to a Static Group to fit into my existing workflow. I have already written multiple scripts to modify group memberships, and I do pass the name and password to access the API as encrypted parameters, but I was looking to steal borrow the code to prompt the user for which group and the machine to add to it.

sdagley
Esteemed Contributor II

@mm2270 Thanks for the input! I'll have a pre-defined list of potential groups as the ones I want the techs to have access to is a small subset of the complete list. And I'll add the launchctl asuser... to be on the safe side as I don't totally trust the context to be the user even when run from Self Service..

mm2270
Legendary Contributor III

Ok, if you have a predefined list, then it's even easier, since there won't be a need to call anything with the API. Just create an AppleScript defined list, like {"Item One","Item Two","Item Three"} etc. in place of the echo line.

AdamCraig
Contributor III

What may be an easier solution is we have several self service policies scoped to the users on our support team. So they can log into self service on anyones computer and then those options show up for them.

That being said this is my "add/delete computer from static group script"
If you don't want to provide API username or pass as variables then it will prompt the user who runs the self service policies for their jamf credentials. If you're techs are running this it may be a good option.

$4 = jamf static group ID
$5 = additions or deletions (needs to be exactly one of those strings to add or delete computers from the provided static group)
$6 = Jamf API user ID $7 = Jamf API user password
$8 = silent ( any string here will cause the script to not give onscreen alerts for success or failure)

#! /bin/bash

jamfproURL="https://companyname.jamfcloud.com"

default_group="918"

computer_name="$2"
current_user="$3"
silent="$8"



if [ -z $4 ]
    then
        groupid="$default_group"
    else
        groupid="$4"
fi

if [ -z $5 ]
    then
        action="additions"
    else
        action="$5"
fi

if [ -z $6 ]
    then
        APIUser=$(/usr/bin/osascript<<END
        tell application "System Events"
        activate
        set the answer to text returned of (display dialog "Please enter your Jamf Username:" default answer "" buttons {"Continue"} default button 1)
        end tell
        END)
    else
        APIUser="$6"
fi

if [ -z $7 ]
    then
        APIPass=$(/usr/bin/osascript<<END
        tell application "System Events"
        activate
        set the answer to text returned of (display dialog "Please enter your Jamf Password:" default answer "" with hidden answer buttons {"Continue"} default button 1)
        end tell
        END)
    else
        APIPass="$7"
fi

xml="<computer_group><computer_${action}><computer><name>$computer_name</name></computer></computer_${action}></computer_group>"

fullURL="${jamfproURL}/JSSResource/computergroups/id/${groupid}"

echo "Created XML"
echo $xml

echo "Jamf API URL"
echo $fullURL


result=$`curl "$fullURL" -u "$APIUser:$APIPass" -H "Content-Type: text/xml" -X PUT -d "$xml"`

echo "result"
echo "$result"

if [ -z $silent ] ; then
    if [[ "$result" == *"<p>The request requires user authentication</p>"* ]] ; then
        echo "Showing Fail message"
        /usr/bin/osascript -e 'tell app "System Events" to display dialog "Failed to update Static Group. Please check your network connection and try again."'
    else
        echo "Showing success message"
        dialog="${action} for the Static Group probably sucessful."
        cmd="Tell app "System Events" to display dialog "$dialog""
        /usr/bin/osascript -e "$cmd"
    fi
else
    echo "running silent No user notifications"
fi
exit 0

cwaldrip
Valued Contributor

I really like @jcarr 's solution myself. Especially since the API access is changing too.

sdagley
Esteemed Contributor II

@cwaldrip Actually I did end up implementing a solution like @jcarr suggested, but I never closed the loop and updated this thread, so thanks for the reminder. Here's the template for the solution I implemented (it's not exactly a solution to the problem in my post to start the thread, but it does address the issue of using the API to add computers to a static group).

 

#!/bin/sh

# Utility - Create Flag File.sh
#
# This script is intended to be used as a script in a Jamf Pro Policy. It will create a
# flag file on a Mac that can be read by an Extended Attribute script which in turn can
# be used as a Smart Group Criteria. This was created to allow Self Service initiated
# scoping of Configuration Profile deployments.
#
# $4 - Path of directory to save Flag File in (will be created if needed)
# $5 - Name of Flag File to create

FlagFilePath="$4"
FlagFileName="$5"

if [ -z "${FlagFilePath}" ] || [ -z "${FlagFileName}" ]; then
    echo "Both the path to the flag file and the flag file name must be provided"
    exit 1
fi

if [ ! -d "${FlagFilePath}" ]; then
    /bin/mkdir "${FlagFilePath}"
fi

/usr/bin/touch "${FlagFilePath}${FlagFileName}"

/usr/local/bin/jamf recon

exit 0
#!/bin/sh

# EA - Template Check For Flag File.sh
#
# One strategy for enabling a Jamf Pro Policy or Configuration Profile is using a Smart Group
# to identify Macs that the Policy or Profile should be deployed to. Some criteria is
# needed to identify a Mac as a member of the target Smart Group. This EA template is a
# mechanism for doing that. If a file exists with the specified name at the specified path
# it will return True, otherwise it returns False. 

FlagFilePath="/Library/SomeOrg/"
FlagFileName="flagfile"
result="False"

if [ -e "${FlagFilePath}${FlagFileName}" ]; then
    result="True"
fi

echo "<result>$result</result>"