Issue with Jamf Extension Attribute Script Not Returning Results

mani2care
Contributor

Hi Jamf Team,

I am encountering an issue with a script that I am using in a Jamf extension attribute. The script is not returning output always “No_Certificate_Found”  when processed through Jamf. I need assistance to validate the issue and understand why it is not picking up the results properly.

When I trigger an inventory update through Jamf's built-in functun, no results are returned. However, when I manually run the command via Jamf using “sudo jamf recon”, I am able to retrieve the expected results. Similarly, the script works when executed via Self Service.

It seems that the script is not functioning properly when built in inventory option is enabled and not running as user in Jamf. Could you please assit this issue? I have attached the script.

Thank you for your assistance.

 

#!/bin/bash

# Expiry Date | Certificate Name | SHA-256 Hash | Keychain Path
#20-Jan-2024 | Manikandan R | 40C6326E5B3458F07A1D2E4DDBEF59728A425C92612FA022263C73BA51FEB8E | "/Users/test/Library/Keychains/login.keychain-db" |test 
#20-Jan-2024 | Manikandan R | B6E53632BDC2A20670CEAF2DCA9FFE92BE130DF100D6B3777646D6541921745 | "/Users/test/Library/Keychains/login.keychain-db" |test

# Output file
output_file="/Users/Shared/expired_certificates_info.txt"
sorted_file="/Users/Shared/sorted_expired_certificates_info.txt"

# Ensure the directory and output files have proper permissions for all users
chmod 777 /Users/Shared
touch "$output_file" "$sorted_file"
chmod 666 "$output_file" "$sorted_file"

# Create or clear the output file and add the header
> "$output_file"

# Current date for comparison
current_date=$(date +"%Y-%m-%d")

# Use security command to find all certificates and process each one
# Function to process certificates in a given keychain
process_certificates_in_keychain() {
    local keychain="$1"
    local user_home="$2"
    # Extract certificates using security command
    sudo -u "$user_home" /usr/bin/security find-certificate -a -Z "$keychain" | while IFS= read -r line; do
    # Extract the SHA-256 hash
    if [[ $line == *"SHA-256 hash:"* ]]; then 
        sha256=$(echo "$line" | awk '{print $3}')
    fi

    # Extract the certificate name
    if [[ $line == *"alis"* ]]; then 
        cert_name=$(echo "$line" | sed 's/.*"alis"<blob>="\([^"]*\)".*/\1/')
    fi

    # Extract the keychain path
    if [[ $line == *"keychain"* ]]; then 
        keychain_path=$(echo "$line" | awk -F' ' '{print $NF}')
    fi

    # Once we have both the SHA-256 hash and certificate name, fetch the expiry date
    if [[ -n $cert_name && -n $sha256 ]]; then
        expiry_date=$(/usr/bin/security find-certificate -a -c "$cert_name" -p -Z | \
            sed -n 'H; /^SHA-256/h; ${g;p;}' | \
            /usr/bin/openssl x509 -noout -enddate 2>/dev/null | \
            cut -f2 -d= | xargs -I {} sh -c 'if [ -n "{}" ]; then date -jf "%b %e %T %Y %Z" "{}" +"%Y-%m-%d"; fi')

        # Only print if all information is found and if the certificate is expired
        if [[ -n $expiry_date && "$expiry_date" < "$current_date" ]]; then
            # Format expiry date to DD-MMM-YYYY
            formatted_expiry_date=$(date -jf "%Y-%m-%d" "$expiry_date" +"%d-%b-%Y")
            echo "$formatted_expiry_date | $cert_name | $sha256 | $keychain_path |$user_home" >> "$output_file"
        fi

        # Reset variables for the next certificate
        expiry_date=""
        cert_name=""
        sha256=""
        keychain_path=""
    fi
        done
}

# Get all users with a home directory on the system and UID greater than 500
user_list=$(dscl . list /Users | grep -v '_')

# Process certificates for each user
for user in $user_list; do
    # Get the UID of the user
    user_uid=$(dscl . -read /Users/"$user" UniqueID | awk '{print $2}')

    # Check if the UID is greater than 500
    if [ "$user_uid" -gt 500 ]; then
        # Get the user's home directory
        user_home=$(dscl . read /Users/"$user" NFSHomeDirectory | cut -d ' ' -f 2)
        
        # Get the list of keychains for the user
        keychains=($(sudo -u "$user" security list-keychains | tr -d '"' | tr ' ' '\n'))
        
        # Process each keychain for certificates
        for keychain in "${keychains[@]}"; do
            process_certificates_in_keychain "$keychain" "$user"
        done
    fi
done

# Sort the output file by expiry date (low to high) and save to a temporary file
sort -t '|' -k 1 "$output_file" > "$sorted_file"

# Replace the original output file with the sorted file
mv "$sorted_file" "$output_file"

output=$(cat "$output_file")

# Check if the output file is empty
if [[ -s "$output_file" ]]; then
    # Display output
    echo "<result>$output</result>"
else
    echo "<result>No_Certificate_Found</result>"
fi

 

 

3 REPLIES 3

shyam9490
New Contributor II

Your getting a result because the script ran in user profile , while running from Jamf the script ran as root. Try sudo -s command first login as root in terminal and try to execute the script you will get the same result as executing from Jamf 

shyam9490
New Contributor II

If your running anything from self service it execute as user 

 

byrnese
New Contributor III

One a side note, I would strongly recommend you not action changes to your endpoints via Extension Attributes. You should make the change via policy, use your EA to validate your expectations, and then use Smart Groups to trigger changes based upon the results of the EA's output.

Aside from the danger of having scripts that action changes on your device on an ongoing basis, you looks the ability to view logs, and track history. If the EA fails in a way other than ways your logic has accounted for, you won't know why.

Finally, those EAs run with inventory updates, so every time you add something that "does" something, it prologues your recon times. If a script errors out in an EA that isn't clean, you run the risk of incomplete inventory updates, or worse, stuck inventory updates. That will lead to your computer failing to being managed correctly, as it waits for the EA to finish.

My 2 cents. Good luck to you.