[PATCH] Add Unix attributes to a user or group in AD

Rowland Penny repenny241155 at gmail.com
Fri Nov 20 09:27:42 UTC 2015


On 20/11/15 08:13, Michael Adam wrote:
> On 2015-11-16 at 19:14 +0000, Rowland Penny wrote:
>> On 16/11/15 14:34, Michael Adam wrote:
>>> Rowland,
>>>
>>> I lost track of the most up-to-date patches.
>>> (Scattered over several mail threads, I think.)
>>> Could you please re-send the latest, complete
>>> patchset for this?
>>>
>>> Thanks a lot!
>>>
>>> Michael
>>>
>>>
>> OK, here are the patches as requested by Michael Adam:
> Thanks for updating the patches!
>
> I'd really like someone who is more into our python/samba-tool
> code to review. Generally the patches look pretty good to me.
> Just two comments right now:
>
> - I still don't quite understand, why you taken an all-or-nothing
>    approach instead of possibly selectively setting unix
>    attributes. And allowing for modification / addition of attribs
>    on objects that already have a nis attribute. It does not
>    seem natural to me.

I am only doing what happens when you add rfc2307 attributes with ADUC, 
this is also the way samba-tool works when you create a user with 
rfc2307 attributes i.e.

samba-tool user add User5 passw5rd --nis-domain=samdom 
--unix-home=/home/User5
--uid-number=10005 --login-shell=/bin/false --gid-number=10000

I entirely agree that samba-tool needs something to add/mod attributes, 
but this will need to be another patch.


>
> - In the first patch, this part seems slightly inconsistent:
>
>> +        if len(res) == 0:
>> +            raise Exception('Unable to find object "%s"' %
>> +                            search_filter)
>> +        assert(len(res) == 1)
> Why once an exception and then assert?
> I could imagine s/th like:
> if len(res) > 1:
>    raise Exception('More than one obj found...")

Yes the patch could be better, still learning python :-)

Will come up with a new patch

Rowland

>
>> The first patch is required by the second & third patches.
>> The second patch adds unix attributes to a user similar to the way ADUC does
>> it.
>> The third patch adds unix attributes to a group, again similar to the way
>> ADUC does it.
>> The fourth patch updates the samba-tool manpage with reference to these
>> patches.
>>
>> I had a look at the samba-tool user add test, but I am struggling to see
>> just how I can alter it for my patches. It doesn't help that it doesn't seem
>> to test the creation of Posixusers in the way that samba-tool now creates
>> them.
> This patch added tests for posix attributes:
> 071047e8953f36a4c71c30d9540323578a4204f2
> Maybe Andrew has hints as to creating tests?
>
> Cheers - Michael
>
>
>
>>  From 9dde7f59a1733a88bc6bd711e0953bcf2eea5bbf Mon Sep 17 00:00:00 2001
>> From: Rowland Penny <repenny241155 at gmail.com>
>> Date: Mon, 16 Nov 2015 15:44:06 +0000
>> Subject: [PATCH 1/4] samdb.py: get object dn from samaccountname
>>
>> Signed-off-by: Rowland Penny <repenny241155 at gmail.com>
>> ---
>>   python/samba/samdb.py |   16 ++++++++++++++++
>>   1 file changed, 16 insertions(+)
>>
>> diff --git a/python/samba/samdb.py b/python/samba/samdb.py
>> index 5750291..155d0df 100644
>> --- a/python/samba/samdb.py
>> +++ b/python/samba/samdb.py
>> @@ -944,3 +944,19 @@ accountExpires: %u
>>           is removed, this routine will put a tombstone in the record.
>>           '''
>>           return dsdb_dns.replace_by_dn(self, dn, new_records)
>> +
>> +    def get_object_dn(self, search_filter):
>> +        """Gets an objects DN
>> +
>> +        :param search_filter: LDAP filter to find the object (eg
>> +            samaccountname=name)
>> +        """
>> +        res = self.search(base=self.domain_dn(),
>> +                          scope=ldb.SCOPE_SUBTREE,
>> +                          expression=search_filter,
>> +                          attrs=["dn", "sAMAccountName"])
>> +        if len(res) == 0:
>> +            raise Exception('Unable to find object "%s"' %
>> +                            search_filter)
>> +        assert(len(res) == 1)
>> +        return res[0].dn
>> -- 
>> 1.7.10.4
>>
>>  From 87c2734c0fed8be0cd87ec6f4a1c5bf686e96807 Mon Sep 17 00:00:00 2001
>> From: Rowland Penny <repenny241155 at gmail.com>
>> Date: Mon, 16 Nov 2015 15:51:42 +0000
>> Subject: [PATCH 2/4] user.py: update user with nis attributes
>>
>> Signed-off-by: Rowland Penny <repenny241155 at gmail.com>
>> ---
>>   python/samba/netcmd/user.py |  156 +++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 156 insertions(+)
>>
>> diff --git a/python/samba/netcmd/user.py b/python/samba/netcmd/user.py
>> index ec91a93..5e491af 100644
>> --- a/python/samba/netcmd/user.py
>> +++ b/python/samba/netcmd/user.py
>> @@ -611,6 +611,161 @@ Example3 shows how an administrator would reset TestUser3 user's password to pas
>>           self.outf.write("Changed password OK\n")
>>   
>>   
>> +class cmd_user_nis_add(Command):
>> +    """Add NIS attributes to a user.
>> +
>> +This command adds NIS info to a user account in the Active
>> +Directory domain.
>> +The username specified on the command is the sAMaccountName.
>> +
>> +Unix (RFC2307) attributes will be added to the user account.
>> +Add 'idmap_ldb:use rfc2307 = Yes' to smb.conf to use these
>> +attributes for UID/GID mapping.
>> +
>> +The command may be run from the root userid or another authorized userid.
>> +The -H or --URL= option can be used to execute the command
>> +against a remote server.
>> +
>> +Example:
>> +samba-tool user nisadd User1 --nis-domain=samdom --uid-number=10005 \
>> +--unix-home=/home/User1 --login-shell=/bin/false [--group-name=unixgroup]
>> +
>> +The example shows how to add RFC2307/NIS attributes to a domain
>> +enabled user account.
>> +The first four parameters are mandatory.
>> +
>> +if the parameter '--group-name' is given, then the groups 'gidNumber'
>> +will be obtained and used for the users 'gidNumber' attribute, this
>> +does of course mean that the group MUST have a 'gidNumber.
>> +
>> +If the last parameter, '--group-name' & is omitted, the users gidNumber
>> +will be  set to the gidNumber found in Domain Users.
>> +This means that 'Domain Users' MUST  have a gidNumber.
>> +"""
>> +    synopsis = "%prog <username> [options]"
>> +
>> +    takes_options = [
>> +        Option("-H", "--URL", help="LDB URL for database or target server",
>> +                type=str, metavar="URL", dest="H"),
>> +        Option("--nis-domain", help="User's Unix/RFC2307 NIS domain",
>> +                type=str),
>> +        Option("--unix-home", help="User's Unix/RFC2307 home directory",
>> +                type=str),
>> +        Option("--group-name", help="A Unix/RFC2307 enabled AD group",
>> +                type=str),
>> +        Option("--login-shell", help="User's Unix/RFC2307 login shell",
>> +                type=str),
>> +        Option("--uid-number", help="User's Unix/RFC2307 numeric UID",
>> +                type=str),
>> +        Option("--gid-number", help="User's Unix/RFC2307 numeric GID number",
>> +                type=str),
>> +
>> +    ]
>> +
>> +    takes_args = ["username"]
>> +
>> +    takes_optiongroups = {
>> +        "sambaopts": options.SambaOptions,
>> +        "credopts": options.CredentialsOptions,
>> +        "versionopts": options.VersionOptions,
>> +        }
>> +
>> +    def run(self, username, credopts=None, sambaopts=None, versionopts=None,
>> +            H=None, nis_domain=None, unix_home=None, uid_number=None,
>> +            gid_number=None, group_name=None, login_shell=None):
>> +
>> +        lp = sambaopts.get_loadparm()
>> +        creds = credopts.get_credentials(lp)
>> +
>> +        samdb = SamDB(url=H, session_info=system_session(), credentials=creds,
>> +                      lp=lp)
>> +
>> +        if None in (nis_domain, uid_number, login_shell, unix_home):
>> +            raise CommandError('Missing parameters. To enable NIS features, '
>> +                               'the following options have to be given: '
>> +                               '--nis-domain=, --uid-number, --login-shell=,'
>> +                               ' --unix-home=, Operation cancelled.')
>> +
>> +        domain_dn = samdb.domain_dn()
>> +        search_filter = "(samaccountname=%s)" % username
>> +        user_dn = samdb.get_object_dn(search_filter)
>> +
>> +        # what if user already is a NIS user??
>> +        res = samdb.search(user_dn,
>> +                          scope=ldb.SCOPE_BASE,
>> +                          attrs=["uidNumber"])
>> +        if "uidNumber" in res[0]:
>> +            raise CommandError("User %s already is a NIS user." % username)
>> +
>> +        if group_name is not None:
>> +            # get users primary GID from group_name
>> +            search_filter = "samaccountname=%s" % group_name
>> +            group_dn = samdb.get_object_dn(search_filter)
>> +            try:
>> +                res = samdb.search(group_dn,
>> +                                   scope=ldb.SCOPE_SUBTREE,
>> +                                   attrs=["gidNumber"])
>> +                assert len(res) == 1
>> +                gid_number = res[0]["gidNumber"][0]
>> +            except:
>> +                raise CommandError("Group %s does not have a gidNumber" %
>> +                                    group_name)
>> +
>> +        if group_name is None:
>> +            # set users primary GID to the one from Domain Users
>> +            du_dn = "CN=Domain Users,CN=Users," + domain_dn
>> +            try:
>> +                res = samdb.search(du_dn,
>> +                                   scope=ldb.SCOPE_SUBTREE,
>> +                                   attrs=["gidNumber"])
>> +                assert len(res) == 1
>> +                gid_number = res[0]["gidNumber"][0]
>> +            except:
>> +                raise CommandError("Domain Users Group does \
>> +not have a gidNumber attribute")
>> +
>> +        if not lp.get("idmap_ldb:use rfc2307"):
>> +            self.outf.write("You are setting a Unix/RFC2307 UID or GID. \
>> +You may want to set 'idmap_ldb:use rfc2307 = Yes' in smb.conf to use those \
>> +attributes for XID/SID-mapping.\n")
>> +
>> +        update_user = """
>> +dn: %s
>> +changetype: modify
>> +add: uid
>> +uid: %s
>> +-
>> +add: msSFU30Name
>> +msSFU30Name: %s
>> +-
>> +add: msSFU30NisDomain
>> +msSFU30NisDomain: %s
>> +-
>> +add: uidNumber
>> +uidNumber: %s
>> +-
>> +add: gidNumber
>> +gidNumber: %s
>> +-
>> +add: loginShell
>> +loginShell: %s
>> +-
>> +add: unixHomeDirectory
>> +unixHomeDirectory: %s
>> +-
>> +add: unixUserPassword
>> +unixUserPassword: ABCD!efgh12345$67890
>> +""" % (user_dn, username, username, nis_domain, uid_number, gid_number,
>> +       login_shell, unix_home)
>> +
>> +        try:
>> +            samdb.modify_ldif(update_user)
>> +        except Exception, e:
>> +            raise CommandError("Failed to update user '%s': " % username, e)
>> +
>> +        self.outf.write("User '%s' updated successfully\n" % username)
>> +
>> +
>>   class cmd_user(SuperCommand):
>>       """User management."""
>>   
>> @@ -624,3 +779,4 @@ class cmd_user(SuperCommand):
>>       subcommands["setexpiry"] = cmd_user_setexpiry()
>>       subcommands["password"] = cmd_user_password()
>>       subcommands["setpassword"] = cmd_user_setpassword()
>> +    subcommands["nisadd"] = cmd_user_nis_add()
>> -- 
>> 1.7.10.4
>>
>>  From 4e50cd59ec38d29ba6efc47b5420a47f656e74a9 Mon Sep 17 00:00:00 2001
>> From: Rowland Penny <repenny241155 at gmail.com>
>> Date: Mon, 16 Nov 2015 15:57:23 +0000
>> Subject: [PATCH 3/4] group.py: update group with nis attributes
>>
>> Signed-off-by: Rowland Penny <repenny241155 at gmail.com>
>> ---
>>   python/samba/netcmd/group.py |   94 ++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 94 insertions(+)
>>
>> diff --git a/python/samba/netcmd/group.py b/python/samba/netcmd/group.py
>> index 722bcc4..efb819a 100644
>> --- a/python/samba/netcmd/group.py
>> +++ b/python/samba/netcmd/group.py
>> @@ -408,6 +408,99 @@ samba-tool group listmembers \"Domain Users\" -H ldap://samba.samdom.example.com
>>               raise CommandError('Failed to list members of "%s" group ' % groupname, e)
>>   
>>   
>> +class cmd_group_nis_add(Command):
>> +    """Add NIS attributes to a group.
>> +
>> +This command adds NIS info to a group account in the Active Directory domain.
>> +The groupname specified on the command is the sAMaccountName.
>> +
>> +Unix (RFC2307) attributes will be added to the group account.
>> +Configure 'idmap_ldb:use rfc2307 = Yes' in smb.conf to use these GID mapping
>> +attributes.
>> +
>> +The command may be run from the root userid or another authorized userid.
>> +The -H or --URL= option can be used to execute the command against a remote
>> +server.
>> +
>> +Example:
>> +samba-tool group nisadd Group1 --nis-domain=samdom --gid-number=12345
>> +
>> +The example shows how to add RFC2307/NIS attributes to a domain enabled group
>> +account. The groups gidNumber will be set to '12345'
>> +
>> +"""
>> +    synopsis = "%prog <groupname> [options]"
>> +
>> +    takes_optiongroups = {
>> +        "sambaopts": options.SambaOptions,
>> +        "credopts": options.CredentialsOptions,
>> +        "versionopts": options.VersionOptions,
>> +    }
>> +
>> +    takes_options = [
>> +        Option("-H", "--URL", help="LDB URL for database or target server",
>> +               type=str, metavar="URL", dest="H"),
>> +        Option("--gid-number", help="Group's Unix/RFC2307 GID number", type=int),
>> +        Option("--nis-domain", help="Group's Unix/RFC2307 NIS domain",
>> +               type=str),
>> +    ]
>> +
>> +    takes_args = ["groupname"]
>> +
>> +
>> +    def run(self, groupname, credopts=None, sambaopts=None, versionopts=None,
>> +            H=None, nis_domain=None, gid_number=None):
>> +
>> +        lp = sambaopts.get_loadparm()
>> +        creds = credopts.get_credentials(lp)
>> +
>> +        samdb = SamDB(url=H, session_info=system_session(),
>> +                      credentials=creds, lp=lp)
>> +
>> +        if (gid_number is None and nis_domain is not None) or \
>> +           (gid_number is not None and nis_domain is None):
>> +            raise CommandError('Both --gid-number and --nis-domain'
>> +                               ' have to be set for a RFC2307-enabled group.'
>> +                               'Operation cancelled.')
>> +
>> +        domain_dn = samdb.domain_dn()
>> +        search_filter = "(samaccountname=%s)" % groupname
>> +        group_dn = samdb.get_object_dn(search_filter)
>> +
>> +        # what if group already is a NIS group??
>> +        res = samdb.search(group_dn,
>> +                           scope=ldb.SCOPE_BASE,
>> +                           attrs=["gidNumber"])
>> +        if "gidNumber" in res[0]:
>> +            raise CommandError("Group %s already is a NIS group." % groupname)
>> +
>> +        if not lp.get("idmap_ldb:use rfc2307"):
>> +            self.outf.write("You are setting a Unix/RFC2307 GID. \
>> +You may want to set 'idmap_ldb:use rfc2307 = Yes' in smb.conf to \
>> +use this attribute for XID/SID-mapping.\n")
>> +
>> +        update_group = """
>> +dn: %s
>> +changetype: modify
>> +add: msSFU30NisDomain
>> +msSFU30NisDomain: %s
>> +-
>> +add: msSFU30Name
>> +msSFU30Name: %s
>> +-
>> +add: gidNumber
>> +gidNumber: %s
>> +-
>> +""" % (group_dn, nis_domain, groupname,  gid_number)
>> +
>> +        try:
>> +            samdb.modify_ldif(update_group)
>> +        except Exception, e:
>> +            raise CommandError("Failed to update group '%s': " % groupname, e)
>> +
>> +        self.outf.write("Group '%s' updated successfully\n" % groupname)
>> +
>> +
>>   class cmd_group(SuperCommand):
>>       """Group management."""
>>   
>> @@ -418,3 +511,4 @@ class cmd_group(SuperCommand):
>>       subcommands["removemembers"] = cmd_group_remove_members()
>>       subcommands["list"] = cmd_group_list()
>>       subcommands["listmembers"] = cmd_group_list_members()
>> +    subcommands["nisadd"] = cmd_group_nis_add()
>> -- 
>> 1.7.10.4
>>
>>  From 96abc002deae41f9499e1d3f41cd3b576015876d Mon Sep 17 00:00:00 2001
>> From: Rowland Penny <repenny241155 at gmail.com>
>> Date: Mon, 16 Nov 2015 16:07:31 +0000
>> Subject: [PATCH 4/5] Subject: [PATCH 4/4] samba-tool manpage: Add user &
>>   group 'nisadd' lines
>>
>> Signed-off-by: Rowland Penny <repenny241155 at gmail.com>
>> ---
>>   docs-xml/manpages/samba-tool.8.xml |   12 ++++++++++++
>>   1 file changed, 12 insertions(+)
>>
>> diff --git a/docs-xml/manpages/samba-tool.8.xml b/docs-xml/manpages/samba-tool.8.xml
>> index a575a20..486aacb 100644
>> --- a/docs-xml/manpages/samba-tool.8.xml
>> +++ b/docs-xml/manpages/samba-tool.8.xml
>> @@ -445,6 +445,12 @@
>>   </refsect3>
>>   
>>   <refsect3>
>> +	<title>group nisadd</title>
>> +	<para>Add RFC2307 attributes to a group, similar to using the ADUC
>> +UNIX Attributes tab.</para>
>> +</refsect3>
>> +
>> +<refsect3>
>>   	<title>group removemembers <replaceable>groupname</replaceable> <replaceable>members</replaceable> [options]</title>
>>   	<para>Remove members from the specified AD group.</para>
>>   </refsect3>
>> @@ -572,6 +578,12 @@
>>   </refsect3>
>>   
>>   <refsect3>
>> +	<title>user nisadd</title>
>> +	<para>Add RFC2307 attributes to a user, similar to using the ADUC
>> +UNIX Attributes tab.</para>
>> +</refsect3>
>> +
>> +<refsect3>
>>   	<title>user password [options]</title>
>>   	<para>Change password for an user account (the one provided in
>>   	authentication).</para>
>> -- 
>> 1.7.10.4
>>




More information about the samba-technical mailing list