Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Creating a ‘Self Service First’ Mentality at Target

9d350fa2294e1192f8f12b0ebf1a1d8b?s=47 Jamf
October 25, 2018

Creating a ‘Self Service First’ Mentality at Target

Presentation from JNUC 2018, the world's largest rally of Apple IT administrators.

Creating a ‘Self Service First’ Mentality at Target

Presented by:
Chris Driscoll, Target
Noah Anderson, Target

View all session slides, recordings and more at https://www.jamf.com/events/jamf-nation-user-conference/2018/.



October 25, 2018

More Decks by Jamf

Other Decks in Technology


  1. None
  2. Chris Driscoll EDGE Engineer / Target Corporation chris.driscoll@target.com / Slack:

    @cdriscoll Noah Anderson EDGE Engineer / Target Corporation noah.anderson@target.com / Slack: @NoahRJ
  3. Creating a Self Service First Mentality at Target Presentation agenda:

    • How to extend Self Service from software to hardware • Use Self Service as the front end to other applications / workflows • Simplify the user experience, reduce support, improve TCO
  4. 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017

    2018 Incidents Machines
  5. 3% 70% 16% 11% Leaders Creative Technology Other 12% 36%

    5% 24% 6% 30% 40% 2% 4% 2% 7% 62% 90% 32% 48% Machine Deployment Demographics
  6. 0% 25% 50% 75% 100% December 2014 February 2015 April

    2015 June 2015 August 2015 October 2015 December 2015 February 2016 April 2016 June 2016 July 2016 September 2016 November 2016 January 2017 March 2017 May 2017 July 2017 September 2017 November 2017 January 2018 March 2018 May 2018 July 2018 Call Center Hi Tech Support Resolution Success
  7. How do you continue to improve the experience… while maintaining

    exponential growth… without additional support… and without a budget request?
  8. Self Service First Principles • Simplify the experience • Try

    harder • Maintain cost-advantage
  9. Self Service First Concept • Self Service Policy • Trigger

    a script • Take action
  10. Self Service First Examples • Software • Hardware • Rights

  11. Self Service First Licensed Software • Complete setup / approval

    / troubleshooting • Message software details / cost / etc • Always include a ‘More Info…’
  12. Total Cost Purchase Warranty Repair / Support Resale SAVES 19.3%

    SAVES 15.4% Hardware Requests
  13. Hardware Requests Accessories? 44% 38% 28%

  14. Virtual Vending Machine

  15. #Set ServiceNow Catalog API configs URL="servicenow.company.com?key=KEY" Username=$(/usr/bin/stat -f%Su /dev/console) Serial=$(ioreg

    -c IOPlatformExpertDevice -d 2 | awk -F\" '/IOPlatformSerialNumber/{print $ (NF-1)}') Peripheral_Requested="Apple Magic Keyboard" #Begin prompting user for accessory order Selections=($("${CocoaDialog}" #CocoaDialog prompt includes keyboard info, price, and order options, including remote ship and HQ pickup locations)) Button=${Selections[0]} #Identify which button was selected and take action if [[ $Button == "Cancel" ]]; then echo "User selected Cancel" exit 1 elif [[ $Button == "More" ]]; then echo "User selected More Info..." open https://www.apple.com/shop/product/MLA22LL/A/magic-keyboard-us-english exit 0 else echo "User selected Order" fi #Code Walkthrough
  16. #If Order was selected, every other element in the array

    is the Location Location=${Selections[@]:1} echo "Location selected: $Location" #Create a CocoaDialog progress bar so the user knows we're doing something in the background. rm -f /tmp/hpipe mkfifo /tmp/hpipe "$CocoaDialog" progressbar --indeterminate --title "Virtual Vending Machine" --text "Submitting your request..." < /tmp/ hpipe & exec 3<> /tmp/hpipe #Submit to ServiceNow via Catalog API; capture output APIResponse=($(curl -X POST $URL -H 'Authorization: Bearer '$Bearer_Token -H 'Content-Type: application/json' -d "{"requested_for\": \"$Username\","location\": \"$Location\","computer_name\": \"$Serial\""peripheral_requested\": \"$Peripheral_Requested\"}")) RequestNumber=$(echo $APIResponse | cut -d \" -f 8) #Exit CocoaDialog progress bar exec 3>&- rm -f /tmp/hpipe #Verify if API submit was successful RTMreturned=$(echo $RequestNumber | cut -c 1-3) if [[ $RTMreturned != "RTM" ]]; then echo "API Failure - RTM number not returned" "${CocoaDialog}" #CocoaDialog prompt that indicates failure to submit and next steps for troubleshooting exit 1 else echo "Request Number: $RequestNumber" "$CocoaDialog" #Prompt that indicates success, the request number, and next steps for pickup or shipping details fi #Code Walkthrough 2: Electric Boogaloo
  17. None
  18. Virtual Vending Machine - Feedback 0 300 600 900 1200

    1500 1800 2100 January February March April May June July August
  19. Hardware Request - What’s next?

  20. Self Service First Rights Request • Instructions on the internal

    wiki • Request in MyAccess or ServiceNow • Fulfillment in Self Service
  21. Self Service First USB Rights • One Self Service policy

    • Triggers a script that reviews Jamf Pro and ServiceNow • Prompt the user accordingly
  22. USB Rights - Jamf Pro config Set up two new

    fields • Authorized for USB • USB Grant Date
  23. setVariables() { jssURL="" jssUser="" jssPass="" Auth_Key="" Bearer_Token="" Username=$(/usr/bin/stat -f%Su /dev/console)

    UserInJSS } UserInJSS() { #Validate user is associated with a machine in Jamf Pro UserRecordInJSS=$(/usr/bin/curl -s -u $jssUser:$jssPass $jssURL/JSSResource/users/name/$Username -H "Accept: application/xml" | /usr/ bin/xpath '/user/full_name/text()' 2>/dev/null) if [ "$UserRecordInJSS" != "" ]; then echo "$Username / $UserRecordInJSS exists in Jamf Pro" #Check on status of rights request pullUserUSBRequestInJSS else echo $Username "does not exist in JSS" /usr/local/bin/jamf recon -endUsername $Username & echo $Username "now associated with the machine in Jamf Pro" #Assume no USB Rights have been requested via Self Service so routing user to next step in request process submitUSBRequestInSN fi } pullUserUSBRequestInJSS() { #Validate if user already has USB Rights Request / Fulfillment from the EA field we've previously written to UserUSBRequestInJSS=$(/usr/bin/curl -s -u $jssUser:$jssPass $jssURL/JSSResource/users/name/$Username -H "Accept: application/xml" | / usr/bin/xpath '/user/extension_attributes/extension_attribute[id = "3"]/value/text()' 2>/dev/null) RTMvTSK=$(echo $UserUSBRequestInJSS | cut -c 1-3) if [[ $RTMvTSK = "RTM" ]]; then echo $UserUSBRequestInJSS "- request was made but not fulfilled" lookupUSBRequestInSN elif [[ $RTMvTSK = "TSK" ]]; then echo $UserUSBRequestInJSS "- request was fulfilled" #user potentially re-requesting USB Rights reRequestUSBRights fi } #Code Walkthrough
  24. lookupUSBRequestInSN() { RTMStatus=$(curl -s -X GET -H "Authorization: Bearer ${Bearer_Token}"

    "https://servicenow.company.com/ service_catalog_entries/v1/requested_item/$UserUSBRequestInJSS"?key=${Auth_Key} -H 'Cache-Control: no-cache' -H 'Content- Type: application/json' | tr , "\n" | sed -n -e 's/^.*stage//p' | cut -d '"' -f3) RTMState=$(curl -s -X GET -H "Authorization: Bearer ${Bearer_Token}" "https://servicenow.company.com/ service_catalog_entries/v1/requested_item/$UserUSBRequestInJSS"?key=${Auth_Key} -H 'Cache-Control: no-cache' -H 'Content- Type: application/json' | tr , "\n" | sed -n -e 's/^.*state//p' | cut -d '"' -f3) echo "API return status of the requested item $UserUSBRequestInJSS is $RTMStatus, $RTMState" case ${RTMStatus}_${RTMState} in "Request Cancelled"_"Closed Incomplete") RTMState="Request: Rejected Your USB Rights Request ($UserUSBRequestInJSS) was rejected by your approving manger. If you believe it was rejected in error, please submit another request below." ;; "Waiting for Approval"_"Work in Progress") RTMState="Request: Waiting for Approval Your USB Rights Request ($UserUSBRequestInJSS) has still not been approved by your manager. Please follow up with them and ask to approve the pending request." ;; "Fulfillment"_"Work in Progress") RTMState="Request: Awaiting Fulfillment Your USB Rights Request ($UserUSBRequestInJSS) has been approved and is waiting for our backend system to process. If rights have not been granted within a half hour, please contact your IT helpdesk with your RTM# for followup." ;; "Completed"_"Closed Complete") RTMState="Request: Completed Your USB Rights Request ($UserUSBRequestInJSS) has been approved and fulfilled. If you still do not have USB rights on your machine, please restart and try again. If you continue to have issues, please contact your IT helpdesk with your RTM# for followup." ;; *) RTMState="Something went wrong with the ServiceNow process - please contact your IT helpdesk with your RTM# ($UserUSBRequestInJSS) for followup." ;; esac } #Code Walkthrough
  25. reRequestUSBRights() { #Look up expiration date of previous request from

    the other previously set EA field USBExpirationDate=$(/usr/bin/curl -s -u $jssUser:$jssPass $jssURL/JSSResource/users/name/$Username -H "Accept: application/xml" | /usr/bin/xpath '/user/extension_attributes/extension_attribute[id = "4"]/value/text()' 2>/dev/null) echo "Expiration Date: $USBExpirationDate" DaysTilExpiration=$(expr 365 - $(expr $(expr $(date '+%s') - $(date -j -f '%Y-%m-%d' $USBExpirationDate '+%s')) / 86400)) echo "Days til expiration: $DaysTilExpiration" if [[ $DaysTilExpiration -lt 0 ]]; then echo "User's previous USB Rights have expired" #JH prompt showing that USB rights have expired and asking if user would like to re-request rights or get more info on the process else echo "User still has active USB Rights" #JH prompt showing # of days left in USB rights and asking if user would like to re-request rights or get more info on the process fi } submitUSBRequestInSN() { #Submit to ServiceNow via Catalog API #Capture API response APIResponse=($(curl -X POST ${ServiceNowAPIURL}?key=${Auth_Key} -H 'Authorization: Bearer '$Bearer_Token -H 'Content- Type: application/json' -d "{ \"recipient\": \"$Username\", \"notes\": \"$Notes\" }")) RequestNumber=$(echo $APIResponse | cut -d \" -f 8) verifySNResponse } #Code Walkthrough
  26. verifySNResponse () { #Verify if API submit was successful RTMreturned=$(echo

    $RequestNumber | cut -c 1-3) if [[ $RTMreturned != "RTM" ]]; then #Report back via JH prompt that something went wrong in the submission process and to try again/ raise a manual request else echo "Request Number: $RequestNumber" updateJamfPro fi } updateJamfPro() { #Update the user record in Jamf Pro with the RTM value so they can query it later echo "Sending PUT to add RTM to Jamf Pro " curl -X PUT -u $jssUser:$jssPass $jssURL/JSSResource/users/name/$Username -H "Content-Type: application/xml" -d "<user><name>'$Username'</name><extension_attributes><extension_attribute><id>3</ id><name>Authorized for USB</name><type>String</type><value>'$RequestNumber'</value></ extension_attribute></extension_attributes></user>" fi notifyUser } notifyUser() { #JamfHelper prompt that includes the submitted RTM# and instructions to follow up with a manager for approval } #Code Walkthrough
  27. ##### MAIN ##### echo "Start" setVariables echo "End" #Code Walkthrough

  28. None
  29. USB Rights - Feedback 0 300 600 900 7/13/2018 7/16/2018

    7/18/2018 7/20/2018 7/23/2018 7/25/2018 7/27/2018 7/31/2018 8/2/2018 8/5/2018 8/7/2018 8/9/2018 8/13/2018 8/15/2018 8/17/2018 8/19/2018 8/21/2018 8/23/2018 8/25/2018 8/27/2018 8/29/2018 8/31/2018 9/4/2018 9/6/2018 9/10/2018 9/12/2018 9/14/2018
  30. Summary Self Service First • Simplify the experience • Try

    harder • Maintain cost-advantage 2008 2010 2012 2014 2016 2018
  31. https://git.io/fASWc

  32. © JAMF Software, LL THANK YOU!