Extension Attributes Best Practices

dstranathan
Valued Contributor II

Im starting to really get into Extension Attributes! These things are freakin' magic. So many possibilites to be creative here. I have come up with a couple cool EAs that really help my Desktop team a lot in terms of gathering important site-sepcific information.

•Any suggestions on how many EA's is too many? Is there a limit in terms of maximum EAs? I currently expect to max-out at around ~20 EAs. Most are lightweight things (grab 4 ARD fields, Check for existence of specific files, verify AD OU location etc)

•Where do the EA scripts live exactly?

•Any thoughts on when to use a Smart Group versus a Extension Attribute? There are times when I can forsee both use cases.

•Anyone want to share there examples of custom EAs? Im curious as to how the community leverages EAs.

•JAMF web admin: Why isnt there a "Additional Tag" or "Primary Tenet" sub-menu for Extension Attributes like there is for Scripts, Smart Groups, etc? "Constructive criticism" ;0)

6 REPLIES 6

tthurman
Contributor III

I believe the EA scripts live in the database.

I think the only issue you're going to run into with EAs is the more you have, the longer a recon will take. I think I currently have around 50.

There is a section here on JAMF nation for EAs.
https://jamfnation.jamfsoftware.com/extensionAttributes.html

Hope this helps. :)
--
TJ

DBrowning
Valued Contributor II

I use EA's for a lot of items. I've got over 20. For importing data into our SCCM instance i had to pull a lot of custom data in order for it to report properly. Below you will see a quick list of some that I use. Some of these were created when using AutoPkgr for patching.

2fb229fa44224ca19ca53e69604aa15d

mm2270
Legendary Contributor III

50 EAs? We got you beat there. We have around 130! And yes, it does add a bit of time to your recon's, so truthfully, the least amount you can use the better. Honestly, the ones we have we need to comb through and determine which are really needed at this point so we can clean out a few and speed up our recons. One important thing to keep in mind when writing EAs is to endeavor to make the script as fast and efficient as possible. IOW, the faster a script runs when run locally in Terminal, the better it will be as an Extension Attribute. I've been known to go back and rewrite some of our older ones once I learn about a faster method of getting the piece of data I'm looking for. It may only shave off a fraction of a second, but when you multiply things by 100+ it all adds up!

@dstranathan in addition to the resource for Extension Attributes here on JAMFNation, some of us maintain our own github repos for EAs. Here is mine, which is only a small amount of the ones we use on our JSS, but there are many other repos out there: https://github.com/mm2270/Extension-Attributes

dstranathan
Valued Contributor II

When setting up a EA that is a "Yes/No" boolean drop-down menu type, how can I get the default value to always be "No" unless otherwise manually changed to "yes" in the JSS?

sean
Valued Contributor

Piping is for plumbers and cake decoration. Try and avoid it as it will reduce the efficiency. In fact I've only just linked to an example of what @mm2270 was alluding to, regarding overhead on scripts.

Recon -realname syntax issue (bash)
Collecting Email Address via AD

If you take the basics of these examples (as shown below) you can see that there is a distinct difference it timing between the initial posted script and the supplied alternative. In fact the original script is only 7 lines of code, whilst the faster is 11. So the script is over 50% larger and yet ran in 2/3 the time.

Two main reasons:

  • dscl was run only once and is calling the local files which has the same data
  • there is no piping to awk

Yes the real time is a fraction of a second, but this example is tiny and as mentioned all this will add up (and remember, not only will it increase the time taken to recon, but someone is probably trying to use the machine at the same time, so think about what you are scripting).

#!/bin/bash

# Script name getADPipes.sh

CurrentUserName=$(whoami)

ADUserHomeCity=$(dscl /Active Directory/DOMAIN -read /Users/$CurrentUserName | awk '$1 == "City:" { print $2}')
ADUserFirstName=$(dscl /Active Directory/DOMAIN -read /Users/$CurrentUserName | awk '$1 == "FirstName:" { print $2}')
ADUserLastName=$(dscl /Active Directory/DOMAIN -read /Users/$CurrentUserName | awk '$1 == "LastName:" { print $2}')
ADUserEMailAddress=$(dscl /Active Directory/DOMAIN -read /Users/$CurrentUserName | awk '$1 == "EMailAddress:" { print $2}')

exit 0
$ time ./getADPipes.sh 

real    0m0.056s
user    0m0.028s
sys 0m0.026s
#!/bin/bash

# Script name getAD.sh

loggedInUser=`stat -f%Su /dev/console`
plistbuddy="/usr/libexec/PlistBuddy"
tempFile="/tmp/dscl.plist"

dscl -plist . read /Users/$loggedInUser EMailAddress City RealName LastName FirstName > $tempFile

userEmail=`$plistbuddy -c "Print dsAttrTypeStandard:EMailAddress:0" $tempFile`
userCity=`$plistbuddy -c "Print dsAttrTypeStandard:City:0" $tempFile`
userLastName=`$plistbuddy -c "Print dsAttrTypeStandard:LastName:0" $tempFile`
userFirstName=`$plistbuddy -c "Print dsAttrTypeStandard:FirstName:0" $tempFile`

exit 0
$ time ./getAD.sh

real    0m0.038s
user    0m0.025s
sys 0m0.017s

It may also be worth considering how often the information you require is changing.

Examples:

  • If it only changes once per login, perhaps the script could be a login script that writes to a plist and the EA reads the plist instead of trying to run the whole script.
  • Perhaps a launch agent may be better placed to run the script as perhaps a watch folder and again you could write the data to a plist to read as an EA.

The more efficient they are, the more you can get away with.

cwaldrip
Valued Contributor

@dstranathan you'll want to include a default answer in your EA. Basically an if/then/else/fi type statement.

Here's an example from one of my EAs. You could modify this to do what you want, I'm trying to find the version of a binary, and if it's not there report N/A.

#!/bin/bash

if [ -e /usr/local/bin/dockutil ]; then
    bar=`dockutil --version`
else
    bar=N/A
fi

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