How to obtain the value of a certain Extension Attribute through the API

darms21
New Contributor

Using the API, is it possible to get the value of a single extension attribute? For example if I have the follow XML
<computer> <general>...</general> <extension_attributes> <attribute> <name>Domain</name> <value>DomainA</value>
</attribute> <attribute> <name>Firewall</name> <value>On</value> </attribute> </extension_attributes>
Is it possible to request the value of the Firewall extension attribute?

22 REPLIES 22

tsuter
New Contributor II

Did you ever find an answer to this. I have the exact same problem at the moment

Chris
Valued Contributor

I'm sure there are better ways, but this is what i do:

http://work.chrisdietrich.de/reading-casper-extension-attributes-with-a-shell-script/

iJake
Valued Contributor

I use xpath in my shell scripts as well. It's a life saver.

mm2270
Legendary Contributor III

Yeah me too (using xpath to parse the xml). I actually didn't know about the ability to use the "/attribute/[name=$var]" syntax though, so thanks for posting about that. That helps with things like pulling EAs.
One note on that though. I'm still on JSS 8.73 and I needed to use single quotes around the variable name. The double quotes were generating errors for me for some reason.

BrysonTyrrell
Contributor II

Love the writeup @Chris :)

There are changes to extension attributes in 9.x I thought I'd call out. They include unique IDs now and 'attribute' became 'extension_attribute', so your XML would look like this in 9.x:

<computer>
    <extension_attributes>
        ...
        <extension_attribute>
            <id>2</id>
            <name>Firewall</name>
            <type>String</type>
            <value>On</value>
        </extension_attribute>
    </extension_attributes>
</computer>

There's not much difference to using the name instead of the ID except less typing. Using the same curl Chris provides to only pull the subset containing the extension attributes, I wrote an adaptation of his xPath example to pull out the value without an extra pipe to Awk (I'm going to need to update my posts...):

EAID=2
xml=$(curl -u 'user':'pass' https://jss.address.com/JSSResource/computers/id/1/subset/extension_attributes)
value=$(echo $xml | xpath "//*[id=$EAID]/value/text()" 2>/dev/null)
echo $value
On

tsuter
New Contributor II

Updated for 9.x, runs against the UDID instead of the Mac address

#!/bin/sh

apiURL='https://casper:8443/JSSResource/computers/udid/'
apiUser='apiuser'
apiPass='apipass'
extAttName=""EA Name""

udid=$(/usr/sbin/system_profiler SPHardwareDataType | /usr/bin/awk '/Hardware UUID:/ { print $3 }')

value=$(curl -s -u $apiUser:$apiPass $apiURL$udid/subset/extension_attributes | xpath "//extension_attribute[name=$extAttName]" 2>&1 | awk -F'<value>|</value>' '{print $2}')

echo $value

loceee
Contributor

@brysontyrell that xpath syntax to find elements has changed my life... or at least a bunch of scripts I am working on. :)

Thanks!

loceee
Contributor

that and ...

xpath "//element/element/mykey/text()"

damn I wish I knew about that earlier.

yr_joelbruner
New Contributor III

Yes! I was an xpath hack before this (ok I still am but a highly functioning one ;)!

The one catch I found is matching an EA’s XML node based on value, strings vs numbers:

Nodes with number values can be like this: //extension_attribute[id=13]/value
String matches however must single quote: //extension_attribute[name='EAName']/value

Thanks @Chris and This StackExchange page

danshaw
Contributor II

Have there been any changes to the v10 API that would make this not work? I am trying to pull a computers EA's, but I think the problem is that when I do using CURL, I get the error:

not well-formed (invalid token) at line 1, column 0, byte 0:
{"computer":{"extension_attributes":[{"id":88,"name":"Active Directory Health","type":"String","value":"Valid"}
 at /System/Library/Perl/Extras/5.18/darwin-thread-multi-2level/XML/Parser.pm line 187.

My curl is pretty simple. I have the correct username/pass and hard coded in my computers UDID:

curl -u user:pass https://jss.***.com/JSSResource/computers/udid/COMPUID/subset/extension_attributes

I'm then trying to use xpath to filter out one of my ID's

value=$(echo $xml | xpath "//*[id=$EAID]/value/text()" 2>/dev/null)

sdagley
Esteemed Contributor II

@danshaw My guess is you need to add -H "Accept: application/xml" to your curl call to the JSS API as the default response is now JSON rather than XML

danshaw
Contributor II

@sdagley I tried that and got the error:

Can't call method "isa" on an undefined value at /System/Library/Perl/Extras/5.18/XML/XPath/Expr.pm line 239.

sdagley
Esteemed Contributor II

@danshaw Any chance you added the Accept header incorrectly? (See this for an example: https://www.jamf.com/jamf-nation/discussions/7673/jss-api-returning-json-instead-of-xml). If that doesn't look like the cause of your XPath error, try posting your script for review.

danshaw
Contributor II

Whats interesting is that when I type the CURL statement in terminal it works just fine, but when I try to save it to a variable and run it as a script, it generates the error. I am interested in the EA ID of 32. Here is the script:

EAID=32
xml=$(curl -u apiuser:pass -H "Accept: application/xml" https://jss.***.com/JSSResource/computers/udid/MYCOMPUTERUUID/subset/extension_attributes)
value=$(echo $xml | xpath '//*[id=$EAID]/value/text()')
echo $value

3530e982c1574a9a83b950ed31f79ea8

The screenshot above has me running it first with the change you wanted me to make and the second is my initial problem without that change.

sdagley
Esteemed Contributor II

@danshaw So the curl command is correctly returning the EAs for the computer you specify with MYCOMPUTERUUID? Have you verified the Accept header results in a valid XML response from the API call?

BrysonTyrrell
Contributor II

@danshaw

You can't use single quotes in a shell script for that because single quoted strings are literals: no expansion of any variables. Switch to double-quotes.

xpath "//*[id=$EAID]/value/text()"

danshaw
Contributor II

Argh. Same error.

value=$(echo $xml | xpath "//*[id=32]/value/text()")

BrysonTyrrell
Contributor II

@danshaw

I was able to successfully obtain the value of an extension attribute out of the Jamf JSS using those lines you posted (with my own UUID and a different EA ID):

EAID=15
xml=$(curl -u bryson.tyrrell -H "Accept: application/xml" https://XXX.com/JSSResource/computers/udid/$UUID/subset/extension_attributes)
echo $xml | xpath "//*[id=$EAID]/value/text()"

danshaw
Contributor II

@brysontyrrell That worked! I think I have it working for now. Thank you so much for your troubleshooting help. I appreciate it!

ktrojano
Release Candidate Programs Tester

Is this still a viable was to get the value of an extension attribute? Here's my code:

EAID=7

xml=$(curl -su username:password -H "Accept: application/xml" https://jamfurl/JSSResource/computers/serialnumber/xxxxxxxxxxxx/subset/extension_attributes)

echo $xml

result=$(echo $xml | xpath "//*[id=$EAID]/value/text()" 2>/dev/null)

echo $result

 

The first echo shows the results of the curl command so I know that is working. The second echo display nothing. I'm not sure what is wrong with my code. 

Kimberly Trojanowski

mm2270
Legendary Contributor III

@ktrojano You should read through this blog post.

Dealing with xpath changes in Big Sur – Scripting OS X

The code to get xpath to work correctly changed a few years back now, so it will need to be updated accordingly. The blog post has the details.

ktrojano
Release Candidate Programs Tester

Thanks, I'll check this out. 

Kimberly Trojanowski