Posted on 03-07-2016 01:22 PM
Hello'
Objective: Create smart group to report on systems that users have administrative rights.
I created the extension attribute via script. It is accurately reporting accounts that have administrative rights. The problem is when I create the logic for the smart group there is no way for me to differentiate/exclude from known admin accounts.
There are three possible admin accounts that may exist on a given system. When I create the criteria logic I make an entry for each that "is not" admdsk, and/or "is not" mbadmin and finish with "is not" blank. tried every possible combination of and's an or's with and with out parentheeses to no avail. I'm pretty sure this will require a appended script that will exclude the known accounts before output. I'm guessing this is an issue because the script output is multiple account name separated by a space. Here is the existing script that makes the extension attribute output.
list=()
for username in $(dscl . list /Users UniqueID | awk '$2 > 500 { print $1 }'); do
if [[ $(dsmemberutil checkmembership -U "${username}" -G admin) != not ]]; then
# Any reported accounts are added to the array list
list+=("${username}")
fi
done
echo "result>${list[@]}</result"
Solved! Go to Solution.
Posted on 03-09-2016 03:06 PM
Guess you don't make your admins hidden accounts, even though that is what your original script is based upon (user id greater than 500). You can specify an array of known admin accounts and check against that instead. Based on your output above, this should just return thar00. Change the array to account for any known admins you wish to exclude from the result.
You could also add a check at the end and if the array is empty specify the output.
#!/bin/bash
#Script to detect if a computer has unknown local admin accounts
#Initialize array
declare -a admin_list=()
# Declare known admins
declare -a known_admins=('root' 'dsadmin')
# Add unknown admins users to array
function add_admins
{
while [ $# -gt 0 ]
do
# Assume unknown until otherwise proven
it_admin="FALSE"
# Check admin aginst list of known admins
# If known do not add to list
for each_admin in "${known_admins[@]}"
do
if [[ "$each_admin" == "$1" ]]
then
it_admin="TRUE"
break
fi
done
# If not known now add to list
if [[ "$it_admin" == "FALSE" ]]
then
admin_list+=($1)
fi
shift
done
}
# Get admin user list and pass to function
add_admins `dscl . read /Groups/admin GroupMembership | cut -d ":" -f 2`
# Prints the array's list contents
echo "<result>$(printf '%s
' "${admin_list[@]}")</result>"
exit 0
Posted on 03-07-2016 03:52 PM
First thing is, please enclose your script in the script tags here so we can actually see the formatting. That's the button with the >_ icon on it.
Second, to solve the issue, you can use the printf command to print the array so it puts each name on its own line.
Here is your script with the script formatting in place and with the printf command included in the result output.
#!/bin/bash
#Script to detect if a computer has a local admin account on it with an UID of above 500
#Initialize array
list=()
#generate user list of users with UID greater than 500
for username in $(dscl . list /Users UniqueID | awk '$2 > 500 { print $1 }'); do
# Checks to see which usernames are reported as being admins.
# The check is running dsmemberutil's check membership and listing the accounts that are being reported as admin users.
# Actual check is for accounts that are NOT not an admin (i.e. not standard users.)
if [[ $(dsmemberutil checkmembership -U "${username}" -G admin) != not ]]; then
# Any reported accounts are added to the array list
list+=("${username}")
fi
done
# Prints the array's list contents
echo "<result>$(printf '%s
' "${list[@]}")</result>"
Last thing is, I'm not completely certain if your test condition will return the results you're looking for. Typically the !=
syntax looks for an exact match or in this case, non match. Since the dsmemberutil command isn't returning just "not" as its result, it may end up pulling in accounts that are in fact not admins. I haven't really tested your script to see about that though. If you find its not working as expected, you can change the line to look like this, which should work
if [[ ! $(dsmemberutil checkmembership -U "${username}" -G admin) =~ not ]]; then
Posted on 03-07-2016 07:16 PM
First, thank you for the direction regarding the tags.
OK I left the old script in place for "User Admins" attribute and created the EA "User Admins v2" with your script. There are three accounts on this system, the test account is a standard account. The output was identical whether I used
#if [[ $(dsmemberutil checkmembership -U "${username}" -G admin) != not ]]; then
OR
#if [[ ! $(dsmemberutil checkmembership -U "${username}" -G admin) =~ not ]]; then
here is the output
Posted on 03-08-2016 01:57 PM
I'd probably do it the other way around. Rather than go through every user and work out what their UID is and then check their membership, I'd get a list of the local admins and then remove those that don't have a UID greater than 500
#!/bin/bash
#Script to detect if a computer has a local admin account on it with an UID of above 500
#Initialize array
declare -a admin_list=()
# Test admin users and add users with id greater than 500 to array
function test_for_admins
{
while [ $# -gt 0 ]
do
if [ `id -u $1` -gt 500 ]
then
admin_list+=($1)
fi
shift
done
}
# Get admin user list and pass to function
test_for_admins `dscl . read /Groups/admin GroupMembership | cut -d ":" -f 2`
# Prints the array's list contents
echo "<result>$(printf '%s
' "${admin_list[@]}")</result>"
exit 0
Posted on 03-09-2016 11:41 AM
Thank you sean, We are getting closer, but I am still not able to get the Smart Computer Group logic to exclude known accounts. Excuse my script illiteracy, but would it be possible for the output to be filtered to exclude variables (known accounts) ? Resulting in just a users account (with admin) or a blank output (no other account with admin) ? Here is the current output
Posted on 03-09-2016 03:06 PM
Guess you don't make your admins hidden accounts, even though that is what your original script is based upon (user id greater than 500). You can specify an array of known admin accounts and check against that instead. Based on your output above, this should just return thar00. Change the array to account for any known admins you wish to exclude from the result.
You could also add a check at the end and if the array is empty specify the output.
#!/bin/bash
#Script to detect if a computer has unknown local admin accounts
#Initialize array
declare -a admin_list=()
# Declare known admins
declare -a known_admins=('root' 'dsadmin')
# Add unknown admins users to array
function add_admins
{
while [ $# -gt 0 ]
do
# Assume unknown until otherwise proven
it_admin="FALSE"
# Check admin aginst list of known admins
# If known do not add to list
for each_admin in "${known_admins[@]}"
do
if [[ "$each_admin" == "$1" ]]
then
it_admin="TRUE"
break
fi
done
# If not known now add to list
if [[ "$it_admin" == "FALSE" ]]
then
admin_list+=($1)
fi
shift
done
}
# Get admin user list and pass to function
add_admins `dscl . read /Groups/admin GroupMembership | cut -d ":" -f 2`
# Prints the array's list contents
echo "<result>$(printf '%s
' "${admin_list[@]}")</result>"
exit 0
Posted on 03-14-2016 01:21 PM
Thank you Sean, this works well appears that I only have to set my smart group to Admin Users "is not" blank.
Posted on 03-14-2016 02:39 PM
Cool. You may want to mark it resolved for anyone else that may search in the future.
Posted on 03-14-2016 04:45 PM
Posted on 03-15-2016 01:32 AM
Just posting my version, slightly different use case... but might be handy for some.
Posted on 03-17-2016 05:23 AM
@bentoms Careful with your script. You may get false positives. Eg.
#!/bin/bash
#What if the user is called David Min and is not a local account admin
adminGroupMembership="root admin"
loggedInUser=dmin
if [[ $adminGroupMembership =~ "$loggedInUser" ]]
then
echo "User is admin"
else
echo "User is not admin"
fi
exit 0
This is why I used an array and did exact matches.
Posted on 05-23-2018 08:47 PM
This script it working well for me, however, I'd like to create a smart group based on this EA. At the moment, if it finds no known users, the result is blank. The problem with this is that I can't report on a blank EA field. Is there to modify this, so if no users were found it prints something like "No Admin Users"?
Posted on 05-30-2018 09:17 PM
In response to @phillnz, I tried editing the original script by sean to print an output if the admin_list array is empty. I'm fairly novice at this but it seems to work. Feel free to suggest any improvements.
#!/bin/bash
#Script to detect if a computer has unknown local admin accounts
#Initialize array
declare -a admin_list=()
# Declare known admins
declare -a known_admins=('root' 'dsadmin')
# Add unknown admins users to array
function add_admins
{
while [ $# -gt 0 ]
do
# Assume unknown until otherwise proven
it_admin="FALSE"
# Check admin aginst list of known admins
# If known do not add to list
for each_admin in "${known_admins[@]}"
do
if [[ "$each_admin" == "$1" ]]
then
it_admin="TRUE"
break
fi
done
# If not known now add to list
if [[ "$it_admin" == "FALSE" ]]
then
admin_list+=($1)
fi
shift
done
}
# Get admin user list and pass to function
add_admins `dscl . read /Groups/admin GroupMembership | cut -d ":" -f 2`
# Prints the array's list contents
if [[ $admin_list == "" ]]
then
echo "No unknown admin users"
else
echo "<result>$(printf '%s
' "${admin_list[@]}")</result>"
fi
exit 0