Option to not update extension attribute on specific condition

sosnovsken
New Contributor III

I'm working on an extension attribute that gets a computer's OU. I found existing code, modified it, and it works great! However, when a user goes off campus, the EA script can't make the ldap query because our domain isn't accessible over the internet. This causes the EA to become blank. It updates to the proper value when the user comes back on campus.

How can I tell an EA to leave the value it has alone? I tried to put something like this at the top of my script (changed my IP's for obvious reasons, but the rest of it is verbatim):

ETH0IP=`ipconfig getifaddr en0`
ETH1IP=`ipconfig getifaddr en1`
if [[ $ETH0IP != "192.168"* ]] && [[ $ETH1IP != "192.168"* ]]; then
    exit 0
fi

I thought that if I didn't have a <result> tag it might just kill the script. Unfortunately, I see the same behavior. Anyone else know how to solve this?

1 ACCEPTED SOLUTION

alexjdale
Valued Contributor III

You could have the script write the last "good" result to a plist with the defaults command, then if the ldap query fails, have the script read it in and echo it back as the result.

View solution in original post

16 REPLIES 16

russeller
Contributor III

Can you have it ping an internal resource at the beginning of the script and if is not available to exit?

if [ ! "$(ping -q -c1 internal.company.com)" ]; then
    echo "internal.company.com is not available. Aborting..."
    exit 1
fi

Will it still write a blank value if you "exit 1" the EA?

sosnovsken
New Contributor III

I tried exit -1 and that still wrote a blank value.

I tested my logic in a script on a client by echoing one thing if it was true and one if it was false... so I don't think that part needs to change. The ping does seem more elegant though.

alexjdale
Valued Contributor III

You could have the script write the last "good" result to a plist with the defaults command, then if the ldap query fails, have the script read it in and echo it back as the result.

sosnovsken
New Contributor III

My last resort was going to be doing something similar with a text/marker file and then spitting out the result of `more file.txt` into a variable. Seems inelegant, but if it works....

Thanks!

mm2270
Legendary Contributor III

Yeah, we've had the same issue. We use a few EAs to pull information from our internal domain controller, and as soon as we put a JSS cluster in the DMZ so Macs could report in from the outside, we starting getting blank results. We initially tried some of the same things you did, like trying to use exit in the script if it could;t ping the DC, but found it still placed a blank value in the computer record.
In talking about this with our TAM, turns out this actually makes sense if you think about how a recon happens. The jamf binary collects information as it gores from each section, including the EA scripts. It compiles all this into a final result that it needs to update the computer record with. The issue is that if you tell the EA script to simply exit with no result, it tells the jamf binary it got a null value and that null value gets written into the final results that it uploads at the end.
So in the end you can't simply tell the EA script to exit or you get "no result", which is exactly what you end up seeing in the computer record. Its not intelligent enough to say, 'hmm, i couldn't pull a result for this script so let me leave the existing value in place. In reality, the binary isn't even aware of the "existing" value.

Our "fix" was to have it return something like "NA" instead of trying to exit. Its not perfect, but we can tell our Smart groups to exclude anything that has a result of "N/A"

Edit: Also just wanted to mention that I also tried using a function in the script to do an API call to get the current value out of the Mac's API record (if it couldn't pull a live one that is). Unfortunately, the API requires Tomcat, which is disabled on a Limited Access JSS instance in the DMZ, so this fails too. :( Foiled again! So that's why we ended up just submitting a value that would tell us the Mac is on the outside of our network when it reported in I hadn't really tried dumping the result into a local file to read back, and that may actually work, but one thing to keep in mind is that you'd also have to have some logic in the script to look for the plist first and then pull the result. If the EA script runs for the first time on an external Mac it won't have any "previous" value to read back. Real chicken and egg kind of problem :(

In thinking about this problem again because of this thread, I may submit a Feature Request to ask for the jamf binary to be more intelligent and not blank out an existing value if an EA script failed to run successfully or was told to exit based on a condition. I'm not really confident we'll ever really see that happen, but no harm in asking I guess.

ernstcs
Contributor III

Perhaps Extension Attributes need a "safe word" that can be returned in the result set to be set free and not overwrite the existing data. =D

Not sure what you could pass it that would never be a possibility of a returned value, but I'm sure we could come up with something. Maybe fluggaenkdechioebolsen.

Anyone care to start a feature request?

sosnovsken
New Contributor III

@mm2270

I just wrote some logic to write it to a plain old text file, which works perfectly. I'll have to check in with our helpdesk, but I don't think there will ever be a situation where a computer doesn't do its first inventory check on campus... so that should make this a pretty straightforward.

@ernstcs
We are brand new to casper (haven't even done the jumpstart yet... I just figured I'd get started early). Are they pretty cool about feature requests?

ernstcs
Contributor III

@sosnovsken Post under the Feature Request section of the website is your best course of action regardless.

Either the community gets behind it and votes it up or JAMF just recognizes it as a no brainer. Based on the responses right away you are not alone.

I can't comment on how long it may take for you to see something JAMF says they will implement once they agree it should be in the roadmap.

tlarkin
Honored Contributor

Hi Everyone,

I've done similar things with curl. Basically have your script try to curl an internal site, and if it can't it exits with a status other than zero. If it can, it just writes the most up-to-date information to a flat file via some logic in your script. Then at recon, have your EA read the flat file. Example of curl:

$ curl -I http://casperweb.local
HTTP/1.1 200 OK
Date: Mon, 21 Apr 2014 21:42:06 GMT
Server: Apache/2.2.22 (Ubuntu)
Last-Modified: Wed, 29 May 2013 20:46:16 GMT
ETag: "340a43-b1-4dde1791cc9e8"
Accept-Ranges: bytes
Content-Length: 177
Vary: Accept-Encoding
Content-Type: text/html
X-Pad: avoid browser bug

tlark:Contents tlarkin$ echo $?
0
tlark:Contents tlarkin$ curl -I http://casperwebfake.local
curl: (6) Could not resolve host: casperwebfake.local
tlark:Contents tlarkin$ echo $?
6

The first command is successful, so it returns exit status 0. The second fails, and then returns exit status 6. Write these attributes to a plist file and then update them accordingly. Next time the device checks in, it will just read the value of that flat file. I know there can be some issues with it being updated in real time, but once that value is set, it should fall into the smart group of that OU, until it changes. Most of the time these sort of situations are pretty static, so the device/user won't change that often. If this is for scoping something that is dynamic I think using LDAP groups and Self Service may be a better fit.

Hope this helps,
Tom

mm2270
Legendary Contributor III

The curl trick won't work so well for those of us that have a Limited Access JSS, since the curl command might actually work, even if the Mac isn't internal on the network. I personally have preferred to use a ping to a domain controller (assuming your network teams allow a ping to it) and add a count of 2 to the command so it doesn't spin off endlessly.

sosnovsken
New Contributor III

Thanks everyone! I think writing to the flat file is going to work perfectly for our needs. Does anyone see a problem with storing it in a folder path like /usr/local/myOrgName?

sosnovsken
New Contributor III

mm2270
Legendary Contributor III

@sosnovsken - as long as there is no sensitive information in the file, that seems like a valid enough path to store it in to me.

Voted up your Feature Request.

bentoms
Release Candidate Programs Tester

@sosnovsken, voted up FR too.

FWIW, we had the same issue on v8 using an EA to get the management account from the API (@mm2270 helped with the script).

We've a clustered JSS, so externally it would blank out the EA.

The FR would have stopped that.

tlarkin
Honored Contributor

Hi @mm2270

In response to this:

The curl trick won't work so well for those of us that have a Limited Access JSS, since the curl command might actually work, even if the Mac isn't internal on the network. I personally have preferred to use a ping to a domain controller (assuming your network teams allow a ping to it) and add a count of 2 to the command so it doesn't spin off endlessly.

Yup I agree with everything you stated here. I just was using my JSS as an example, since that is the only web server I have to test with on my local production laptop. I have used curl in the past to hit internal only sites at previous jobs. We had many web services that you could only hit when on the organizations network. Of course there are many ways to accomplish the same goals. You could ping an internal server as well, like you pointed out.

-Tom

sosnovsken
New Contributor III

@tlarkin @mm2270 at the moment, we have a good number of public IP blocks that we assign our clients... which makes it really easy to compare against the computer's current IP. If we end up moving to NAT/Private IP space (which I think is likely in the next few years) those suggestions of pinging/web requesting against an internal network resource will work beautifully. Thanks for the ideas!