nbalonso.com

Extending MunkiReport-php

| Comments

In my organization we use Microsoft SCCM for managing Windows clients and Munki for managins OS X clients.

I have used SCCM for a while now and have to say that I find it very very powerful. The fact that collects plenty of information from the clients, uploads it to a SQL db and keeps a history, plus the ability of create dynamic computer collections based on querys to the SQL and then target those groups with tasks makes it extremely useful in an enterprise environment. Plus the amazing reports you can get if you have an SQL guru around!

As any organization we try to treat the clients as homogenous as possible, regardless of the platform they run. This makes me move forward on the features/options that we have for OSX.

Now we are preparing reports from all computers to know who has administrator access to which machines. This is simple to do from the SCCM db, but we do not have this available for Mac.

I use Munki as the main deployment tool and MunkiReport-php to collect client information. The reports in there are very useful to track installations, computer locations based on networks, collect hardware details, licensed application installs… but not admin users yet!

So here we go to add this functionality.

First of all we need a way of getting the list of users who are admins. On OS X you can be admin with two different properties, by being a member of the admin group or by having a primary group ID equal to 80. So we need to consider both.  The first one is simple, a simple dscl query will do and then we can tidy up a bit with awk to remove the property name and a touch of regular expressions to get rid of any preceding space

1
bash-3.2$ dscl . -read /Groups/admin GroupMembership | awk '{gsub("GroupMembership:", "");print}' | sed -e 's/^[ ]*//'

Great, now for the second part we are going to check all the local users to see if any of them has primary group ID equal to 80. A loop through the users should do and maybe we can exclude any username that starts by underscore to save some cpu cycles.

1
2
3
4
5
for other_user in `dscl . -list /Users | grep -v "^_"` ; do
  if [ "`dscl . -read /Users/${other_user} PrimaryGroupID | awk '{print $2}'`" == "80" ]; then
    admin_users+=( $other_user )
  fi
done

A bash script combining both with a bit of logic to avoid listing the same user twice could look like this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/sh
# Extracting all the admin users from a computer
#initial list based on group membership
admin_users=`dscl . -read /Groups/admin GroupMembership | awk '{gsub("GroupMembership:", "");print}' | sed -e 's/^[ ]*//'`

#extra paranoid check. Skipping ^_
for other_user in `dscl . -list /Users | grep -v "^_"` ; do
  #checking per user's primary group membership to catch non-standard admins
  if [ "`dscl . -read /Users/${other_user} PrimaryGroupID | awk '{print $2}'`" == "80" ]; then
      #avoiding to add the user twice to the list
      if [ "`echo ${admin_users} | grep ${other_user}`" == ""  ]; then
          admin_users+=( $other_user )
      fi
    fi
done

echo "${admin_users[@]}"

exit 0

Now that we are able to do this in bash and we tested it to work in 10.6 through 10.8 let’s get it to MunkiReport-php. We want to put this into the postflight script so that is executed every time Munki finishes its things. If read carefully what the postflight does is to merge two plist files into one then upload that file to the server. We are going to merge one more plist file so that our list of admins gets uploaded together with the rest of the info.

The idea is to integrate our bash script with a modification of writing to a plist before the merging, then we merge into the temporary plist and lastly we add our admin plist to the delete task.

Open some space into line #29 and include

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#admin users list
admin_users=`dscl . -read /Groups/admin GroupMembership | awk '{gsub("GroupMembership:", "");print}' | sed -e 's/^[ ]*//'`

#extra paranoid check. Skipping ^_
for other_user in `dscl . -list /Users | grep -v "^_"` ; do
  #checking per user's primary group membership to catch non-standard admins
  if [ "`dscl . -read /Users/${other_user} PrimaryGroupID | awk '{print $2}'`" == "80" ]; then
      #avoiding to add the user twice to the list
      if [ "`echo ${admin_users} | grep ${other_user}`" == ""  ]; then
          admin_users+=( $other_user )
      fi
    fi
done
ADMINUSERSPLIST="/tmp/adminUsersArray"
#echo is needed to beat the encoding of the initial list
defaults write "$ADMINUSERSPLIST" "adminUsersArray" -array `echo ${admin_users[@]}`

Then below the initial line #32

1
$PLISTBUDDY -c "Merge ${ADMINUSERSPLIST}.plist :MachineInfo" "$TMPPLIST"

And finally add the new plist to the cleanup task at the end

1
2
3
# Clean up and exit
rm -f "$REPORTTMP" "$TMPPLIST" "$PROFILEPLIST" "${ADMINUSERSPLIST}.plist"
exit 0

The data is now on the server but is useless if you are not able to see it. I know this is trivial simple php (maybe the whole post is) but for completeness I’ll put it.

Let’s say you want to see the information next to each computer in the client_list.php. Between the lines #22 and #23 you can add a new column

1
<th>Local Admins</th>

And then read the actual data from the plist you uploaded and write on each computer’s row with a simple error check and touch of logic to hide the root user that is displayed for 10.8 clients

1
2
3
4
5
6
7
8
9
10
11
<td>
  <?if($client->report_plist && isset($client->report_plist['MachineInfo']['adminUsersArray'])):?>
    <?php
      //Get the array list separated by spaces
      $usersArrayList = implode(' ', $client->report_plist['MachineInfo']['adminUsersArray'] );
      //Remove root
      $usersArrayList = str_replace( "root", "", $usersArrayList);
      echo $usersArrayList;
    ?>
  <?endif?>
</td>

PS: the installation and configuration of MunkiReport-php is (as you just saw) not covered. If you have some trouble with the installation and/or configuration let me know. It has been a long time since I configured mine but I’ll try.

PS2: MunkiWebAdmin is probably the way to go in the future, but for now MunkiReport-php provides very easy AD authentication for my technicians based on a simple .htaccess file and easy extension with simple technologies. The bigger community around MunkiWebAdmin and a much more powerful language are on the other side of the scale

Comments