Way to pull local user accounts from Casper reports

antoinekinch
New Contributor III

Is there a way to pull UID's (User ID's) for Macs in the JAMF database from the GUI or does a script need to be run on each machine to get this? The goal is to run a report to find out which accounts on the machines are network accounts and which accounts are local accounts. Local accounts are created with numbers starting with 501 and network account UID's are 9 digits long.

7 REPLIES 7

tlarkin
Honored Contributor

Hi @bajankinch

There are probably a few ways to accomplish this, but depending on the higher goal one method may be better than the other. Are you looking to report UIDs, or take action on them? There are also some caveats to consider.

I have a few things posted on my GitHub account, found here:

https://github.com/t-lark/example-scripts

example code snip:

# grabs the current user who owns /dev/console

currentUser=$(ls -l /dev/console | awk '{ print $3 }')

# local user accounts with UID of 501 to 999
# this builds an array of all local user accounts betwen this UID range on the local Mac

localUsers=$(dscl . list /Users UniqueID | awk '$2 > 500 && $2 < 1000 { print $1 }')

# listing all mobile/network users
# this will display all connected and synchronized protable users on a Mac
# this only works for accounts syncrhonized as dscl is pointed towards the local BSD database

netUsers=$(dscl . list /Users UniqueID | awk '$2 > 1000 { print $1 }')

# allUsers will list all users above UID 500, it is assumed any management account
# used for IT or otherwise will have a UID lower than 500

allUsers=$(dscl . list /Users UniqueID | awk '$2 > 500 { print $1 }')

Local user accounts created through normal methods (system preferences, dscl, etc) will start at UID 501 and will stop at UID 999. UID 1000 is reserved for the directory admin user of Open Directory, and UID 1001 is the first UID for any Network/LDAP account. If you are connected to AD, the AD plugin will grab the UID of the AD account, which could be a lot higher number than 1001. It has been this way in OS X since the NetInfo days.

The caveats are that local admins can change their UID in System Preferences. So, I could go edit my user and change my UID from 501, to 4589732 if I wanted to. I just created a local user account called 'test' and changed the UID from System preferences to a higher number and it worked:

bash-3.2$ dscl . read /Users/test UniqueID
UniqueID: 9999999

So, this could obviously create some false positives. Furthermore, if I had admin access and I am a smart user, and I can Google the right things I can modify user attributes from the terminal, and make a local account look like a LDAP account if I wanted to. Of course this requires local admin rights.

Another caveat would be, on the workflow of how IT deploys local admin accounts for IT use. If you are deploying hidden accounts under UID 500, you can simply create lists/arrays of user IDs in ranges of 501 and greater and ignore the accounts you use for internal IT use. So, this could also create false positives or toss a wrench into your workflow so to speak unless you account for any local account that is not for a user but rather for IT or another department.

To report on this I would think an extension attribute script to populate the user name and UID or just UID would be something pretty flexible and give you both options of reporting or taking action by scoping a Casper policy to a smart group based on the results of the UID returned. The extension attribute will run on an inventory update as well, so if more users are added to a device, or a user changes their UID, it would track the changes and updates.

The example code I posted is from an example source file I put up on my GitHub after I did a presentation at one of the Macbrained events in the Bay Area. So, it is all proof of concept, but you could take those dscl commands and use them to output the current user, or all users, or users with in a certain UID range to an extension attribute in the JSS.

So, depending on what you want to do, would probably dictate the workflow used. I hope this helps, and please post back any cool solutions you come up with.

Thanks,
Tom

antoinekinch
New Contributor III

Thanks @tlarkin. I am still working on how to do this. Again the goal is to run a report on each machine in the JSS database and return all UID's that are between 501 and 999. The information is already in the database it's all abut extracting it. With the smart groups criteria you cannot select greater than or less than for the UID's!!! I don't think you can select UID as a criteria either but if you go into the machine record and look at local user accounts the information is there!

JPDyson
Valued Contributor

Well, there's the API route... this would get you the node you're looking for:

#!/bin/sh

apiURL="https://you.should.know:8443/JSSResource/computers/macaddress/"
apiUser="apiuser"
apiPass="supersecretpassword"
MacAdd=$( networksetup -getmacaddress en0 | awk '{ print $3 }' | sed 's/:/./g' )

localAccounts=$( curl -s -u $apiUser:$apiPass "$apiURL$MacAdd" | xpath /computer/groups_accounts/local_accounts )

mm2270
Legendary Contributor III

You could go the API route, but why not set up an Extension Attribute that pulls a list of all accounts in the range you're looking for, let it sit for a couple of days, then run an advanced report on all Macs and add the EA into the Display Fields?

tlarkin
Honored Contributor

Hi @bajankinch][/url

Thanks for the follow up on what you are trying to accomplish. Like, @mm2270][/url mentioned a script that populates an extension attribute that can be reported on might be the best way to accomplish this. While you can run SQL statements against the database, I would say a best practice would be to leverage the API in that sense. The pro about running the EA is that it would always update every time a device checks in for inventory. Where as the API route would have to be ran on demand or a scheduled basis against every device, and you are storing a password in a script.

You can then build saved searches that output the result of your EA, which can be every local user in UID range 501 to 999. Just have to be weary of the false positives you can get when users get smart and change their UID.

Here is some example code to maybe work with:

#!/bin/bash

localUsers=$(dscl . list /Users UniqueID | awk '$2 > 500 && $2 < 1000 {print $1, $2}')

for u in ${localUsers} ; do
  echo "<result>${u}</result>"
done

Here is the output of that code:

bash-3.2$ bash ea_local_userid.sh 
<result>tlarkin</result>
<result>501</result>

I changed my test account back to UID 509 to see how multiple users retrun:

$ bash ea_local_userid.sh 
<result>test</result>
<result>509</result>
<result>tlarkin</result>
<result>501</result>

ahambidge
New Contributor II

@bajankinch, this information is already stored in the database. :) However, I don't believe you can query it from the Advanced Search page or anywhere else in the web frontend, so you'll have to get 'dirty' with MySQL.

Try this query:

select * from user_receipts limit 1000;

I actually just emailed my rep just last week about finding out where the JSS has the user admin rights information stored, and noticed that it also contained the information you're looking for. Hopefully this helps!

antoinekinch
New Contributor III

Thanks all, this has been really helpful!