project-config/nodepool/elements/nodepool-base/finalise.d/89-boot-settings
Cédric Jeanneret 916b043710 Ensure NetworkManager doesn't override /etc/resolv.conf
Until now, whenever NetworkManager gets reloaded/restarted/lease
refresh, it would override the /etc/resolv.conf file with the
nameservers and related it gets from the network.

This patch ensures this won't happen ever again.

Note: this is a corrected version of
I92bc12b8f712e28962d24dd6474cfce22b81222c
that was reverted due to indentation + use of ConfigParser issues.

Change-Id: I48560641238911154cc9f353f707a9374613e51a
2022-12-02 15:10:41 +01:00

255 lines
9.0 KiB
Bash
Executable File

#!/bin/bash
# Copyright (C) 2011-2013 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
#
# See the License for the specific language governing permissions and
# limitations under the License.
# dib-lint: disable=set setu setpipefail indent
if [ ${DIB_DEBUG_TRACE:-0} -gt 0 ]; then
set -x
fi
set -e
#
# Note that in OpenStack infra, the configure-unbound role [1] that is
# part of the base jobs will reconfigure unbound based on the host's
# ipv6 support very early in the job setup. Thus the following
# forwarder setup is only relevant to the initial boot and some parts
# of the integration-tests before configure-unbound role is used.
#
# [1] https://opendev.org/opendev/base-jobs/src/branch/master/roles/configure-unbound
#
NODEPOOL_STATIC_NAMESERVER_V4=${NODEPOOL_STATIC_NAMESERVER_V4:-1.0.0.1}
NODEPOOL_STATIC_NAMESERVER_V4_FALLBACK=${NODEPOOL_STATIC_NAMESERVER_V4_FALLBACK:-8.8.8.8}
# Explicitly setting a v6 nameserver implies you want ipv6
if [[ -n ${NODEPOOL_STATIC_NAMESERVER_V6:-} || -n ${NODEPOOL_STATIC_NAMESERVER_V6_FALLBACK} ]]; then
NODEPOOL_STATIC_NAMESERVER_POPULATE_IPV6=1
fi
if [[ ${NODEPOOL_STATIC_NAMESERVER_POPULATE_IPV6:-0} == 1 ]]; then
NODEPOOL_STATIC_NAMESERVER_V6=${NODEPOOL_STATIC_NAMESERVER_V6:-2606:4700:4700::1111}
NODEPOOL_STATIC_NAMESERVER_V6_FALLBACK=${NODEPOOL_STATIC_NAMESERVER_V6_FALLBACK:-2001:4860:4860::8888}
dd of=/tmp/forwarding.conf <<EOF
forward-zone:
name: "."
forward-addr: $NODEPOOL_STATIC_NAMESERVER_V6
forward-addr: $NODEPOOL_STATIC_NAMESERVER_V6_FALLBACK
forward-addr: $NODEPOOL_STATIC_NAMESERVER_V4
forward-addr: $NODEPOOL_STATIC_NAMESERVER_V4_FALLBACK
EOF
else
# Otherwise, only populate ipv4 nameservers here. We used to just
# do both, but we found it unreliable on hosts/platforms without
# ipv6 support (see
# https://www.nlnetlabs.nl/bugs-script/show_bug.cgi?id=4188).
dd of=/tmp/forwarding.conf <<EOF
forward-zone:
name: "."
forward-addr: $NODEPOOL_STATIC_NAMESERVER_V4
forward-addr: $NODEPOOL_STATIC_NAMESERVER_V4_FALLBACK
EOF
fi
mv /tmp/forwarding.conf /etc/unbound/
chown root:root /etc/unbound/forwarding.conf
chmod a+r /etc/unbound/forwarding.conf
UNBOUND_LOGGING_CONF="\
server:
chroot: \"\"
logfile: \"/var/log/unbound.log\"
# Log debug messages
verbosity: 5"
echo "$UNBOUND_LOGGING_CONF" > /tmp/unbound-logging.conf
if [[ "$DISTRO_NAME" =~ (centos|rhel7|fedora|opensuse|openeuler|rocky) ]] ; then
UNBOUND_CONFD=/etc/unbound/conf.d
elif [[ "$DISTRO_NAME" =~ 'gentoo' ]] ; then
UNBOUND_CONFD=/etc/unbound/conf.d
mkdir -p $UNBOUND_CONFD
echo "include: \"$UNBOUND_CONFD/*.conf\"" >> /etc/unbound/unbound.conf
else
UNBOUND_CONFD=/etc/unbound/unbound.conf.d
fi
mv /tmp/unbound-logging.conf $UNBOUND_CONFD
chown root:root $UNBOUND_CONFD/unbound-logging.conf
chmod a+r $UNBOUND_CONFD/unbound-logging.conf
touch /var/log/unbound.log
chown unbound /var/log/unbound.log
chmod 0644 /var/log/unbound.log
# NOTE(ianw) 2022-05-22 : not 100% sure why but emperically unbound
# runs under named context. Generally it doesn't log here on rhel-ish
# distros, but for consistency it's much easier if we just have one
# log file in the same place across distros. Thus set the context to
# allow it.
if [[ -e /usr/sbin/semanage ]]; then
semanage fcontext -a -t named_log_t /var/log/unbound.log
restorecon -v /var/log/unbound.log
fi
if [[ "$DISTRO_NAME" =~ (opensuse) ]] ; then
# NOTE(ianw) 2021-03-17 : something about building the suse chroot
# has changed and /etc/init.d/ is no longer available. However,
# it rc-local.service (part of systemd) still runs. We should
# probably convert this all to a systemd job; but for now...
mkdir -p /etc/init.d
rclocal=/etc/init.d/boot.local
elif [[ "${DISTRO_NAME}" =~ "gentoo" ]]; then
rclocal=/etc/local.d/unbound.start
mkdir -p /etc/local.d
else
# You'd think rc.local would be simple ...
#
# On Redhat systems, systemd's rc-local service looks for an
# executable /etc/rc.d/rc.local file to run. On Debian/Ubuntu, the
# eqivalent file is /etc/rc.local, which is missing on Debian stretch.
#
# Centos' systemd package symlinks /etc/rc.local to /etc/rc.d/rc.local
# correctly. Fedora, however, does not come with an rc.local file at
# all. Thus if we have a rc.d directory, but no rc.local file, we
# need to create it (if you don't have an rc.d directory, and don't
# have /etc/rc.local, then it's not clear what platform you are on).
#
# Bug [1] is filed to bring Fedora in-line with Centos, and has more
# details on all this. As at 2016-10-18 is unresolved.
#
# [1] https://bugzilla.redhat.com/show_bug.cgi?id=1386052
if [[ ! -e /etc/rc.local ]] && [[ ! -e /etc/debian_version ]]; then
if [[ ! -d /etc/rc.d ]]; then
echo "No rc.local and no rc.d directory! See comments in 89-boot-settings"
exit 1
fi
touch /etc/rc.d/rc.local
ln -sf /etc/rc.d/rc.local /etc/rc.local
# permissions added below. selinux context will be fixed up at
# end of build.
fi
rclocal=/etc/rc.local
fi
# Overwrite /etc/resolv.conf at boot (let's hope nothing else is using
# rc.local...)
cat >$rclocal <<EOF
#!/bin/bash
set -o xtrace
# Some providers inject dynamic network config statically. Work around this
# for DNS nameservers. This is expected to fail on some nodes so remove -e.
set +e
sed -i -e 's/^\(DNS[0-9]*=[.0-9]\+\)/#\1/g' /etc/sysconfig/network-scripts/ifcfg-*
sed -i -e 's/^NETCONFIG_DNS_POLICY=.*/NETCONFIG_DNS_POLICY=""/g' /etc/sysconfig/network/config
set -e
echo 'nameserver 127.0.0.1' > /etc/resolv.conf
EOF
# Configure NetworkManager to not manage /etc/resolv.conf
if [ -d /etc/NetworkManager/conf.d ]; then
cat <<EOF |python3
import configparser
p = configparser.ConfigParser()
p['main'] = {'rc-manager': 'unmanaged'}
with open('/etc/NetworkManager/conf.d/rc-manager.conf', 'w') as fh:
p.write(fh)
EOF
fi
# openSUSE doesn't have an iptables service, so apply the iptables rules at boot
if [[ "${DISTRO_NAME}" =~ (opensuse) ]] ; then
cat >>$rclocal <<EOF
iptables-restore /etc/sysconfig/iptables
ip6tables-restore /etc/sysconfig/ip6tables
EOF
fi
cat >>$rclocal <<EOF
exit 0
EOF
# Debian/Ubuntu ship their dummy rc.local with +x permissions, but
# CentOS (and the file we created for Fedora) do not ... this is to
# avoid it holding up the boot as it relies on the network being up).
# Add +x so it runs.
chmod a+x $rclocal
echo 'include: /etc/unbound/forwarding.conf' >> /etc/unbound/unbound.conf
# Disable dlv. Per the unbound.conf manpage this should not be used
# anymore but is in use by some of our distros. The problem here is it
# does lookasides for DNSSEC which increases the number of queries and
# introduces more points of lookup failure. Disable it to avoid these
# problems.
sed -i -e 's/dlv-anchor-file:/#dlv-anchor-file:/g' /etc/unbound/unbound.conf
# Tripleo uses dhcp
dhcp_file=''
if [[ "$DISTRO_NAME" =~ (centos|rhel7|fedora|openeuler|rocky) ]] ; then
dhcp_file=/etc/dhcp/dhclient-eth0.conf
elif [[ "$DISTRO_NAME" =~ (debian|ubuntu|gentoo) ]] ; then
dhcp_file=/etc/dhcp/dhclient.conf
fi
if [ -n "$dhcp_file" ] ; then
cat > $dhcp_file <<EOF
option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
send host-name "<hostname>";
request subnet-mask, broadcast-address, routers,
interface-mtu, rfc3442-classless-static-routes;
supersede domain-name-servers 127.0.0.1;
supersede domain-search "";
supersede domain-name "";
EOF
fi
# On bionic and later, the install of the new systemd-resolved in the
# chroot will see that there is no /etc/resolv.conf and assume it is a
# blank system where it will be the nameserver provider. It thus
# creates /etc/resolv.conf as a link back to its compatability files.
# To configure systemd-resolved's resolvers you need to modify
# /etc/systemd/resolved.conf; which would be possible, but we'd prefer
# to be consistent across all our platforms.
#
# dib will copy whatever is in /etc/resolv.conf.ORIG to
# /etc/resolv.conf as one of the final steps in image creation. Thus
# we are hard-coding resolution to localhost (unbound) here.
#
# Note that with /etc/resolv.conf as a regular file, systemd-resolved
# will also obey it for nameserver info when it starts at boot.
rm -f /etc/resolv.conf.ORIG
echo "nameserver 127.0.0.1" > /etc/resolv.conf.ORIG
case "$DIB_INIT_SYSTEM" in
upstart)
# nothing to do
;;
systemd)
systemctl enable unbound.service
;;
openrc)
rc-update add unbound default
;;
sysv)
# nothing to do
;;
*)
echo "Unsupported init system $DIB_INIT_SYSTEM"
exit 1
;;
esac