confd: add support for vendor/product specific factory-config

With the recent changes to confd to support: hostname format specifiers,
$factory$ default keyword for password, and on-the-fly generation of the
NETCONF SSH host keys, the system no longer depend on the very intricate
confd gen-* scripts to create factory-config and failure-config.

This patch set adds support for detecting and installing product/vendor
specific static factory-config and failure-config files.  See the confd
README for details.

To facilitate generation, e.g., of the NETCONF SSH host keys, the confd
daemon must be running when bootstrapping the first startup-config from
eithe generated or static factory-config.  This is why the bootstrap and
load helper scripts have been changed.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2024-06-25 17:22:36 +02:00
parent 3aead122ee
commit ed88a92fac
5 changed files with 87 additions and 27 deletions
+22
View File
@@ -0,0 +1,22 @@
#!/bin/sh
# Find and install any product specific files in /etc before bootstrap
ident=$(basename "$0")
PREFIXD=/usr/share/product
PRODUCT=$(jq -r '."product-name" | ascii_downcase' /run/system.json)
note()
{
logger -k -p user.notice -t "$ident" "$1"
}
DIR="$PREFIXD/$PRODUCT"
if [ -z "$PRODUCT" ] || [ ! -d "$DIR" ]; then
note "No vendor/product specific directory found, using built-in defaults."
exit 0
fi
note "Using vendor/product specific defaults."
for dir in "$DIR"/*; do
[ -d "$dir" ] && cp -a "$dir" /
done
+25
View File
@@ -6,6 +6,31 @@ between sysrepo and netopeer2 (NETCONF) and the UNIX system under
it all.
Factory & Failure Config
------------------------
Infix supports both static and dynamically generated factory-config. At
boot the dynamic is always generated to `/run/confd/factory-config.gen`,
which is installed to `/etc/factory-config.cfg` and used by default, if
that file does not already exist. The same applies to the failure mode
configuration.
The following describes how a vendor/product specific config is found
and installed into `/etc/factory-config.cfg` before the dynamic one is
installed.
1. `/etc/factory-config.cfg`: built into the image, e.g., r2s
2. `/usr/share/product/<PRODUCT>/etc/factory-config.cfg`, where the
`<PRODUCT>` is determined from the VPD, which is available after
`probe` has run, in `/run/system.json` as `"product-name"`. The
lower case version of the string is used
In the second option a script running just after `probe` will in fact
`cp` the complete product specific directory to `/`, meaning any file
and directory that is writable at runtime can be overloaded with device
specific versions.
Origin & References
-------------------
+16 -20
View File
@@ -4,8 +4,8 @@
########################################################################
# The system factory-config and failure-config are derived from default
# settings snippets, from /usr/share/confd/factory.d, and some generated
# snippets, e.g., device unique password, hostname (based on base MAC
# address), and number of interfaces.
# snippets, e.g., hostname (based on base MAC address) and number of
# interfaces.
#
# The resulting factory-config is used to create the syrepo db (below)
# {factory} datastore. Hence, the factory-config file must match the
@@ -127,6 +127,8 @@ failure()
collate "$FAILURE_GEN" "$FAILURE_CFG" "$FAILURE_D"
}
# Both factory-config and failure-config are generated every boot
# regardless if there is a static /etc/factory-config.cfg or not.
factory "$FACTORY_GEN"
failure "$FAILURE_GEN"
@@ -143,24 +145,18 @@ else
fi
rc=$?
sysrepoctl -z $INIT_DATA
rc=$?
sudo -u root -g wheel sysrepocfg -f json -I"$INIT_DATA" -d running
rc=$?
#rm $INIT_DATA
# On first boot, install factory-config as startup-config.
chgrp wheel /cfg
chmod g+w /cfg
if [ ! -f "$STARTUP_CFG" ]; then
sysrepocfg -f json -X"$STARTUP_CFG"
chgrp wheel "$CFG_PATH_"
chmod g+w "$CFG_PATH_"
if ! sysrepoctl -z "$INIT_DATA"; then
rc=$?
logger -sik -p user.error "Failed loading factory-default datastore"
else
# Clear running-config so we can load/create startup in the next step
temp=$(mktemp)
echo "{}" > "$temp"
sysrepocfg -f json -I"$temp" -d running
rc=$?
rm "$temp"
fi
# Clear running-config so we can load startup in the next step
temp=$(mktemp)
echo "{}" > $temp
sysrepocfg -f json -I$temp -d running
exit $rc
+24 -7
View File
@@ -7,7 +7,6 @@
# sysrepocfg returns OK. This to be able to detect and trigger the Infix
# Fail Secure Mode at boot.
#
set -e
banner_append()
{
@@ -19,6 +18,14 @@ banner_append()
return 0
}
# Ensure correct ownership and permissions, in particular after factory reset
# Created by the system, writable by any user in the admin group.
perms()
{
chown root:wheel "$1"
chmod 0660 "$1"
}
note()
{
logger -s -I $$ -p user.notice -t load "$*"
@@ -45,8 +52,21 @@ else
fi
if [ ! -f "$fn" ]; then
err "No such file, $fn, aborting!"
exit 1
case "$config" in
startup-config)
note "startup-config missing, initializing running datastore from factory-config"
sysrepocfg -C factory-default
rc=$?
note "saving factory-config to $STARTUP_CFG ..."
sysrepocfg -f json -X"$STARTUP_CFG"
perms "$STARTUP_CFG"
exit $rc
;;
*)
err "No such file, $fn, aborting!"
exit 1
;;
esac
fi
note "Loading $config ..."
@@ -82,8 +102,5 @@ note "Loaded $fn successfully."
if [ "$config" = "failure-config" ]; then
banner_append "ERROR: Corrupt startup-config, system has reverted to default login credentials"
else
# Ensure correct ownership and permissions, in particular after factory reset
# Created by the system, writable by any user in the admin group.
chown root:wheel "$fn"
chmod 0660 "$fn"
perms "$fn"
fi