Collecting log Files

tdenton
Contributor II

Hi All 

Hoping someone can help.

Have found a script for collecting log files using jamf pro API thanks @Travid  @david_maestre for updating the script to work with Jamf pro API I belive its based on this https://github.com/kc9wwh/logCollection which no longer seems to work. I belive due to changes in the API.

Im getting the below errror is there anyway to make it work without needing Xcode, seems to be using some tools which are part of Xcode. My coding skills arent up to much so struggling to find whats bits of Xcode its using as dont appear to be reference in the script.

no developer tools were found at '/Applications/Xcode.app', and no install could be requested (perhaps no UI is present), please install manually from 'developer.apple.com'. Failed to retrieve Jamf Pro Computer ID.



#!/bin/bash

## User Variables

jamfProURL="$4"

jamfProUser="$5"

jamfProPass="$6"

logFiles="$7"

## System Variables

mySerial=$(system_profiler SPHardwareDataType | awk '/Serial Number/{print $4}')

currentUser=$(stat -f%Su /dev/console)

compHostName=$(scutil --get LocalHostName)

timeStamp=$(date '+%Y-%m-%d-%H-%M-%S')

## Debugging Outputs (Optional)

echo "Jamf Pro URL: $jamfProURL"

echo "Jamf Pro User: $jamfProUser"

# Do not echo the password for security

echo "Log Files: $logFiles"

echo "Serial Number: $mySerial"

echo "Current User: $currentUser"

echo "Computer Hostname: $compHostName"

## Log Collection

fileName="$compHostName-$currentUser-$timeStamp.zip"

echo "Creating zip file: /private/tmp/$fileName"

zip -r /private/tmp/"$fileName" $logFiles

## Obtain API Auth Token

authResponse=$(curl -sku "$jamfProUser:$jamfProPass" -X POST "$jamfProURL/api/v1/auth/token")

apiAuthToken=$(echo "$authResponse" | plutil -extract token raw -)

tokenExpiration=$(echo "$authResponse" | plutil -extract expires raw -)

if [ -z "$apiAuthToken" ]; then

echo "Failed to obtain API authentication token."

echo "Response: $authResponse"

exit 1

fi

echo "API Authentication Token obtained. Token expires: $tokenExpiration"

## Corrected Filter Field for Serial Number

encodedSerial=$(printf '%s' "$mySerial" | python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip()))')

filterQuery="hardware.serialNumber%3D%3D$encodedSerial"

## Get Jamf Pro Computer ID using the Jamf Pro API

computerIDResponse=$(curl -sk --header "Authorization: Bearer $apiAuthToken" "$jamfProURL/api/v1/computers-inventory?filter=$filterQuery")

jamfProID=$(echo "$computerIDResponse" | python3 -c "

import sys, json

data = json.load(sys.stdin)

if data['totalCount'] > 0:

 print(data['results'][0]['id'])

else:

 sys.exit(1)

" 2>/dev/null)

if [ -z "$jamfProID" ]; then

echo "Failed to retrieve Jamf Pro Computer ID."

echo "Response: $computerIDResponse"

exit 1

fi

echo "Jamf Pro Computer ID: $jamfProID"

## Upload Log File

uploadResponse=$(curl -sk --header "Authorization: Bearer $apiAuthToken" -X POST "$jamfProURL/api/v1/computers-inventory/$jamfProID/attachments" -F file=@/private/tmp/$fileName)

echo "Upload Response: $uploadResponse"

## Check for successful upload

if [[ "$uploadResponse" == *"id"* ]]; then

echo "Log file uploaded successfully."

else

echo "Failed to upload log file."

exit 1

fi

## Invalidate API Auth Token

curl -sk --header "Authorization: Bearer $apiAuthToken" "$jamfProURL/api/v1/auth/invalidate-token" -X POST

## Cleanup

rm /private/tmp/"$fileName"

exit 0

 
Thanks

1 ACCEPTED SOLUTION

sdagley
Esteemed Contributor II

@tdenton Where did the python call in that script come from? It is not part of the https://github.com/kc9wwh/logCollection script and isn't necessary to get a Mac's serial number.

And here's an updated version of the log collections script that uses Bearer Token auth since Basic Auth is no longer supported for the API:

#!/bin/bash


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# Copyright (c) 2020 Jamf.  All rights reserved.
#
#       Redistribution and use in source and binary forms, with or without
#       modification, are permitted provided that the following conditions are met:
#               * Redistributions of source code must retain the above copyright
#                 notice, this list of conditions and the following disclaimer.
#               * Redistributions in binary form must reproduce the above copyright
#                 notice, this list of conditions and the following disclaimer in the
#                 documentation and/or other materials provided with the distribution.
#               * Neither the name of the Jamf nor the names of its contributors may be
#                 used to endorse or promote products derived from this software without
#                 specific prior written permission.
#
#       THIS SOFTWARE IS PROVIDED BY JAMF SOFTWARE, LLC "AS IS" AND ANY
#       EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#       WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#       DISCLAIMED. IN NO EVENT SHALL JAMF SOFTWARE, LLC BE LIABLE FOR ANY
#       DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#       (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#       LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#       ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#       SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# This script was designed to be used in a Self Service policy to allow the facilitation
# or log collection by the end-user and upload the logs to the device record in Jamf Pro
# as an attachment.
#
# REQUIREMENTS:
#           - Jamf Pro
#           - macOS Clients running version 10.13 or later
#
#
# For more information, visit https://github.com/kc9wwh/logCollection
#
# Written by: Joshua Roskos | Jamf
# Revised by: Alton Brailovskiy | Martin Cox (Jamf) 
#
# Revision History
# 2024-07-23: Updated Script - https://github.com/kc9wwh/logCollection/blob/master/BearerAuth.sh
# 2023-11-30: Added support for bearer auth and invalidating bearer token once done.
# 2020-12-01: Added support for macOS Big Sur
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #


## User Variables
## Ensure not to include the / at the end of the JamfProURL parameter. ex https://instance.jamfcloud.com is the parameter NOT https://instance.jamfcloud.com/
## Suggested Logs to pull: /private/var/log/install.log* /private/var/log/jamf.log* /private/var/log/system.log*


jamfProURL="$4"
jamfProUser="$5"
jamfProPass="$6"
logFiles="$7"


bearerTokenResponse=$(curl -s -u "$jamfProUser":"$jamfProPass" "$jamfProURL/api/v1/auth/token" -X POST)


if [[ $? -eq 0 ]]; then
	bearerToken=$(echo "$bearerTokenResponse" | plutil -extract token raw -)
    echo "Bearer token: $bearerToken"
else
	echo "Authentication failed. Check credentials or endpoint."
fi


## System Variables
mySerial=$(system_profiler SPHardwareDataType | grep 'Serial Number' | awk '{print $NF}')
currentUser=$( stat -f%Su /dev/console )
compHostName=$( scutil --get LocalHostName )
timeStamp=$( date '+%Y-%m-%d-%H-%M-%S' )
osMajor=$(/usr/bin/sw_vers -productVersion | awk -F . '{print $1}')
osMinor=$(/usr/bin/sw_vers -productVersion | awk -F . '{print $2}')


## Log Collection
fileName=$compHostName-$currentUser-$timeStamp.zip
zip /private/tmp/$fileName $logFiles


## Upload Log File
if [[ "$osMajor" -ge 11 ]]; then
	jamfProID=$( curl -k -H "Authorization: Bearer ${bearerToken}" $jamfProURL/JSSResource/computers/serialnumber/$mySerial/subset/general | xpath -e "//computer/general/id/text()" )
elif [[ "$osMajor" -eq 10 && "$osMinor" -gt 12 ]]; then
	jamfProID=$( curl -k -H "Authorization: Bearer ${bearerToken}" $jamfProURL/JSSResource/computers/serialnumber/$mySerial/subset/general | xpath "//computer/general/id/text()" )
fi


curl -k -H "Authorization: Bearer ${bearerToken}" $jamfProURL/JSSResource/fileuploads/computers/id/$jamfProID -F name=@/private/tmp/$fileName -X POST


## Cleanup
rm /private/tmp/$fileName


# Invalidate the bearer token after file upload
invalidateResponse=$(curl -s -u "$jamfProUser":"$jamfProPass" "$jamfProURL/api/v1/auth/invalidateToken" -X POST -H "Authorization: Bearer $bearerToken")


if [[ $? -eq 0 ]]; then
	echo "Bearer token invalidated successfully."
else
	echo "Failed to invalidate bearer token. Response: $invalidateResponse"
fi


exit 0

View solution in original post

5 REPLIES 5

Shyamsundar
Contributor

if you wanted to run this device on the end user's machine, Python was removed from macOS long ago, I don't think it will execute.  it gives an error as command line tools are not installed, you can install the same using the command "xcode-select --install" 

tdenton
Contributor II

Thanks @Shyamsundar  just testing with deploying xcode via vpp apps.

Did try xcode-select --install but prompts the users not sure if there away to install in silently 

sdagley
Esteemed Contributor II

@tdenton Where did the python call in that script come from? It is not part of the https://github.com/kc9wwh/logCollection script and isn't necessary to get a Mac's serial number.

And here's an updated version of the log collections script that uses Bearer Token auth since Basic Auth is no longer supported for the API:

#!/bin/bash


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# Copyright (c) 2020 Jamf.  All rights reserved.
#
#       Redistribution and use in source and binary forms, with or without
#       modification, are permitted provided that the following conditions are met:
#               * Redistributions of source code must retain the above copyright
#                 notice, this list of conditions and the following disclaimer.
#               * Redistributions in binary form must reproduce the above copyright
#                 notice, this list of conditions and the following disclaimer in the
#                 documentation and/or other materials provided with the distribution.
#               * Neither the name of the Jamf nor the names of its contributors may be
#                 used to endorse or promote products derived from this software without
#                 specific prior written permission.
#
#       THIS SOFTWARE IS PROVIDED BY JAMF SOFTWARE, LLC "AS IS" AND ANY
#       EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#       WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#       DISCLAIMED. IN NO EVENT SHALL JAMF SOFTWARE, LLC BE LIABLE FOR ANY
#       DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#       (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#       LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#       ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#       SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# This script was designed to be used in a Self Service policy to allow the facilitation
# or log collection by the end-user and upload the logs to the device record in Jamf Pro
# as an attachment.
#
# REQUIREMENTS:
#           - Jamf Pro
#           - macOS Clients running version 10.13 or later
#
#
# For more information, visit https://github.com/kc9wwh/logCollection
#
# Written by: Joshua Roskos | Jamf
# Revised by: Alton Brailovskiy | Martin Cox (Jamf) 
#
# Revision History
# 2024-07-23: Updated Script - https://github.com/kc9wwh/logCollection/blob/master/BearerAuth.sh
# 2023-11-30: Added support for bearer auth and invalidating bearer token once done.
# 2020-12-01: Added support for macOS Big Sur
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #


## User Variables
## Ensure not to include the / at the end of the JamfProURL parameter. ex https://instance.jamfcloud.com is the parameter NOT https://instance.jamfcloud.com/
## Suggested Logs to pull: /private/var/log/install.log* /private/var/log/jamf.log* /private/var/log/system.log*


jamfProURL="$4"
jamfProUser="$5"
jamfProPass="$6"
logFiles="$7"


bearerTokenResponse=$(curl -s -u "$jamfProUser":"$jamfProPass" "$jamfProURL/api/v1/auth/token" -X POST)


if [[ $? -eq 0 ]]; then
	bearerToken=$(echo "$bearerTokenResponse" | plutil -extract token raw -)
    echo "Bearer token: $bearerToken"
else
	echo "Authentication failed. Check credentials or endpoint."
fi


## System Variables
mySerial=$(system_profiler SPHardwareDataType | grep 'Serial Number' | awk '{print $NF}')
currentUser=$( stat -f%Su /dev/console )
compHostName=$( scutil --get LocalHostName )
timeStamp=$( date '+%Y-%m-%d-%H-%M-%S' )
osMajor=$(/usr/bin/sw_vers -productVersion | awk -F . '{print $1}')
osMinor=$(/usr/bin/sw_vers -productVersion | awk -F . '{print $2}')


## Log Collection
fileName=$compHostName-$currentUser-$timeStamp.zip
zip /private/tmp/$fileName $logFiles


## Upload Log File
if [[ "$osMajor" -ge 11 ]]; then
	jamfProID=$( curl -k -H "Authorization: Bearer ${bearerToken}" $jamfProURL/JSSResource/computers/serialnumber/$mySerial/subset/general | xpath -e "//computer/general/id/text()" )
elif [[ "$osMajor" -eq 10 && "$osMinor" -gt 12 ]]; then
	jamfProID=$( curl -k -H "Authorization: Bearer ${bearerToken}" $jamfProURL/JSSResource/computers/serialnumber/$mySerial/subset/general | xpath "//computer/general/id/text()" )
fi


curl -k -H "Authorization: Bearer ${bearerToken}" $jamfProURL/JSSResource/fileuploads/computers/id/$jamfProID -F name=@/private/tmp/$fileName -X POST


## Cleanup
rm /private/tmp/$fileName


# Invalidate the bearer token after file upload
invalidateResponse=$(curl -s -u "$jamfProUser":"$jamfProPass" "$jamfProURL/api/v1/auth/invalidateToken" -X POST -H "Authorization: Bearer $bearerToken")


if [[ $? -eq 0 ]]; then
	echo "Bearer token invalidated successfully."
else
	echo "Failed to invalidate bearer token. Response: $invalidateResponse"
fi


exit 0

@sdagley  didnt spot that, thanks so much this is working perfectley.

Thanks also for posting your version @david_maestre 

david_maestre
New Contributor III

The above looks accurate./ 

I'll attach mine just incase -- currently working just fine. 

Thanks

#!/bin/bash

## User Variables

jamfProURL="$4"

jamfProUser="$5"

jamfProPass="$6"

logFiles="$7"

## System Variables

mySerial=$(system_profiler SPHardwareDataType | awk '/Serial Number/{print $4}')

currentUser=$(stat -f%Su /dev/console)

compHostName=$(scutil --get LocalHostName)

timeStamp=$(date '+%Y-%m-%d-%H-%M-%S')

## Debugging Outputs (Optional)

echo "Jamf Pro URL: $jamfProURL"

echo "Jamf Pro User: $jamfProUser"

# Do not echo the password for security

echo "Log Files: $logFiles"

echo "Serial Number: $mySerial"

echo "Current User: $currentUser"

echo "Computer Hostname: $compHostName"

## Log Collection

fileName="$compHostName-$currentUser-$timeStamp.zip"

echo "Creating zip file: /private/tmp/$fileName"

zip -r /private/tmp/"$fileName" $logFiles

## Obtain API Auth Token

authResponse=$(curl -sku "$jamfProUser:$jamfProPass" -X POST "$jamfProURL/api/v1/auth/token")

apiAuthToken=$(echo "$authResponse" | plutil -extract token raw -)

tokenExpiration=$(echo "$authResponse" | plutil -extract expires raw -)

if [ -z "$apiAuthToken" ]; then

echo "Failed to obtain API authentication token."

echo "Response: $authResponse"

exit 1

fi

echo "API Authentication Token obtained. Token expires: $tokenExpiration"

## Corrected Filter Field for Serial Number

encodedSerial=$(printf '%s' "$mySerial" | python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip()))')

filterQuery="hardware.serialNumber%3D%3D$encodedSerial"

## Get Jamf Pro Computer ID using the Jamf Pro API

computerIDResponse=$(curl -sk --header "Authorization: Bearer $apiAuthToken" "$jamfProURL/api/v1/computers-inventory?filter=$filterQuery")

jamfProID=$(echo "$computerIDResponse" | python3 -c "

import sys, json

data = json.load(sys.stdin)

if data['totalCount'] > 0:

 print(data['results'][0]['id'])

else:

 sys.exit(1)

" 2>/dev/null)

if [ -z "$jamfProID" ]; then

echo "Failed to retrieve Jamf Pro Computer ID."

echo "Response: $computerIDResponse"

exit 1

fi

echo "Jamf Pro Computer ID: $jamfProID"

## Upload Log File

uploadResponse=$(curl -sk --header "Authorization: Bearer $apiAuthToken" -X POST "$jamfProURL/api/v1/computers-inventory/$jamfProID/attachments" -F file=@/private/tmp/$fileName)

echo "Upload Response: $uploadResponse"

## Check for successful upload

if [[ "$uploadResponse" == *"id"* ]]; then

echo "Log file uploaded successfully."

else

echo "Failed to upload log file."

exit 1

fi

## Invalidate API Auth Token

curl -sk --header "Authorization: Bearer $apiAuthToken" "$jamfProURL/api/v1/auth/invalidate-token" -X POST

## Cleanup

rm /private/tmp/"$fileName"

exit 0