[lxc-devel] [PATCH v2 3/3] Improve setting the default password in a new container

Michael H. Warfield mhw at WittsEnd.com
Thu Oct 30 16:07:05 UTC 2014


On Wed, 2014-10-29 at 19:29 +0900, TAMUKI Shoichi wrote:
> Hello,
> 
> From: "Michael H. Warfield" <mhw at WittsEnd.com>
> Subject: Re: [lxc-devel] [PATCH v2 3/3] Improve setting the default password in a new container
> Date: Sat, 11 Oct 2014 13:24:10 -0400
> 
> > > > > The default password in a new container is now auto-generated using
> > > > > phoneme rules and (good) random numbers.
> > > > > 
> > > > > Even if the default random password is set in a distribution-specific
> > > > > template and you use the download template to pull a pre-built rootfs
> > > > > image, you will get the same password every time unless the pre-built
> > > > > rootfs image is updated.
> > > > > 
> > > > > So, the default random password in a new container is to be set after
> > > > > container creation.  The user names whose passwords to be changed are
> > > > > stored in *.chpasswd file which is located at /usr/share/lxc/config.
> > > > > Each line of the file specifies a user name whose password is to be
> > > > > changed.  If the target *.chpasswd file does not exist, no password is
> > > > > changed in a new container.
> > > > 
> > > > This is obviously a festering problem and one that has already been
> > > > addressed in the Fedora and CentOS templates in a different manner and
> > > > additional patches have been submitted and under discussion.  Did you
> > > > even bother to read the code in the Fedora and CentOS templates?
> > > 
> > > At first, I intended to use the code in the Fedora/CentOS templates,
> > > but I became aware that the method was available only when using the
> > > template with '-t' option to lxc-create.  It can not be used by non-
> > > priv users.
> > 
> > That would then be handled by the download template and, iirc, it was
> > Stephane's intention to have those containers start with "locked"
> > accounts and require lxc-attach or something similar to set up.
> 
> I spent time to look into the Fedora template about the password
> treatment.  In summary, the Fedora template works as following specs:
> 
> ----------------------------------------------------------------------
> root_password=[password]
> If the "root_password" is non-blank, use it, else set a default.
> This can be passed to the script as an environment variable and is
> set by a shell conditional assignment.  Looks weird but it is what it is.
> 
> If the root password contains a ding ($) then try to expand it.
> That will pick up things like ${name} and ${RANDOM}.
> If the root password contains more than 3 consecutive X's, pass it as
> a template to mktemp and take the result.
> 
> These are conditional assignments.  They can be overridden from the
> pre-existing environment variables.
> 
> root_display_password=[yes|no]
> If root_display_password=yes, display the temporary root password at
> exit.  Default to no.
> 
> root_store_password=[yes|no]
> If root_store_password=yes, store it in the configuration directory.
> Default to yes.
> 
> root_prompt_password=[yes|no]
> If root_prompt_password=yes, invoke "passwd" to force the user to change
> the root password after the container is created.  Default to no.
> 
> root_expire_password=[yes|no]
> If root_expire_password=yes, you will be prompted to change the root
> password at the first login.  Default to yes.
> ----------------------------------------------------------------------

> Currently, it seems not to take multi-user accounts into account, and
> it does not support with locked accounts.  So, I tried rewriting the
> code:

Yeah, that was addressed in a patch that I sent in over a month ago that
raised some tangential questions with Stéphane.  The intent was to split
that off into a more generalized functions file that had code to address
those issues.  I have reworked a lot of that and haven't resubmitted it
yet.

Could you look at the patch posted to the list on 09/14..

Subject: [PATCH] Various fixes for Fedora/CentOS/OpenSUSE templates and
systemd.

Look at the code in the new "functions" file and the revisions to the
CentOS and Fedora templates to utilize it (ignore the mac address code
generation that was one of the things Stéphane was objecting too as
redundant).  That code is going to be largely unchanged although I would
welcome any input from you on it.

> ----------------------------------------------------------------------
> #!/bin/bash
> 	:
> 	:
> 	:
> # Some combinations of the tuning knobs below do not exactly make sense.
> # but that's ok.
> #
> # If the "LXC_PASSWORD" is non-blank, use it, else set a default.
> # This can be passed to the script as an environment variable and is
> # set by a shell conditional assignment.  Looks weird but it is what it is.
> #
> # If the password is "PROMPT", invoke "passwd" to force the user to
> # change the password after the container is created.
> # Prompting for something interactive has potential for mayhem with
> # users running under the API...  Don't default to "PROMPT".
> # If the password contains one of 3 common "disabled" conventions, or
> # a hash indicator for a real password hash, assume in encrypted form.
> # If the password contains a ding ($) then try to expand it.
> # That will pick up things like ${name} and ${RANDOM}.
> # If the password contains more than 3 consecutive X's, pass it as
> # a template to mktemp and take the result.
> #
> # If LXC_DISPLAY_PASSWORD = yes, display the temporary password at exit.
> # If LXC_STORE_PASSWORD = yes, store it in the configuration directory
> # If LXC_EXPIRE_PASSWORD = yes, you will be prompted to change the
> # password at the first login.
> #
> # These are conditional assignments...  They can be overridden from the
> # pre-existing environment variables...
> #
> # Make sure this is in single quotes to defer expansion to later!
> #: ${LXC_PASSWORD='${uname[$i]^}-$name-$RANDOM'}
> : ${LXC_PASSWORD='${uname[$i]^}-$name-XXXXXX'}
> # Now, it doesn't make much sense to display, store, and force change
> # together.  But, we gotta test, right???
> : ${LXC_DISPLAY_PASSWORD=no}
> : ${LXC_STORE_PASSWORD=yes}
> # Expire password?  Default to yes, but can be overridden from
> # the environment variable
> : ${LXC_EXPIRE_PASSWORD=yes}
> 	:
> 	:
> 	:
> configure_foo() {
> 	:
> 	:
> 	:
>   # Let's do something better for the initial password.
>   # It's not perfect but it will defeat common scanning brute force
>   # attacks in the case where ssh is exposed.  It may also be set to
>   # expired, forcing the user to change it at first login.
>   for i in `seq 0 $((${#uname[@]} - 1))` ; do
>     if [ "${passwd[$i]}" == "PROMPT" ] ; then
>       cat <<- EOF | unexpand
> 	Invoking the passwd command in the container to set the ${uname[$i]} password...
> 	
> 	        chroot $rootfs passwd ${uname[$i]}
> 	
> 	EOF
>       chroot $rootfs passwd ${uname[$i]}
>     elif [ -n "$(expr "${passwd[$i]}" : '\(\!\{1,2\}\|\$\|*\)$')" ] ; then
>       # Matches one of 3 common "disabled" conventions so treat them
>       # as if they were "hashed" passwords to be copied literally
>       # by chpasswd.  Result is an account with no valid password.
>       echo "Disabling ${uname[$i]} password..."
>       echo "${uname[$i]}:${passwd[$i]}" | chroot $rootfs chpasswd -e
>     elif [ -n "$(expr "${passwd[$i]}" : '$\([1256]\|2a\)\$')" ] ; then
>       # Matches on a hash indicator for a real password hash.
>       echo -n "Setting ${uname[$i]} password hash to "
>       [ "$LXC_DISPLAY_PASSWORD" == "yes" ] \
>           && echo "'${passwd[$i]}'..." || echo "'********'..."
>       echo "${uname[$i]}:${passwd[$i]}" | chroot $rootfs chpasswd -e
>     else
>       # Anything else, assume a clear text password template...
>       echo -n "Setting ${uname[$i]} password to "
>       [ "$LXC_DISPLAY_PASSWORD" == "yes" ] \
>           && echo "'${passwd[$i]}'..." || echo "'********'..."
>       echo "${uname[$i]}:${passwd[$i]}" | chroot $rootfs chpasswd
>       [ "$LXC_DISPLAY_PASSWORD" == "yes" ] || continue
>       cat <<- EOF
> 	The temporary password for ${uname[$i]} is: '${passwd[$i]}'
> 	
> 	You may want to note that password down before starting the container.
> 	
> 	EOF
>     fi
>   done
>   if [ "$LXC_EXPIRE_PASSWORD" == "yes" ] ; then
>     # Also set this password as expired to force the user to change it!
>     for i in `seq 0 $((${#uname[@]} - 1))` ; do
>       chroot $rootfs passwd -e ${uname[$i]}
>     done
>     cat <<- "EOF"
> 	The password is set up as "expired" and will require it to be changed
> 	at first login, which you should do as soon as possible.  If you lose the
> 	password or wish to change it without starting the container, you
> 	can change it from the host by running the following command (which will
> 	also reset the expired flag):
> 	
> 	EOF
>     for i in `seq 0 $((${#uname[@]} - 1))` ; do
>       echo $'\t'"chroot $rootfs passwd ${uname[$i]}"
>     done
>     echo
>   fi
> 	:
> 	:
> 	:
> }
> 
> copy_configuration() {
> 	:
> 	:
> 	:
>   for i in `seq 0 $((${#uname[@]} - 1))` ; do
>     echo "${uname[$i]}" >> $path/chpasswd
>   done
>   if [ "$LXC_STORE_PASSWORD" == "yes" ] ; then
>     touch $path/tmp_pass
>     chmod 600 $path/tmp_pass
>     # Append the user and password to the file.
>     # We might be ultimately adding more than one.
>     for i in `seq 0 $((${#uname[@]} - 1))` ; do
>       echo "Storing $(uname[$i]} password in '$path/tmp_pass'..."
>       echo "${uname[$i]}:${passwd[i]}" >> $path/tmp_pass
>     done
>     cat <<- EOF | unexpand
> 	The temporary password is stored in:
> 	
> 	        '$path/tmp_pass'
> 	
> 	EOF
>   fi
> 	:
> 	:
> 	:
> }
> 	:
> 	:
> 	:
> uname=root
> #uname=(root alice bob $user)
> for i in `seq 0 $((${#uname[@]} - 1))` ; do
>   if [ -z "$LXC_PASSWORD" ] ; then
>     passwd[$i]=${uname[$i]^}-$name-$RANDOM
>   else
>     if [ -n "$(expr "$LXC_PASSWORD" : '\(\!\{1,2\}\|\$\|*\)$')"
>         -o -n "$(expr "$LXC_PASSWORD" : '$\([1256]\|2a\)\$')" ] ; then
>       # If the password contains one of 3 common "disabled" conven-
>       # tions, or a hash indicator for a real password hash, leave it
>       # unchanged.
>       passwd[$i]="$LXC_PASSWORD"
>     else
>       # In case it's got a ding in it, try and expand it!
>       # In theory, this could also access and external program.
>       passwd[$i]=`eval echo "$LXC_PASSWORD"`
>     fi
>     # If it has more than 3 consequtive X's in it, feed it
>     # through mktemp as a template.
>     if [ `expr "${passwd[$i]}" : '.*XXX$'` -ne 0 ] ; then
>       passwd[$i]=`mktemp -u ${passwd[$i]}`
>     fi
>   fi
> done
> 	:
> 	:
> 	:
> ----------------------------------------------------------------------
> 
> However, when using download template, the accounts should be locked
> eventually.  Also, I think the password treatment should have the same
> behavior between using the template with '-t' option to lxc-create and
> using download template.  So, I think that creating passwords should
> be done after the template runs.  That means, most of the processing
> about creating passwords in the template will be moved to the point
> after the template runs in lxc-create command:
> 
> ----------------------------------------------------------------------
> #!/bin/bash
> 	:
> 	:
> 	:
> configure_foo() {
> 	:
> 	:
> 	:
>   # set password
>   for i in `seq 0 $((${#uname[@]} - 1))` ; do
>     echo "Setting ${uname[$i]} password to '${uname[$i]}'..."
>     echo "${uname[$i]}:${uname[$i]}" | chroot $rootfs chpasswd
>     echo "Disabling ${uname[$i]} password..."
>     chroot $rootfs passwd -l ${uname[$i]}
>   done
> 	:
> 	:
> 	:
> }
> 
> copy_configuration() {
> 	:
> 	:
> 	:
>   for i in `seq 0 $((${#uname[@]} - 1))` ; do
>     echo "${uname[$i]}" >> $path/chpasswd
>   done
> 	:
> 	:
> 	:
> }
> 	:
> 	:
> 	:
> uname=root
> #uname=(root alice bob $user)
> 	:
> 	:
> 	:
> ----------------------------------------------------------------------
> 
> Regards,
> TAMUKI Shoichi
> _______________________________________________
> lxc-devel mailing list
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel
> 

-- 
Michael H. Warfield (AI4NB) | (770) 978-7061 |  mhw at WittsEnd.com
   /\/\|=mhw=|\/\/          | (678) 463-0932 |  http://www.wittsend.com/mhw/
   NIC whois: MHW9          | An optimist believes we live in the best of all
 PGP Key: 0x674627FF        | possible worlds.  A pessimist is sure of it!

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 465 bytes
Desc: This is a digitally signed message part
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20141030/bf1dd554/attachment.sig>


More information about the lxc-devel mailing list