#!/bin/sh # Bootstrap system factory-config, failure-config and sysrepo db. # ######################################################################## # 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. # # The resulting factory-config is used to create the syrepo db (below) # {factory} datastore. Hence, the factory-config file must match the # the YANG models of the active image. ######################################################################## # NOTE: with the Infix defaults, a br2-external can provide a build-time # /etc/factory-config.cfg to override the behavior of this script. # # This applies also for /etc/failure-config.cfg, but we recommend # strongly that you instead provide gen-err-custom, see below. # # TODO: Look for statically defined factory-config, based on system's # product ID, or just custom site-specific factory on /cfg. ######################################################################## STATUS="" # When logging errors, generating /etc/issue* or /etc/banner (SSH) . /etc/os-release # /etc/confdrc controls the behavior or most of the gen-scripts, # customize in an overlay when using Infix as an br2-external. RC=/etc/confdrc if [ "$1" = "-f" ] && [ -f "$2" ]; then RC=$2 fi if [ ! -f "$RC" ]; then logger -sik -p user.error -t bootstrap "Missing rc file $RC" 2>/dev/null \ || echo "Missing rc file $RC" exit 99 fi # shellcheck disable=SC1090 . "$RC" # Gather all .json files in $dir, sort them numerically, and use jq # magic to create a configuration file without duplicates. Allowing # overrides of the Infix defaults in a br2-external. # # 10-foo.json -- Static Infix default # 20-bar.json -- Generated Infix bar # 30-config.json -- By br2-external provided gen-cfg-custom # 30-foo.json -- Static br2-external replacing 10-foo.json # # Note: to override just the base hostname, used in gen-hostname, set # BR2_TARGET_GENERIC_HOSTNAME in your br2-external's defconfig. # # shellcheck disable=SC2046,SC2086 collate() { gen=$1; shift cfg=$1; shift dir=$1 rm -f "$gen" jq -s 'reduce .[] as $item ({}; . * $item)' $(find $dir -name '*.json' | sort) >"$gen" chmod 444 "$gen" if [ ! -f "$cfg" ]; then cp "$gen" "$cfg" fi } # Report error on console, syslog, and set login banners for getty + ssh console_error() { logger -p user.crit -t bootstrap "$1" # shellcheck disable=SC3037 /bin/echo -e "\n\n\e[31mCRITICAL BOOTSTRAP ERROR\n$1\e[0m\n" > /dev/console [ -z "$STATUS" ] || return STATUS="CRITICAL ERROR: $1" printf "\n$STATUS\n" | tee -a \ /etc/banner \ /etc/issue \ /etc/issue.net \ >/dev/null return 0 } factory() { gen=$1 # Fetch defaults, simplifies sort in collate() cp "$FACTORY_DEFAULTS_D"/* "$FACTORY_D/" # Create an overlay for /etc/hostname to change the default in an br2-external gen-hostname >"$FACTORY_D/20-hostname.json" gen-motd >"$FACTORY_D/20-motd.json" gen-hardware >"$FACTORY_D/20-hardware.json" # shellcheck disable=SC2086 gen-interfaces $GEN_IFACE_OPTS >"$FACTORY_D/20-interfaces.json" # Extract password for admin user from VPD if ! gen-admin-auth infix-shell-type:bash >"$FACTORY_D/20-authentication.json"; then console_error "Unable to create factory-config, gen-admin-auth failed" return fi [ -s "$FACTORY_D/20-hostkey.json" ] || gen-hostkeys >"$FACTORY_D/20-hostkey.json" # Optional commands (from an overlay) to run for br2-externals [ -x "$(command -v gen-ifs-custom)" ] && gen-ifs-custom >"$FACTORY_D/20-interfaces.json" [ -x "$(command -v gen-cfg-custom)" ] && gen-cfg-custom >"$FACTORY_D/30-config.json" collate "$FACTORY_GEN" "$FACTORY_CFG" "$FACTORY_D" } failure() { gen=$1 # Fetch defaults, simplifies sort in collate() cp "$FAILURE_DEFAULTS_D"/* "$FAILURE_D" gen-hostname "$FAIL_HOSTNAME" >"$FAILURE_D/20-hostname.json" gen-interfaces >"$FAILURE_D/20-interfaces.json" # Same password as factory-config, but another login shell if ! gen-admin-auth infix-shell-type:bash >"$FAILURE_D/20-authentication.json"; then console_error "Invalid password hash in vital product data, failure-config incomplete!" fi [ -s "$FAILURE_D/20-hostkey.json" ] || gen-hostkeys >"$FAILURE_D/20-hostkey.json" # Optional failure/error config to generate (or override) for br2-externals [ -x "$(command -v gen-err-custom)" ] && gen-err-custom >"$FAILURE_D/30-error.json" collate "$FAILURE_GEN" "$FAILURE_CFG" "$FAILURE_D" } factory "$FACTORY_GEN" failure "$FAILURE_GEN" if [ -n "$TESTING" ]; then echo "Done." exit 0 fi # Drop all pre-initialized data from netopeer2 install, then re-create # with required netopeer2 models, sysrepo implicitly installs its own, # and then we initialize it all with our factory defaults. rm -rf /etc/sysrepo/* /dev/shm/sr_* mkdir -p /etc/sysrepo/ if [ -f "$FACTORY_CFG" ]; then cp "$FACTORY_CFG" "$INIT_DATA" else cp "$FAILURE_CFG" "$INIT_DATA" fi sysrepoctl -s $SEARCH \ -i ietf-system@2014-08-06.yang -g wheel -p 0660 \ -e authentication \ -e local-users \ -e ntp \ -e ntp-udp-port \ -e timezone-name \ -i iana-timezones@2013-11-19.yang -g wheel -p 0660 \ -i nc-notifications@2008-07-14.yang -g wheel -p 0660 \ -i notifications@2008-07-14.yang -g wheel -p 0660 \ -i ietf-keystore@2019-07-02.yang -g wheel -p 0660 \ -e keystore-supported \ -e local-definitions-supported \ -e key-generation \ -i ietf-truststore@2019-07-02.yang -g wheel -p 0660 \ -e truststore-supported \ -e x509-certificates \ -i ietf-tcp-common@2019-07-02.yang -g wheel -p 0660 \ -e keepalives-supported \ -i ietf-ssh-server@2019-07-02.yang -g wheel -p 0660 \ -e local-client-auth-supported \ -i ietf-tls-server@2019-07-02.yang -g wheel -p 0660 \ -e local-client-auth-supported \ -i ietf-netconf-server@2019-07-02.yang -g wheel -p 0660 \ -e ssh-listen \ -e tls-listen \ -e ssh-call-home \ -e tls-call-home \ -i ietf-interfaces@2018-02-20.yang -g wheel -p 0660 \ -e if-mib \ -i ietf-ip@2018-02-22.yang -g wheel -p 0660 \ -e ipv6-privacy-autoconf \ -i ietf-network-instance@2019-01-21.yang -g wheel -p 0660 \ -i ietf-netconf-monitoring@2010-10-04.yang -g wheel -p 0660 \ -i ietf-netconf-nmda@2019-01-07.yang -g wheel -p 0660 \ -e origin \ -e with-defaults \ -i ietf-subscribed-notifications@2019-09-09.yang \ -g wheel -p 0660 \ -e encode-xml \ -e replay \ -e subtree \ -e xpath \ -i ietf-yang-push@2019-09-09.yang -g wheel -p 0660 \ -e on-change \ -i ietf-routing@2018-03-13.yang -g wheel -p 0660 \ -i ietf-ipv6-unicast-routing@2018-03-13.yang -g wheel -p 0660 \ -i ietf-ipv4-unicast-routing@2018-03-13.yang -g wheel -p 0660 \ -i ietf-ospf@2022-10-19.yang -g wheel -p 0660 \ -e bfd \ -e explicit-router-id \ -i iana-if-type@2023-01-26.yang -g wheel -p 0660 \ -i iana-hardware@2018-03-13.yang -g wheel -p 0660 \ -i ietf-hardware@2018-03-13.yang -g wheel -p 0660 \ -e hardware-state \ -i infix-hardware@2024-04-25.yang -g wheel -p 0660 \ -i ieee802-dot1q-types@2022-10-29.yang -g wheel -p 0660 \ -i infix-ip@2023-09-14.yang -g wheel -p 0660 \ -i infix-if-type@2024-01-29.yang -g wheel -p 0660 \ -i infix-routing@2024-03-06.yang -g wheel -p 0660 \ -i infix-interfaces@2024-01-15.yang -g wheel -p 0660 \ -e vlan-filtering \ -i ieee802-dot1ab-lldp@2022-03-15.yang -g wheel -p 0660 \ -i infix-lldp@2023-08-23.yang -g wheel -p 0660 \ -i infix-dhcp-client@2024-04-12.yang -g wheel -p 0660 \ -i infix-shell-type@2023-08-21.yang -g wheel -p 0660 \ -i infix-system@2024-04-12.yang -g wheel -p 0660 \ -i infix-services@2024-04-08.yang -g wheel -p 0660 \ -i ieee802-ethernet-interface@2019-06-21.yang -g wheel -p 0660 \ -i infix-ethernet-interface@2024-02-27.yang -g wheel -p 0660 \ -I "${INIT_DATA}" rc=$? # Unlike `sysrepoctl -i` the `-c` command requires separate invocations. # NOTE: we ignore any errors from these at bootstrap since sysrepo may # already enable some of these feature, resulting in error here. # Enable features required by netopeer2 sysrepoctl -c ietf-netconf -g wheel -p 0660 \ -e writable-running \ -e candidate \ -e rollback-on-error \ -e validate \ -e startup \ -e url \ -e xpath \ -e confirmed-commit # Allow wheel group users (admin) to modify NACM and do factory reset sysrepoctl -c ietf-netconf-acm -g wheel -p 0660 sysrepoctl -c ietf-factory-default -g wheel -p 0660 sysrepoctl -c sysrepo-plugind -g wheel -p 0660 # On first boot, install factory-config as startup-config. Due to a # limitation in sysrepo we cannot initialize ietf-netconf-acm, so we # cheat, see sysrepo#3079 chgrp wheel /cfg chmod g+w /cfg if [ ! -f "$STARTUP_CFG" ]; then sysrepocfg -f json -X"$STARTUP_CFG" fi # Clear running-config so we can load startup in the next step echo "{}" > "$INIT_DATA" sysrepocfg -f json -I"$INIT_DATA" -d running exit $rc