> On May 9, 2016, at 5:55 PM, Stephano Cetola <[email protected]> 
> wrote:
> 
> On 05/09, Khem Raj wrote:
>> 
>>> On May 9, 2016, at 4:42 PM, Stephano Cetola 
>>> <[email protected]> wrote:
>>> 
>>> This fix ensures that systemd users are created at build and that any
>>> staticids for the users or groups are preserved. This functionality only
>>> existed for readonly filesystems, however it seems wise to be sure these
>>> users are added rather than relying on systemd to create them.
>> 
>> We need to cover the case where online package management is used. If you 
>> were to fix
>> it in systemd recipe itself which takes care of creating these users in post 
>> installs
>> that will fix it for this case too.
> I'm not sure I follow you. I can see how this could be done in a post
> install script, but I'm missing how this would help online package
> management. Could you please point me in the right direction?

Lets say, I did not install microhttpserver in default image. But later on I 
decided to install it via
O_P_M feeds. or remove for that matter.

>> 
>>> 
>>> [ YOCTO #9497 ]
>>> 
>>> Signed-off-by: Stephano Cetola <[email protected]>
>>> ---
>>> meta/classes/rootfs-postcommands.bbclass | 66 
>>> +++++++++++++++++++++-----------
>>> meta/classes/useradd-staticids.bbclass   | 56 +--------------------------
>>> useradd-staticids-list.bbclass           | 56 +++++++++++++++++++++++++++
>>> 3 files changed, 100 insertions(+), 78 deletions(-)
>>> create mode 100644 useradd-staticids-list.bbclass
>>> 
>>> diff --git a/meta/classes/rootfs-postcommands.bbclass 
>>> b/meta/classes/rootfs-postcommands.bbclass
>>> index 95d28af..db4cc75 100644
>>> --- a/meta/classes/rootfs-postcommands.bbclass
>>> +++ b/meta/classes/rootfs-postcommands.bbclass
>>> @@ -1,4 +1,4 @@
>>> -
>>> +inherit useradd-staticids-list
>>> # Zap the root password if debug-tweaks feature is not enabled
>>> ROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains_any("IMAGE_FEATURES", [ 
>>> 'debug-tweaks', 'empty-root-password' ], "", "zap_empty_root_password ; 
>>> ",d)}'
>>> 
>>> @@ -23,6 +23,9 @@ POSTINST_LOGFILE ?= "${localstatedir}/log/postinstall.log"
>>> SYSTEMD_DEFAULT_TARGET ?= '${@bb.utils.contains("IMAGE_FEATURES", 
>>> "x11-base", "graphical.target", "multi-user.target", d)}'
>>> ROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains("DISTRO_FEATURES", 
>>> "systemd", "set_systemd_default_target; ", "", d)}'
>>> 
>>> +# Create systemd users at build rather than at runtime
>>> +ROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains("DISTRO_FEATURES", 
>>> "systemd", "create_systemd_sysusers; ", "", d)}'
>>> +
>>> ROOTFS_POSTPROCESS_COMMAND += 'empty_var_volatile;'
>>> 
>>> # Disable DNS lookups, the SSH_DISABLE_DNS_LOOKUP can be overridden to allow
>>> @@ -30,7 +33,45 @@ ROOTFS_POSTPROCESS_COMMAND += 'empty_var_volatile;'
>>> SSH_DISABLE_DNS_LOOKUP ?= " ssh_disable_dns_lookup ; "
>>> ROOTFS_POSTPROCESS_COMMAND_append_qemuall = "${SSH_DISABLE_DNS_LOOKUP}"
>>> 
>>> -
>>> +# Add systemd users checking for any staticids
>>> +python create_systemd_sysusers () {
>>> +    import shlex
>>> +    import subprocess
>>> +    s_users = merge_files(get_passwd_list(d), 7)
>>> +    s_groups = merge_files(get_group_list(d), 4)
>>> +    confs = ['%s/usr/lib/sysusers.d/systemd.conf' % 
>>> d.getVar('IMAGE_ROOTFS', d), '%s/usr/lib/sysusers.d/systemd-remote.conf' % 
>>> d.getVar('IMAGE_ROOTFS', d)]
>>> +    for conf in confs:
>>> +        if os.path.isfile(conf):
>>> +            with open(conf, 'r') as f:
>>> +                for line in f:
>>> +                    if line.startswith('#'):
>>> +                        continue
>>> +                    fields = shlex.split(line.rstrip())
>>> +                    if not fields:
>>> +                        continue
>>> +                    if fields[0] == 'u':
>>> +                        useradd_params = ''
>>> +                        if fields[1] in s_users:
>>> +                            useradd_params += '--uid %s' % 
>>> s_users[fields[1]][2]
>>> +                            bb.warn("Changing user %s's uid to (%s), 
>>> verify configuration files!" % (fields[1], s_users[fields[1]][2]))
>>> +                        elif fields[2] != '-':
>>> +                            useradd_params += '--uid %s' % fields[2]
>>> +                        if fields[3] != '-':
>>> +                            useradd_params += ' --comment "%s"' % fields[3]
>>> +                        useradd_params += ' --root "%s" --shell 
>>> /sbin/nologin  --system %s' % (d.getVar("IMAGE_ROOTFS", d), fields[1])
>>> +                        code = subprocess.call('useradd %s' % 
>>> useradd_params, shell=True)
>>> +                    elif fields[0] == 'g':
>>> +                        groupadd_params = ""
>>> +                        if fields[1] in s_groups:
>>> +                            groupadd_params += '--gid %s' % 
>>> s_groups[fields[1]][2]
>>> +                            bb.warn("Changing group %s's gid to (%s), 
>>> verify configuration files!" % (fields[1], s_groups[fields[1]][2]))
>>> +                        elif fields[2] != '-':
>>> +                            groupadd_params += '--gid %s' % fields[2]
>>> +                        if fields[3] != '-':
>>> +                            groupadd_params += ' --comment "%s"' % 
>>> (d.getVar("IMAGE_ROOTFS", d), fields[3])
>>> +                        groupadd_params += ' --root "%s" --system %s' % 
>>> (d.getVar("IMAGE_ROOTFS", d), fields[1])
>>> +                        code = subprocess.call('groupadd %s' % 
>>> groupadd_params, shell=True)
>>> +}
>>> 
>>> #
>>> # A hook function to support read-only-rootfs IMAGE_FEATURES
>>> @@ -73,27 +114,6 @@ read_only_rootfs_hook () {
>>>                     ${IMAGE_ROOTFS}/etc/init.d/populate-volatile.sh
>>>             fi
>>>     fi
>>> -
>>> -   if ${@bb.utils.contains("DISTRO_FEATURES", "systemd", "true", "false", 
>>> d)}; then
>>> -       # Update user database files so that services don't fail for a 
>>> read-only systemd system
>>> -       for conffile in ${IMAGE_ROOTFS}/usr/lib/sysusers.d/systemd.conf 
>>> ${IMAGE_ROOTFS}/usr/lib/sysusers.d/systemd-remote.conf; do
>>> -           [ -e $conffile ] || continue
>>> -           grep -v "^#" $conffile | sed -e '/^$/d' | while read type name 
>>> id comment; do
>>> -               if [ "$type" = "u" ]; then
>>> -                   useradd_params=""
>>> -                   [ "$id" != "-" ] && useradd_params="$useradd_params 
>>> --uid $id"
>>> -                   [ "$comment" != "-" ] && 
>>> useradd_params="$useradd_params --comment $comment"
>>> -                   useradd_params="$useradd_params --system $name"
>>> -                   eval useradd --root ${IMAGE_ROOTFS} $useradd_params || 
>>> true
>>> -               elif [ "$type" = "g" ]; then
>>> -                   groupadd_params=""
>>> -                   [ "$id" != "-" ] && groupadd_params="$groupadd_params 
>>> --gid $id"
>>> -                   groupadd_params="$groupadd_params --system $name"
>>> -                   eval groupadd --root ${IMAGE_ROOTFS} $groupadd_params 
>>> || true
>>> -               fi
>>> -           done
>>> -       done
>>> -   fi
>>> }
>>> 
>>> #
>>> diff --git a/meta/classes/useradd-staticids.bbclass 
>>> b/meta/classes/useradd-staticids.bbclass
>>> index a9b506d..e9dfe69 100644
>>> --- a/meta/classes/useradd-staticids.bbclass
>>> +++ b/meta/classes/useradd-staticids.bbclass
>>> @@ -1,3 +1,4 @@
>>> +inherit useradd-staticids-list
>>> # In order to support a deterministic set of 'dynamic' users/groups,
>>> # we need a function to reformat the params based on a static file
>>> def update_useradd_static_config(d):
>>> @@ -17,35 +18,6 @@ def update_useradd_static_config(d):
>>>        def error(self, message):
>>>            raise bb.build.FuncFailed(message)
>>> 
>>> -    def list_extend(iterable, length, obj = None):
>>> -        """Ensure that iterable is the specified length by extending with 
>>> obj
>>> -        and return it as a list"""
>>> -        return list(itertools.islice(itertools.chain(iterable, 
>>> itertools.repeat(obj)), length))
>>> -
>>> -    def merge_files(file_list, exp_fields):
>>> -        """Read each passwd/group file in file_list, split each line and 
>>> create
>>> -        a dictionary with the user/group names as keys and the split lines 
>>> as
>>> -        values. If the user/group name already exists in the dictionary, 
>>> then
>>> -        update any fields in the list with the values from the new list 
>>> (if they
>>> -        are set)."""
>>> -        id_table = dict()
>>> -        for conf in file_list.split():
>>> -            if os.path.exists(conf):
>>> -                f = open(conf, "r")
>>> -                for line in f:
>>> -                    if line.startswith('#'):
>>> -                        continue
>>> -                    # Make sure there always are at least exp_fields 
>>> elements in
>>> -                    # the field list. This allows for leaving out trailing
>>> -                    # colons in the files.
>>> -                    fields = list_extend(line.rstrip().split(":"), 
>>> exp_fields)
>>> -                    if fields[0] not in id_table:
>>> -                        id_table[fields[0]] = fields
>>> -                    else:
>>> -                        id_table[fields[0]] = list(itertools.imap(lambda 
>>> x, y: x or y, fields, id_table[fields[0]]))
>>> -
>>> -        return id_table
>>> -
>>>    # We parse and rewrite the useradd components
>>>    def rewrite_useradd(params):
>>>        # The following comes from --help on useradd from shadow
>>> @@ -73,19 +45,6 @@ def update_useradd_static_config(d):
>>>        parser.add_argument("-U", "--user-group", help="create a group with 
>>> the same name as the user", action="store_const", const=True)
>>>        parser.add_argument("LOGIN", help="Login name of the new user")
>>> 
>>> -        # Return a list of configuration files based on either the default
>>> -        # files/passwd or the contents of USERADD_UID_TABLES
>>> -        # paths are resolved via BBPATH
>>> -        def get_passwd_list(d):
>>> -            str = ""
>>> -            bbpath = d.getVar('BBPATH', True)
>>> -            passwd_tables = d.getVar('USERADD_UID_TABLES', True)
>>> -            if not passwd_tables:
>>> -                passwd_tables = 'files/passwd'
>>> -            for conf_file in passwd_tables.split():
>>> -                str += " %s" % bb.utils.which(bbpath, conf_file)
>>> -            return str
>>> -
>>>        newparams = []
>>>        users = None
>>>        for param in re.split('''[ \t]*;[ 
>>> \t]*(?=(?:[^'"]|'[^']*'|"[^"]*")*$)''', params):
>>> @@ -206,19 +165,6 @@ def update_useradd_static_config(d):
>>>        parser.add_argument("-r", "--system", help="create a system 
>>> account", action="store_true")
>>>        parser.add_argument("GROUP", help="Group name of the new group")
>>> 
>>> -        # Return a list of configuration files based on either the default
>>> -        # files/group or the contents of USERADD_GID_TABLES
>>> -        # paths are resolved via BBPATH
>>> -        def get_group_list(d):
>>> -            str = ""
>>> -            bbpath = d.getVar('BBPATH', True)
>>> -            group_tables = d.getVar('USERADD_GID_TABLES', True)
>>> -            if not group_tables:
>>> -                group_tables = 'files/group'
>>> -            for conf_file in group_tables.split():
>>> -                str += " %s" % bb.utils.which(bbpath, conf_file)
>>> -            return str
>>> -
>>>        newparams = []
>>>        groups = None
>>>        for param in re.split('''[ \t]*;[ 
>>> \t]*(?=(?:[^'"]|'[^']*'|"[^"]*")*$)''', params):
>>> diff --git a/useradd-staticids-list.bbclass b/useradd-staticids-list.bbclass
>>> new file mode 100644
>>> index 0000000..377f748
>>> --- /dev/null
>>> +++ b/useradd-staticids-list.bbclass
>>> @@ -0,0 +1,56 @@
>>> +# Return a list of configuration files based on either the default
>>> +# files/group or the contents of USERADD_GID_TABLES
>>> +# paths are resolved via BBPATH
>>> +def get_group_list(d):
>>> +    str = ""
>>> +    bbpath = d.getVar('BBPATH', True)
>>> +    group_tables = d.getVar('USERADD_GID_TABLES', True)
>>> +    if not group_tables:
>>> +        group_tables = 'files/group'
>>> +    for conf_file in group_tables.split():
>>> +        str += " %s" % bb.utils.which(bbpath, conf_file)
>>> +    return str
>>> +
>>> +def list_extend(iterable, length, obj = None):
>>> +    import itertools
>>> +    """Ensure that iterable is the specified length by extending with obj
>>> +    and return it as a list"""
>>> +    return list(itertools.islice(itertools.chain(iterable, 
>>> itertools.repeat(obj)), length))
>>> +
>>> +def merge_files(file_list, exp_fields):
>>> +    import itertools
>>> +    """Read each passwd/group file in file_list, split each line and create
>>> +    a dictionary with the user/group names as keys and the split lines as
>>> +    values. If the user/group name already exists in the dictionary, then
>>> +    update any fields in the list with the values from the new list (if 
>>> they
>>> +    are set)."""
>>> +    id_table = dict()
>>> +    for conf in file_list.split():
>>> +        if os.path.exists(conf):
>>> +            f = open(conf, "r")
>>> +            for line in f:
>>> +                if line.startswith('#'):
>>> +                    continue
>>> +                # Make sure there always are at least exp_fields elements 
>>> in
>>> +                # the field list. This allows for leaving out trailing
>>> +                # colons in the files.
>>> +                fields = list_extend(line.rstrip().split(":"), exp_fields)
>>> +                if fields[0] not in id_table:
>>> +                    id_table[fields[0]] = fields
>>> +                else:
>>> +                    id_table[fields[0]] = list(itertools.imap(lambda x, y: 
>>> x or y, fields, id_table[fields[0]]))
>>> +
>>> +    return id_table
>>> +
>>> +# Return a list of configuration files based on either the default
>>> +# files/passwd or the contents of USERADD_UID_TABLES
>>> +# paths are resolved via BBPATH
>>> +def get_passwd_list(d):
>>> +    str = ""
>>> +    bbpath = d.getVar('BBPATH', True)
>>> +    passwd_tables = d.getVar('USERADD_UID_TABLES', True)
>>> +    if not passwd_tables:
>>> +        passwd_tables = 'files/passwd'
>>> +    for conf_file in passwd_tables.split():
>>> +        str += " %s" % bb.utils.which(bbpath, conf_file)
>>> +    return str
>>> --
>>> 2.8.0
>>> 
>>> --
>>> _______________________________________________
>>> Openembedded-core mailing list
>>> [email protected]
>>> http://lists.openembedded.org/mailman/listinfo/openembedded-core
>> 
> 
> 

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

-- 
_______________________________________________
Openembedded-core mailing list
[email protected]
http://lists.openembedded.org/mailman/listinfo/openembedded-core

Reply via email to