Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] issuegen: detect util-linux RPM version, set output directory appropriately #40

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[Unit]
Description=Generate /run/issue.d/console-login-helper-messages.issue
Description=Generate console-login-helper-messages issue snippet
Before=systemd-user-sessions.service
Wants=network-online.target
After=network-online.target sshd-keygen.target
Expand Down
71 changes: 48 additions & 23 deletions usr/libexec/console-login-helper-messages/issuegen
Original file line number Diff line number Diff line change
Expand Up @@ -14,42 +14,67 @@
set -e

PKG_NAME=console-login-helper-messages
ISSUE_DIR_PUBLIC=issue.d
ISSUE_DIR_PRIVATE="${PKG_NAME}/issue.d"
SSH_DIR=/etc/ssh
ISSUE_SNIPPETS_PATH=${PKG_NAME}/issue.d

# The public directories are to be read by higher-level programs to display
# the issue on login, e.g. agetty.
# The private directories are to be read only by this script.
mkdir -p "${SSH_DIR}"
mkdir -p "/run/${ISSUE_DIR_PUBLIC}"
mkdir -p "/run/${ISSUE_DIR_PRIVATE}"
# Snippet locations that are read by issuegen to generate combined snippet
# data, which is outputted in ${generated_file} (below).
ETC_SNIPPETS="/etc/${ISSUE_SNIPPETS_PATH}"
RUN_SNIPPETS="/run/${ISSUE_SNIPPETS_PATH}"
USR_LIB_SNIPPETS="/usr/lib/${ISSUE_SNIPPETS_PATH}"
Copy link
Contributor Author

@rfairley rfairley Apr 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking the variable names should not need to distinguish the private/public path, at least for now, since for issuegen all snippets are written into the "private" directories. Previously, ISSUE_DIR_PUBLIC was unused. The *_SNIPPETS variables will just refer to the snippet paths that will get read in order to create ${generated_file}.

For #7, we may allow a choice of using the public or private locations for the snippet locations by invoking e.g. issuegen or issuegen --legacy respectively from the console-login-helper-messages-issuegen.service unit (this choice would be needed for systems that have util-linux version under 2.35 - e.g. RHCOS). We would probably try to split the ssh, udev, and generated issue parts up and have SSH_KEY_OUTDIR and UDEV_IF_OUTDIR set to either /run/issue.d (public) or /run/console-login-helper-messages/issue.d (private - i.e. the RUN_SNIPPETS variable). The private locations would be used for the *_OUTDIR variables if --legacy was passed. However more discussion can be done on this in #7. In any case, the *_SNIPPETS locations should be consumed only when creating ${generated_file} - the *_SNIPPETS variables shouldn't need to change after this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could either use a config file (like a file in /etc/console-login-helper-messages/foo.conf) to set the paths to output to or we could detect the version of util-linux and switch based on that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

though would we still want to use a private directory for all the snippets and then just write out generated_file to the public directory like we do for motdgen in #44

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 a config file would be good at some point. A specfile would make the choice on the output paths set in /etc/console-login-helper-messages/foo.conf, based on the util-linux version.

I'm thinking if a config file is added, we'd want to support an extensible config file format - which would allow on/off configuration for each piece of information (udev interfaces, ssh keys, etc) (#15), and whether the snippets are output in the issue, motd, or other. I've opened this to discuss #45.

For now, going with having issuegen check the util-linux version and set SSH_KEY_OUTDIR, UDEV_IF_OUTDIR, and generated_file appropriately seems simplest - this could be default behaviour if a config path was not specified if we added a config file. Will update this PR with the check on the util-linux version and setting the path shortly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now updated with the version check - kept so that the check would only make the switch automatically for RPM-based distributions for now.


# Output locations for snippets produced by issuegen.
SNIPPETS_OUTDIR="${RUN_SNIPPETS}"
GENERATED_FILE_OUTDIR="/run/${PKG_NAME}"

# Check util-linux version, and set output directories accordingly.
# If not on an RPM-based system, then just continue keeping the output
# directories at their defaults.
if command -v rpm >/dev/null; then
UTIL_LINUX_VERSION=$(rpm -q --queryformat="%{version}" util-linux)
UTIL_LINUX_MAJOR_VERSION=$(echo ${UTIL_LINUX_VERSION} | awk -F '.' '{print $1}')
UTIL_LINUX_MINOR_VERSION=$(echo ${UTIL_LINUX_VERSION} | awk -F '.' '{print $2}')
# Check that util-linux-2.35 or higher is installed, which includes necessary
# support for /run/issue.d: https://github.com/karelzak/util-linux/commit/456bcbca6b55fbed33d9f86e69a51abd0e1b8f0b
if [[ ${UTIL_LINUX_MAJOR_VERSION} -gt 2 ]] || [[ ${UTIL_LINUX_MAJOR_VERSION} -eq 2 && ${UTIL_LINUX_MINOR_VERSION} -ge 35 ]]; then
SNIPPETS_OUTDIR=/run/issue.d
GENERATED_FILE_OUTDIR=/run/issue.d
fi
fi

# Make sure the output directories are created upfront, so there is no error
# writing to them.
mkdir -p ${SNIPPETS_OUTDIR} ${GENERATED_FILE_OUTDIR}

# Provide key fingerprints via issue

# Provide key fingerprints via issue.
SSH_DIR=/etc/ssh
# Ensure `${SSH_DIR}` is created and can be searched without error.
mkdir -p "${SSH_DIR}"
SSH_KEY_OUTDIR="${SNIPPETS_OUTDIR}"
for KEY_FILE in $(find "${SSH_DIR}" -name 'ssh_host_*_key') ; do
ssh-keygen -l -f "${KEY_FILE}"
done | awk '{print "SSH host key: " $2 " " $4}' > "/run/${ISSUE_DIR_PRIVATE}/21_ssh_host_keys.issue"
done | awk '{print "SSH host key: " $2 " " $4}' > "${SSH_KEY_OUTDIR}/21_ssh_host_keys.issue"

# Data from udev rules

# Add/remove data from udev rules.
UDEV_IF_OUTDIR="${SNIPPETS_OUTDIR}"
case "${ACTION}" in
add)
echo "${INTERFACE}: \\4{${INTERFACE}} \\6{${INTERFACE}}" > "/run/${ISSUE_DIR_PRIVATE}/22_${INTERFACE}.issue"
echo "${INTERFACE}: \\4{${INTERFACE}} \\6{${INTERFACE}}" > "${UDEV_IF_OUTDIR}/22_${INTERFACE}.issue"
;;
remove)
rm -f "/run/${ISSUE_DIR_PRIVATE}/22_${INTERFACE}.issue"
rm -f "${UDEV_IF_OUTDIR}/22_${INTERFACE}.issue"
;;
esac

# TODO: it would be nice to have /run/issue.d be an official directory,
# see https://github.com/karelzak/util-linux/commit/1fc82a1360305f696dc1be6105c9c56a9ea03f52#commitcomment-27949895
# until then, $GENERATED_ISSUE writes to the privately scoped directory (not in /run/issue.d)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In particular, #7 is tracking this comment - no longer need to mention in the source.

#
# Pick 40 as an index as other files can order around it easily.
generated_file="/run/${PKG_NAME}/40_${PKG_NAME}.issue"

# Generate a final issue message from compiling the snippets.
# Pick 40 as a prefix as other files can order around it easily.
generated_file="${GENERATED_FILE_OUTDIR}/40_${PKG_NAME}.issue"
generated_string=''
# Hack around files potentially not existing in the below paths with `|| true`.
generated_string+=$(cat /etc/${ISSUE_DIR_PRIVATE}/* 2>/dev/null || true)
generated_string+=$(cat /run/${ISSUE_DIR_PRIVATE}/* 2>/dev/null || true)
generated_string+=$(cat /usr/lib/${ISSUE_DIR_PRIVATE}/* 2>/dev/null || true)
generated_string+=$(cat ${ETC_SNIPPETS}/* 2>/dev/null || true)
generated_string+=$(cat ${RUN_SNIPPETS}/* 2>/dev/null || true)
generated_string+=$(cat ${USR_LIB_SNIPPETS}/* 2>/dev/null || true)

echo "${generated_string}" > "${generated_file}"