Hi Michael, On Thu, Dec 26, 2013 at 6:08 PM, Michael H. Warfield <m...@wittsend.com> wrote: > CentOS and Fedora Templates: Harden root passwords and add static MAC network > addresses. > > 1) Add logic to root password setting. Root password is now set to > "Root-${name}-${RANDOM} to defeat common brute force scans. > 2) Enhance exit messages to explain root password and password changing.
Not an objection but a question. What about creating the container using either quiet parameter or via API? In that case user is unlikely to see that output hence won't be able to login the box. > 3) Add random generated hwaddr (MAC) entires for any network interfaces > in default config copied to container. > 4) Add shell variable expansion of default config. > 5) Cross patch templates to bring them more into coherence with each other. > > Signed-off-by: Michael H. Warfield <m...@wittsend.com> > --- > templates/lxc-centos.in | 114 > +++++++++++++++++++++++++++++++++++++----------- > templates/lxc-fedora.in | 99 +++++++++++++++++++++++++++++++++++++---- > 2 files changed, 180 insertions(+), 33 deletions(-) > > diff --git a/templates/lxc-centos.in b/templates/lxc-centos.in > index 7d47715..5bb5349 100644 > --- a/templates/lxc-centos.in > +++ b/templates/lxc-centos.in > @@ -33,6 +33,7 @@ default_path=@LXCPATH@ > # We really need something better here! > root_password=root > > +# These are only going into comments in the resulting config... > lxc_network_type=veth > lxc_network_link=lxcbr0 > > @@ -256,8 +257,10 @@ EOF > mknod -m 600 ${dev_path}/initctl p > mknod -m 666 ${dev_path}/ptmx c 5 2 > > - echo "setting root passwd to $root_password" > + echo "Setting root passwd to '$root_password'" > echo "root:$root_password" | chroot $rootfs_path chpasswd > + # Also set this password as expired to force the user to change it! > + chroot $rootfs_path passwd -e root > > # This will need to be enhanced for CentOS 7 when systemd > # comes into play... /\/\|=mhw=|\/\/ > @@ -374,6 +377,7 @@ copy_centos() > # i prefer rsync (no reason really) > mkdir -p $rootfs_path > rsync -a $cache/rootfs/ $rootfs_path/ > + echo > return 0 > } > > @@ -428,28 +432,71 @@ install_centos() > return $? > } > > -copy_configuration() > +create_hwaddr() > { > + echo $(dd if=/dev/urandom bs=8 count=1 2>/dev/null | md5sum > + | sed -e 's/\(..\)\(..\)\(..\)\(..\)\(..\).*/fe:\1:\2:\3:\4:\5/') > +} > > +copy_configuration() > +{ > mkdir -p $config_path > + > + grep -q "^lxc.rootfs" $config_path/config 2>/dev/null || echo " > +lxc.rootfs = $rootfs_path > +" >> $config_path/config > + > + # The following code is to create static MAC addresses for each > + # interface in the container. This code will work for multiple > + # interfaces in the default config. > + mv $config_path/config $config_path/config.def > + while read LINE > + do > + # This should catch variable expansions from the default config... > + if expr "${LINE}" : '.*\$' > /dev/null 2>&1 > + then > + LINE=$(eval "echo \"${LINE}\"") > + fi > + > + # There is a tab and a space in the regex bracket below! > + # Seems that \s doesn't work in brackets. > + KEY=$(expr $LINE : '\s*\([^ ]*\)\s*=') > + > + if [[ "${KEY}" != "lxc.network.hwaddr" ]] > + then > + echo ${LINE} >> $config_path/config > + > + if [[ "${KEY}" == "lxc.network.link" ]] > + then > + echo "lxc.network.hwaddr = $(create_hwaddr)" >> > $config_path/config > + fi > + fi > + done < $config_path/config.def > + > + rm -f $config_path/config.def > + > cat <<EOF >> $config_path/config > lxc.utsname = $utsname > lxc.tty = 4 > lxc.pts = 1024 > -lxc.rootfs = $rootfs_path > -lxc.mount = $config_path/fstab > +lxc.mount = $config_path/fstab > lxc.cap.drop = sys_module mac_admin mac_override sys_time > > lxc.autodev = $auto_dev > > +# When using LXC with apparmor, uncomment the next line to run unconfined: > +#lxc.aa_profile = unconfined > + > # example simple networking setup, uncomment to enable > #lxc.network.type = $lxc_network_type > #lxc.network.flags = up > #lxc.network.link = $lxc_network_link > #lxc.network.name = eth0 > -# additional example for veth network type, static MAC address, > -# and persistent veth device name on host side > +# Additional example for veth network type > +# static MAC address, > #lxc.network.hwaddr = 00:16:3e:77:52:20 > +# persistent veth device name on host side > +# Note: This may potentially collide with other containers of same > name! > #lxc.network.veth.pair = v-$name-e0 > > #cgroups > @@ -460,8 +507,6 @@ lxc.cgroup.devices.allow = c 1:5 rwm > # consoles > lxc.cgroup.devices.allow = c 5:1 rwm > lxc.cgroup.devices.allow = c 5:0 rwm > -lxc.cgroup.devices.allow = c 4:0 rwm > -lxc.cgroup.devices.allow = c 4:1 rwm > # /dev/{,u}random > lxc.cgroup.devices.allow = c 1:9 rwm > lxc.cgroup.devices.allow = c 1:8 rwm > @@ -473,13 +518,12 @@ EOF > > cat <<EOF > $config_path/fstab > proc proc proc nodev,noexec,nosuid 0 0 > -devpts dev/pts devpts defaults 0 0 > sysfs sys sysfs defaults 0 0 > EOF > > if [ $? -ne 0 ]; then > - echo "Failed to add configuration" > - return 1 > + echo "Failed to add configuration" > + return 1 > fi > > return 0 > @@ -489,22 +533,21 @@ clean() > { > > if [ ! -e $cache ]; then > - exit 0 > + exit 0 > fi > > # lock, so we won't purge while someone is creating a repository > ( > - flock -x 200 > - if [ $? != 0 ]; then > - echo "Cache repository is busy." > - exit 1 > - fi > - > - echo -n "Purging the download cache for centos-$release..." > - rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 > - exit 0 > + flock -x 200 > + if [ $? != 0 ]; then > + echo "Cache repository is busy." > + exit 1 > + fi > > - ) 200>/var/lock/subsys/lxc-centos > + echo -n "Purging the download cache for centos-$release..." > + rm --preserve-root --one-file-system -rf $cache && echo "Done." || > exit 1 > + exit 0 > + ) 200>@LOCALSTATEDIR@/lock/subsys/lxc-centos > } > > usage() > @@ -554,6 +597,12 @@ if [ ! -z "$clean" -a -z "$path" ]; then > exit 0 > fi > > +# Let's do something better for the initial root password. > +# It's not perfect but it will defeat common scanning brute force > +# attacks in the case where ssh is exposed. It will also be set to > +# expired, forcing the user to change it at first login. > +root_password=Root-${name}-${RANDOM} > + > if [ -z "${utsname}" ]; then > utsname=${name} > fi > @@ -572,7 +621,7 @@ fi > # utsname and hostname = Container_Name.Domain_Name > > if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then > - if [ -n "$(dnsdomainname)" ]; then > + if [[ "$(dnsdomainname)" != "" && "$(dnsdomainname)" != "localdomain" > ]]; then > utsname=${utsname}.$(dnsdomainname) > fi > fi > @@ -666,5 +715,20 @@ if [ ! -z $clean ]; then > clean || exit 1 > exit 0 > fi > -echo "container rootfs and config created, default root password is > '$root_password'" > -echo "edit the config file to check/enable networking setup" > +echo " > +Container rootfs and config have been created. > +Edit the config file to check/enable networking setup. > +" > + > +echo "The temporary password for root is: '$root_password' > + > +You may want to note that password down before starting the container. > + > +The password set up as "expired" and will require it to be changed it at > +first login, which you should do as soon as possible. If you lose the > +root 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): > + > + chroot ${rootfs_path} passwd > +" > diff --git a/templates/lxc-fedora.in b/templates/lxc-fedora.in > index 5f66ff1..b0c214a 100644 > --- a/templates/lxc-fedora.in > +++ b/templates/lxc-fedora.in > @@ -33,6 +33,10 @@ default_path=@LXCPATH@ > # We really need something better here! > root_password=root > > +# These are only going into comments in the resulting config... > +lxc_network_type=veth > +lxc_network_link=lxcbr0 > + > # is this fedora? > # Alow for weird remixes like the Raspberry Pi > # > @@ -194,8 +198,10 @@ EOF > mknod -m 600 ${dev_path}/initctl p > mknod -m 666 ${dev_path}/ptmx c 5 2 > > - echo "setting root passwd to $root_password" > + echo "Setting root passwd to '$root_password'" > echo "root:$root_password" | chroot $rootfs_path chpasswd > + # Also set this password as expired to force the user to change it! > + chroot $rootfs_path passwd -e root > > # specifying this in the initial packages doesn't always work. > # Even though it should have... > @@ -243,7 +249,7 @@ configure_fedora_init() > > configure_fedora_systemd() > { > - unlink ${rootfs_path}/etc/systemd/system/default.target > + rm -f ${rootfs_path}/etc/systemd/system/default.target > touch ${rootfs_path}/etc/fstab > chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/udev.service > chroot ${rootfs_path} ln -s /lib/systemd/system/multi-user.target > /etc/systemd/system/default.target > @@ -837,6 +843,7 @@ copy_fedora() > # i prefer rsync (no reason really) > mkdir -p $rootfs_path > rsync -Ha $cache/rootfs/ $rootfs_path/ > + echo > return 0 > } > > @@ -891,11 +898,53 @@ install_fedora() > return $? > } > > -copy_configuration() > +# Generate a random hardware (MAC) address composed of FE followed by > +# 5 random bytes... > +create_hwaddr() > { > + echo $(dd if=/dev/urandom bs=8 count=1 2>/dev/null | md5sum | > + sed -e 's/\(..\)\(..\)\(..\)\(..\)\(..\).*/fe:\1:\2:\3:\4:\5/') > +} > > +copy_configuration() > +{ > mkdir -p $config_path > - grep -q "^lxc.rootfs" $config_path/config 2>/dev/null || echo > "lxc.rootfs = $rootfs_path" >> $config_path/config > + > + grep -q "^lxc.rootfs" $config_path/config 2>/dev/null || echo " > +lxc.rootfs = $rootfs_path > +" >> $config_path/config > + > + # The following code is to create static MAC addresses for each > + # interface in the container. This code will work for multiple > + # interfaces in the default config. It will also strip any > + # hwaddr stanzas out of the default config since we can not share > + # MAC addresses between containers. > + mv $config_path/config $config_path/config.def > + while read LINE > + do > + # This should catch variable expansions from the default config... > + if expr "${LINE}" : '.*\$' > /dev/null 2>&1 > + then > + LINE=$(eval "echo \"${LINE}\"") > + fi > + > + # There is a tab and a space in the regex bracket below! > + # Seems that \s doesn't work in brackets. > + KEY=$(expr "${LINE}" : '\s*\([^ ]*\)\s*=') > + > + if [[ "${KEY}" != "lxc.network.hwaddr" ]] > + then > + echo "${LINE}" >> $config_path/config > + > + if [[ "${KEY}" == "lxc.network.link" ]] > + then > + echo "lxc.network.hwaddr = $(create_hwaddr)" >> > $config_path/config > + fi > + fi > + done < $config_path/config.def > + > + rm -f $config_path/config.def > + > cat <<EOF >> $config_path/config > lxc.utsname = $utsname > lxc.tty = 4 > @@ -908,6 +957,18 @@ lxc.autodev = $auto_dev > # When using LXC with apparmor, uncomment the next line to run unconfined: > #lxc.aa_profile = unconfined > > +# example simple networking setup, uncomment to enable > +#lxc.network.type = $lxc_network_type > +#lxc.network.flags = up > +#lxc.network.link = $lxc_network_link > +#lxc.network.name = eth0 > +# Additional example for veth network type > +# static MAC address, > +#lxc.network.hwaddr = 00:16:3e:77:52:20 > +# persistent veth device name on host side > +# Note: This may potentially collide with other containers of same > name! > +#lxc.network.veth.pair = v-$name-e0 > + > #cgroups > lxc.cgroup.devices.deny = a > # /dev/null and zero > @@ -929,6 +990,7 @@ EOF > proc proc proc nodev,noexec,nosuid 0 0 > sysfs sys sysfs defaults 0 0 > EOF > + > if [ $? -ne 0 ]; then > echo "Failed to add configuration" > return 1 > @@ -1006,6 +1068,12 @@ if [ ! -z "$clean" -a -z "$path" ]; then > exit 0 > fi > > +# Let's do something better for the initial root password. > +# It's not perfect but it will defeat common scanning brute force > +# attacks in the case where ssh is exposed. It will also be set to > +# expired, forcing the user to change it at first login. > +root_password=Root-${name}-${RANDOM} > + > if [ -z "${utsname}" ]; then > utsname=${name} > fi > @@ -1024,7 +1092,7 @@ fi > # utsname and hostname = Container_Name.Domain_Name > > if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then > - if [ -n "$(dnsdomainname)" ]; then > + if [[ "$(dnsdomainname)" != "" && "$(dnsdomainname)" != "localdomain" > ]]; then > utsname=${utsname}.$(dnsdomainname) > fi > fi > @@ -1128,12 +1196,14 @@ if [ ! -z $clean ]; then > clean || exit 1 > exit 0 > fi > -echo "container rootfs and config created" > +echo " > +Container rootfs and config have been created. > +Edit the config file to check/enable networking setup. > +" > > if [[ -d ${cache_base}/bootstrap ]] > then > - echo " > -You have successfully built a Fedora container and cache. This cache may > + echo "You have successfully built a Fedora container and cache. This > cache may > be used to create future containers of various revisions. The directory > ${cache_base}/bootstrap contains a bootstrap > which may no longer needed and can be removed. > @@ -1147,3 +1217,16 @@ This is only used in the creation of the bootstrap > run-time-environment > and may be removed. > " > fi > + > +echo "The temporary password for root is: '$root_password' > + > +You may want to note that password down before starting the container. > + > +The password set up as "expired" and will require it to be changed it at > +first login, which you should do as soon as possible. If you lose the > +root 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): > + > + chroot ${rootfs_path} passwd > +" > -- > 1.8.3.1 > > > -- > Michael H. Warfield (AI4NB) | (770) 978-7061 | m...@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! > > > _______________________________________________ > lxc-devel mailing list > lxc-devel@lists.linuxcontainers.org > http://lists.linuxcontainers.org/listinfo/lxc-devel > -- S.Çağlar Onur <cag...@10ur.org> _______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel