Extension to the samba-tool group subcommand functionality to allow listing of the...
authorLukasz Zalewski <lukas@eecs.qmul.ac.uk>
Tue, 1 May 2012 20:17:33 +0000 (21:17 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 2 May 2012 22:09:09 +0000 (08:09 +1000)
source4/scripting/python/samba/netcmd/group.py
source4/scripting/python/samba/tests/samba_tool/group.py
source4/setup/tests/blackbox_group.sh

index 004307b1834e6ff189bf8ff676009b59f5c9534f..5cd9ba8701b794468183745f41497578bb72cde8 100644 (file)
@@ -20,6 +20,8 @@
 import samba.getopt as options
 from samba.netcmd import Command, SuperCommand, CommandError, Option
 import ldb
+from samba.ndr import ndr_unpack
+from samba.dcerpc import security
 
 from getpass import getpass
 from samba.auth import system_session
@@ -260,6 +262,7 @@ Example2 shows how to remove a single user account, User2, from the supergroup A
             raise CommandError('Failed to remove members "%s" from group "%s"' % (listofmembers, groupname), e)
         self.outf.write("Removed members from group %s\n" % groupname)
 
+
 class cmd_group_list(Command):
     """List all groups"""
 
@@ -293,6 +296,68 @@ class cmd_group_list(Command):
         for msg in res:
             self.outf.write("%s\n" % msg.get("samaccountname", idx=0))
 
+
+class cmd_group_list_members(Command):
+    """List all members of an AD group
+
+This command lists members from an existing Active Directory group. The command accepts one group name.
+
+Example1:
+samba-tool group listmembers \"Domain Users\" -H ldap://samba.samdom.example.com -Uadministrator%passw0rd
+"""
+
+    synopsis = "%prog <groupname> [options]"
+
+    takes_options = [
+        Option("-H", "--URL", help="LDB URL for database or target server", type=str,
+               metavar="URL", dest="H"),
+        ]
+
+    takes_optiongroups = {
+        "sambaopts": options.SambaOptions,
+        "credopts": options.CredentialsOptions,
+        "versionopts": options.VersionOptions,
+        }
+
+    takes_args = ["groupname"]
+
+    def run(self, groupname, credopts=None, sambaopts=None, versionopts=None, H=None):
+        lp = sambaopts.get_loadparm()
+        creds = credopts.get_credentials(lp, fallback_machine=True)
+
+        try:
+            samdb = SamDB(url=H, session_info=system_session(),
+                          credentials=creds, lp=lp)
+
+            search_filter = "(&(objectClass=group)(samaccountname=%s))" % groupname
+            res = samdb.search(samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE,
+                               expression=(search_filter),
+                               attrs=["objectSid"])
+
+            if (len(res) != 1):
+                return
+
+            group_dn = res[0].get('dn', idx=0)
+            object_sid = res[0].get('objectSid', idx=0)
+
+            object_sid = ndr_unpack(security.dom_sid, object_sid)
+            (group_dom_sid, rid) = object_sid.split()
+
+            search_filter = "(|(primaryGroupID=%s)(memberOf=%s))" % (rid, group_dn)
+            res = samdb.search(samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE,
+                               expression=(search_filter),
+                               attrs=["cn"])
+
+            if (len(res) == 0):
+                return
+
+            for msg in res:
+                self.outf.write("%s\n" % msg.get("cn", idx=0))
+
+        except Exception, e:
+            raise CommandError('Failed to list members of "%s" group ' % groupname, e)
+
+
 class cmd_group(SuperCommand):
     """Group management"""
 
@@ -302,3 +367,4 @@ class cmd_group(SuperCommand):
     subcommands["addmembers"] = cmd_group_add_members()
     subcommands["removemembers"] = cmd_group_remove_members()
     subcommands["list"] = cmd_group_list()
+    subcommands["listmembers"] = cmd_group_list_members()
index be10716f46cbbbee0ac5812502f61b88bc6a399f..b7f751747dccf60241fd171637a703caefc987a6 100644 (file)
@@ -118,6 +118,25 @@ class GroupCmdTestCase(SambaToolCmdTest):
             found = self.assertMatch(out, name,
                                      "group '%s' not found" % name)
 
+    def test_listmembers(self):
+        (result, out, err) = self.runsubcmd("group", "listmembers", "Domain Users",
+                                            "-H", "ldap://%s" % os.environ["DC_SERVER"],
+                                            "-U%s%%%s" % (os.environ["DC_USERNAME"],
+                                                          os.environ["DC_PASSWORD"]))
+        self.assertCmdSuccess(result, "Error running listmembers")
+
+        search_filter = "(|(primaryGroupID=513)(memberOf=CN=Domain Users,CN=Users,%s))" % self.samdb.domain_dn()
+
+        grouplist = self.samdb.search(base=self.samdb.domain_dn(),
+                                      scope=ldb.SCOPE_SUBTREE,
+                                      expression=search_filter,
+                                      attrs=["cn"])
+
+        self.assertTrue(len(grouplist) > 0, "no groups found in samdb")
+
+        for groupobj in grouplist:
+            name = groupobj.get("cn", idx=0)
+            found = self.assertMatch(out, name, "group '%s' not found" % name)
 
     def _randomGroup(self, base={}):
         """create a group with random attribute values, you can specify base attributes"""
index 08b8e5b56e22643606240a45dbb0d18be8881015..aaddeebf3b210b033a3f9334b198cf3fb2757fce 100755 (executable)
@@ -71,4 +71,10 @@ testit "group delete" $samba_tool group delete $CONFIG ddg
 testit "group delete" $samba_tool group delete $CONFIG gdg
 testit "group delete" $samba_tool group delete $CONFIG udg
 
+#test listing of all groups
+testit "group list" $samba_tool group list $CONFIG
+
+#test listing of members of a particular group
+testit "group listmembers" $samba_tool group listmembers $CONFIG Users
+
 exit $failed