Skip to content

Commit

Permalink
templates: Rework node-valid-hostname to fix SELinux denial
Browse files Browse the repository at this point in the history
BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1956836

Unfortunately right now, executing `bash` skips a domain transition
(see fedora-selinux/selinux-policy#778)
so the way we're sourcing the script means we stay in `initrc_t`
and end up triggering a SELinux policy denial.

(BTW this denial turns out to just delay the successful exit
 of the script, which will then end up just delaying kubelet start.
 it's otherwise harmless, but we also don't want SELinux policy denials
 in our product by default)

Fix this in two ways:

- First, just move the thing to `/usr/local/bin` to avoid issues
  with labeling of `/usr/local/sbin` that were fixed in openshift/os#551
- Second, rework it to be executed directly

While we're here:

- Clean the confusing+outdated comment about being a NM dispatcher
- Drop the `logger` bit which was only necessary as a NM dispatcher;
  since we're *always* running under systemd, this makes `journalctl -u node-valid-hostname`
  actually show the script output.
- Make it crystal clear that the "truncate hostname" is only run in GCP.
- Fix various typos
- Use the more precise term "non-localhost" in various places instead of the more ambiguous
  terms "real"/"valid"
  • Loading branch information
cgwalters committed Jun 16, 2021
1 parent b2fec38 commit 783aa2c
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 94 deletions.
64 changes: 64 additions & 0 deletions templates/common/_base/files/usr-local-bin-mco-hostname.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
mode: 0755
path: "/usr/local/bin/mco-hostname"
contents:
inline: |
#!/bin/bash
# First, we need to wait until DHCP finishes and the node has a non-`localhost`
# hostname before `kubelet.service` starts.
# That's the `--wait` argument as used by `node-valid-hostname.service`.
#
# Second, on GCP specifically we truncate the hostname if it's >63 characters.
# That's `gcp-hostname.service`.
# Block indefinitely until the host gets a non-localhost name.
# Note node-valid-hostname.service uses systemd to abort if this takes too long.
wait_localhost() {
echo "waiting for non-localhost hostname to be assigned"
while [[ "$(< /proc/sys/kernel/hostname)" =~ (localhost|localhost.localdomain) ]];
do
sleep 1
done
echo "node identified as $(</proc/sys/kernel/hostname)"
exit 0
}
set_gcp_hostname() {
/usr/bin/afterburn --provider gcp --hostname=/run/afterburn.hostname
local host_name=$(cat /run/afterburn.hostname)
local type_arg="transient"
# /etc/hostname is used for static hostnames and is authoritative.
# This will check to make sure that the static hostname is the
# less than or equal to 63 characters in length.
if [ -f /etc/hostname ] && [ "$(cat /etc/hostname | wc -m)" -gt 0 ]; then
etc_name="$(< /etc/hostname)"
type_arg="static"
if [ "${etc_name}" != "${host_name}" ]; then
echo "/etc/hostname is set to ${etc_name} but does not match ${host_name}"
echo "using /etc/hostname as the authoritative name"
host_name="${etc_name}"
fi
fi
# Only mutate the hostname if the length is longer than 63 characters. The
# hostname will be the lesser of 63 characters after the first dot in the
# FQDN. This algorithm is only known to work in GCP, and hence is only
# executed in GCP.
if [ "${#host_name}" -gt 63 ]; then
alt_name=$(printf "${host_name}" | cut -f1 -d'.' | cut -c -63)
echo "${host_name} is longer than 63 characters, using truncated hostname"
host_name="${alt_name}"
fi
echo "setting ${type_arg} hostname to ${host_name}"
/bin/hostnamectl "--${type_arg}" set-hostname "${host_name}"
exit 0
}
arg=${1}; shift;
case "${arg}" in
--wait) wait_localhost;;
--gcp) set_gcp_hostname;;
*) echo "Unhandled arg $arg"; exit 1
esac

This file was deleted.

11 changes: 4 additions & 7 deletions templates/common/_base/units/node-valid-hostname.service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,20 @@ name: node-valid-hostname.service
enabled: true
contents: |
[Unit]
Description=Ensure the node hostname is valid for the cluster
Description=Wait for a non-localhost hostname
Before=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
User=root
ExecStart=/usr/local/bin/mco-hostname --wait
# SystemD prevents direct execution of the script in /usr/local/sbin,
# so it is sourced. See the script for functionality.
ExecStart=/bin/bash -c "source /usr/local/sbin/set-valid-hostname.sh; wait_localhost; set_valid_hostname `hostname`"
# Wait up to 5min for the node to get a real hostname.
# Wait up to 5min for the node to get a non-localhost name
TimeoutSec=300
[Install]
WantedBy=multi-user.target
# Ensure that network-online.target will not complete until the node has a real hostname.
# Ensure that network-online.target will not complete until the node has a non-localhost hostname.
RequiredBy=network-online.target
7 changes: 3 additions & 4 deletions templates/common/gcp/units/gcp-hostname.service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,17 @@ contents: |
Description=Set GCP Transient Hostname
# Removal of this file signals firstboot completion
ConditionPathExists=!/etc/ignition-machine-config-encapsulated.json
# Block services relying on Networking being up.
# Block services relying on networking being up.
Before=network-online.target
# Wait for NetworkManager to report its online
# Wait for NetworkManager to report it's online
After=NetworkManager-wait-online.service
# Run before hostname checks
Before=node-valid-hostname.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/usr/bin/afterburn --provider gcp --hostname=/run/afterburn.hostname
ExecStart=/bin/bash -c "source /usr/local/sbin/set-valid-hostname.sh; set_valid_hostname `cat /run/afterburn.hostname`"
ExecStart=/usr/local/bin/mco-hostname --gcp
[Install]
WantedBy=multi-user.target
Expand Down

0 comments on commit 783aa2c

Please sign in to comment.