Wednesday, November 16, 2011

OS X groups, subgroups and GeneratedUIDs

OS X groups are more confusing than they need to be, due to the use of UUIDs. First, lets create a group to test with and include a single user (test1):
$ sudo dseditgroup -o create -t group test00
$ sudo dseditgroup -o edit -a test1 -t user test00
$ dseditgroup -o read test00
dsAttrTypeStandard:GeneratedUID -
  C110609F-0C0A-42E7-B663-D93BA03ECDAC
dsAttrTypeStandard:RecordName -
  test00
dsAttrTypeStandard:AppleMetaNodeLocation -
  /Local/Default
dsAttrTypeStandard:GroupMembers -
  6D456134-85E6-4912-88C7-7C6139057B9B
dsAttrTypeStandard:RecordType -
  dsRecTypeStandard:Groups
dsAttrTypeStandard:NestedGroups -
dsAttrTypeStandard:PrimaryGroupID -
  505
dsAttrTypeStandard:GroupMembership -
  test1
Note that we have GroupMembership that includes test1 and the GroupMembers attribute lists the GUID for the test1 user. Neither of these attributes tell us about groups that are members of this group. To see how they are stored, we will add a subgroup:
$ sudo dseditgroup -o edit -a testsubgroup -t group test00
$ dseditgroup -o read test00
dsAttrTypeStandard:GeneratedUID -
  C110609F-0C0A-42E7-B663-D93BA03ECDAC
dsAttrTypeStandard:RecordName -
  test00
dsAttrTypeStandard:AppleMetaNodeLocation -
  /Local/Default
dsAttrTypeStandard:GroupMembers -
  6D456134-85E6-4912-88C7-7C6139057B9B
dsAttrTypeStandard:RecordType -
  dsRecTypeStandard:Groups
dsAttrTypeStandard:NestedGroups -
  6B3D7A4A-A795-4569-8640-2105F73EEA6B
dsAttrTypeStandard:PrimaryGroupID -
  505
dsAttrTypeStandard:GroupMembership -
  test1
Note that the subgroup UUID is now listed under NestedGroups, but the human-readable name is not, presumably because apple wanted to make this as painful as possible. There isn't a nice way to map UUID to a recordname, but searching in the local node does work (although it seems to ignore the output formatting options):
$ dscl -plist . -search /Groups GeneratedUID 6B3D7A4A-A795-4569-8640-2105F73EEA6B
testsubgroup  GeneratedUID = (
    "6B3D7A4A-A795-4569-8640-2105F73EEA6B"
)
So the outcome of this is that to code to answer a simple question: 'who are the members of this group?' is actually really complicated.

There is however a way to check if a user is a member of a group, and it will follow nested group relationships:
$ sudo dseditgroup -o edit -a test2 -t user testsubgroup
$ dseditgroup -o checkmember -m test2 test00
yes test2 is a member of test00

No comments: