diff --git a/salt/common/tools/sbin/so-common b/salt/common/tools/sbin/so-common index 812c1bb10..4e6580ae1 100755 --- a/salt/common/tools/sbin/so-common +++ b/salt/common/tools/sbin/so-common @@ -291,6 +291,20 @@ download_and_verify() { fi } +# check if container with name is running and optionally stop it +docker_check_running() { + # show running containers, only names + if docker ps --format '{{.Names}}' | grep -q "^so-${1}$"; then + if [[ "$2" == "--stop" ]]; then + docker stop "so-${1}" + fi + + return 0 + else + return 1 + fi +} + elastic_license() { read -r -d '' message <<- EOM diff --git a/salt/common/tools/sbin/so-kernel-upgrade b/salt/common/tools/sbin/so-kernel-upgrade new file mode 100755 index 000000000..46d471051 --- /dev/null +++ b/salt/common/tools/sbin/so-kernel-upgrade @@ -0,0 +1,57 @@ +#!/bin/bash +# +# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one +# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at +# https://securityonion.net/license; you may not use this file except in compliance with the +# Elastic License 2.0. +# +# so-kernel-upgrade — switch the boot default to the installed UEK8 (6.x) kernel. +# +# Security Onion is moving off the EL9 stock kernel / UEK7 (5.x) onto UEK8 (6.x). +# Installing the kernel-uek-core package adds a UEK8 boot entry but does NOT make it the +# default: kernel-install/grubby only auto-promote a new kernel within the running +# kernel's flavor lineage, and we're crossing from a 5.x kernel to the new 6.x UEK flavor. +# So even with UPDATEDEFAULT=yes and DEFAULTKERNEL=kernel-uek-core the box keeps booting +# the old kernel. This tool finds the newest installed 6.x UEK kernel and makes it the +# GRUB default via grubby so the next boot comes up on UEK8. +# +# Idempotent: if the UEK8 kernel is already the default it does nothing. It only sets the +# boot default; it does NOT reboot — the admin reboots the node on their own schedule. + +log() { echo "[so-kernel-upgrade] $*"; } + +[ "$(id -u)" -eq 0 ] || { log "must run as root"; exit 1; } +command -v grubby >/dev/null 2>&1 || { log "grubby not found"; exit 1; } + +# Newest installed UEK8 (6.x) kernel known to the bootloader. UEK8 vmlinuz paths look like +# /boot/vmlinuz-6.12.0-203.76.7.5.el9uek.x86_64; the 5.x UEK7 and 5.14 RHCK won't match. +target="$(grubby --info=ALL 2>/dev/null \ + | sed -n 's/^kernel="\(.*\)"$/\1/p' \ + | grep -E '/vmlinuz-6\.[0-9]+.*uek' \ + | sort -V | tail -1)" + +if [ -z "$target" ]; then + log "no installed 6.x UEK (UEK8) kernel found — confirm the kernel repo is assigned and" + log "'dnf update' has installed kernel-uek-core. Nothing to do." + exit 0 +fi + +current="$(grubby --default-kernel 2>/dev/null)" +if [ "$current" = "$target" ]; then + log "UEK8 kernel is already the boot default: $target" + exit 0 +fi + +log "current default kernel: ${current:-unknown}" +log "switching boot default to UEK8 kernel: $target" +grubby --set-default="$target" || { log "ERROR: grubby --set-default failed for $target"; exit 1; } + +# Verify the change actually took before claiming success. +now="$(grubby --default-kernel 2>/dev/null)" +if [ "$now" != "$target" ]; then + log "ERROR: default kernel is still '${now:-unknown}' after set-default" + exit 1 +fi + +log "boot default is now $target" +log "REBOOT REQUIRED to start using the UEK8 kernel (currently running $(uname -r))." diff --git a/salt/common/tools/sbin/so-restart b/salt/common/tools/sbin/so-restart index 7345078b8..14747d134 100755 --- a/salt/common/tools/sbin/so-restart +++ b/salt/common/tools/sbin/so-restart @@ -5,27 +5,41 @@ # https://securityonion.net/license; you may not use this file except in compliance with the # Elastic License 2.0. - - -# Usage: so-restart kibana | playbook - . /usr/sbin/so-common -if [ $# -ge 1 ]; then +usage() { + echo "Usage: $0 [args]" + echo "" + echo "Supported args:" + echo " --force | -f Force stop all Salt jobs before starting component." + echo "" + echo "Examples:" + echo " $0 kibana Restart Kibana" + echo " $0 kibana --force Force stop all Salt jobs before restarting Kibana" + exit 1 +} - echo $banner - printf "Restarting $1...\n\nThis could take a while if another Salt job is running. \nRun this command with --force to stop all Salt jobs before proceeding.\n" - echo $banner - - if [ "$2" = "--force" ]; then - printf "\nForce-stopping all Salt jobs before proceeding\n\n" - salt-call saltutil.kill_all_jobs - fi - - case $1 in - "elastic-fleet") docker stop so-elastic-fleet && docker rm so-elastic-fleet && salt-call state.apply elasticfleet queue=True;; - *) docker stop so-$1 ; docker rm so-$1 ; salt-call state.apply $1 queue=True;; - esac -else - echo -e "\nPlease provide an argument by running like so-restart $component, or by using the component-specific script.\nEx. so-restart logstash, or so-logstash-restart\n" +if [[ $# -lt 1 ]]; then + usage fi + +#shellcheck disable=SC2154 +echo "$banner" +printf "Restarting %s...\n\nThis could take a while if another Salt job is running. \nRun this command with --force to stop all Salt jobs before proceeding.\n" "$1" +echo "$banner" +if [[ "$2" = "--force" ]] || [[ "$2" = "-f" ]]; then + printf "\nForce-stopping all Salt jobs before proceeding\n\n" + salt-call saltutil.kill_all_jobs +fi +case $1 in + "elastic-fleet"|"elasticfleet") + docker_check_running "elastic-fleet" "--stop" + docker rm "so-elastic-fleet" 2> /dev/null + salt-call state.apply elasticfleet queue=True + ;; + *) + docker_check_running "$1" "--stop" + docker rm "so-${1}" 2> /dev/null + salt-call state.apply "$1" queue=True + ;; +esac diff --git a/salt/common/tools/sbin/so-start b/salt/common/tools/sbin/so-start index 1a312a94d..a5c66ffe7 100755 --- a/salt/common/tools/sbin/so-start +++ b/salt/common/tools/sbin/so-start @@ -5,27 +5,54 @@ # https://securityonion.net/license; you may not use this file except in compliance with the # Elastic License 2.0. - - -# Usage: so-start all | kibana | playbook - +# shellcheck disable=SC1091 . /usr/sbin/so-common -if [ $# -ge 1 ]; then - echo $banner - printf "Starting $1...\n\nThis could take a while if another Salt job is running. \nRun this command with --force to stop all Salt jobs before proceeding.\n" - echo $banner +usage() { + echo "Usage: $0 [args]" + echo "" + echo "Supported args:" + echo " --force | -f Force stop all Salt jobs before starting component." + echo "" + echo "Examples:" + echo " $0 kibana Start Kibana" + echo " $0 kibana --force Force stop all Salt jobs before starting Kibana" + exit 1 +} - if [ "$2" = "--force" ]; then - printf "\nForce-stopping all Salt jobs before proceeding\n\n" - salt-call saltutil.kill_all_jobs - fi - - case $1 in - "all") salt-call state.highstate queue=True;; - "elastic-fleet") if docker ps | grep -q so-$1; then printf "\n$1 is already running!\n\n"; else docker rm so-$1 >/dev/null 2>&1 ; salt-call state.apply elasticfleet queue=True; fi ;; - *) if docker ps | grep -E -q '^so-$1$'; then printf "\n$1 is already running\n\n"; else docker rm so-$1 >/dev/null 2>&1 ; salt-call state.apply $1 queue=True; fi ;; - esac -else - echo -e "\nPlease provide an argument by running like so-start $component, or by using the component-specific script.\nEx. so-start logstash, or so-logstash-start\n" +if [[ $# -lt 1 ]]; then + usage fi + +#shellcheck disable=SC2154 +echo "$banner" +printf "Starting %s...\n\nThis could take a while if another Salt job is running. \nRun this command with --force to stop all Salt jobs before proceeding.\n" "$1" +echo "$banner" +if [[ "$2" = "--force" ]] || [[ "$2" == "-f" ]]; then + printf "\nForce-stopping all Salt jobs before proceeding\n\n" + salt-call saltutil.kill_all_jobs +fi + +case "$1" in + "all") + salt-call state.highstate queue=True + ;; + "elastic-fleet"|"elasticfleet") + if docker_check_running "elastic-fleet"; then + printf "\nso-%s is already running!\n\n" "elastic-fleet" + /usr/sbin/so-status + else + docker rm "so-elastic-fleet" 2> /dev/null + salt-call state.apply elasticfleet queue=True + fi + ;; + *) + if docker_check_running "$1"; then + printf "\nso-%s is already running\n\n" "$1" + /usr/sbin/so-status + else + docker rm "so-${1}" 2> /dev/null + salt-call state.apply "$1" queue=True + fi + ;; +esac diff --git a/salt/common/tools/sbin/so-stop b/salt/common/tools/sbin/so-stop index 32e24f83a..d036a7b63 100755 --- a/salt/common/tools/sbin/so-stop +++ b/salt/common/tools/sbin/so-stop @@ -5,21 +5,33 @@ # https://securityonion.net/license; you may not use this file except in compliance with the # Elastic License 2.0. - - -# Usage: so-stop kibana | playbook | thehive - +# shellcheck disable=SC1091 . /usr/sbin/so-common -if [ $# -ge 1 ]; then - echo $banner - printf "Stopping $1...\n" - echo $banner +usage() { + echo "Usage: $0 " + echo "" + echo "Examples:" + echo " $0 kibana Stop Kibana" + exit 1 +} - case $1 in - *) docker stop so-$1 ; docker rm so-$1 ;; - esac -else - echo -e "\nPlease provide an argument by running like so-stop $component, or by using the component-specific script.\nEx. so-stop logstash, or so-logstash-stop\n" +if [[ $# -lt 1 ]]; then + usage fi + +#shellcheck disable=SC2154 +echo "$banner" +printf "Stopping %s...\n" "$1" +echo "$banner" +case $1 in + "elasticfleet"|"elastic-fleet") + docker_check_running "elastic-fleet" "--stop" + docker rm "so-elastic-fleet" 2> /dev/null + ;; + *) + docker_check_running "$1" "--stop" + docker rm "so-${1}" 2> /dev/null + ;; +esac diff --git a/salt/elasticsearch/files/ingest/zeek.ssl b/salt/elasticsearch/files/ingest/zeek.ssl index 0bd6fedb2..80a7b12da 100644 --- a/salt/elasticsearch/files/ingest/zeek.ssl +++ b/salt/elasticsearch/files/ingest/zeek.ssl @@ -5,6 +5,7 @@ { "remove": { "field": ["host"], "ignore_failure": true } }, { "json": { "field": "message", "target_field": "message2", "ignore_failure": true } }, { "rename": { "field": "message2.version", "target_field": "ssl.version", "ignore_missing": true } }, + { "set": { "description": "Set transport for the community_id processor", "if": "ctx.ssl?.version == null || !ctx.ssl.version.startsWith('DTLS')", "field": "network.transport", "value": "tcp", "ignore_failure": true } }, { "rename": { "field": "message2.cipher", "target_field": "ssl.cipher", "ignore_missing": true } }, { "rename": { "field": "message2.curve", "target_field": "ssl.curve", "ignore_missing": true } }, { "rename": { "field": "message2.server_name", "target_field": "ssl.server_name", "ignore_missing": true } }, diff --git a/salt/manager/files/mirror-kernel.txt b/salt/manager/files/mirror-kernel.txt new file mode 100644 index 000000000..1d9ce75d2 --- /dev/null +++ b/salt/manager/files/mirror-kernel.txt @@ -0,0 +1,2 @@ +https://repo.securityonion.net/file/so-repo/prod/3/oracle/9-uek8 +https://repo-alt.securityonion.net/prod/3/oracle/9-uek8 diff --git a/salt/manager/files/repodownload.conf b/salt/manager/files/repodownload.conf index 3c156a9db..67ae4b121 100644 --- a/salt/manager/files/repodownload.conf +++ b/salt/manager/files/repodownload.conf @@ -10,4 +10,9 @@ keepcache=0 name=Security Onion Repo repo mirrorlist=file:///opt/so/conf/reposync/mirror.txt enabled=1 -gpgcheck=1 \ No newline at end of file +gpgcheck=1 +[securityonionkernel] +name=Security Onion Repo repo +mirrorlist=file:///opt/so/conf/reposync/mirror-kernel.txt +enabled=1 +gpgcheck=1 diff --git a/salt/manager/init.sls b/salt/manager/init.sls index ef2428492..a74d16ff2 100644 --- a/salt/manager/init.sls +++ b/salt/manager/init.sls @@ -87,6 +87,28 @@ repo_dir: - group - show_changes: False +kernelrepo_dir: + file.directory: + - name: /nsm/kernelrepo + - user: socore + - group: socore + - recurse: + - user + - group + - show_changes: False + +# Ensure /nsm/kernelrepo is always a valid (if empty) repo before it is ever assigned to +# a client. Without repodata/repomd.xml an enabled file:///nsm/kernelrepo repo makes every +# dnf operation fail; so-repo-sync only populates it after the highstate, so seed an empty +# repo here. Only runs when repodata is missing, so it won't clobber a synced repo. +kernelrepo_init_empty: + cmd.run: + - name: createrepo /nsm/kernelrepo + - unless: 'test -e /nsm/kernelrepo/repodata/repomd.xml' + - require: + - file: kernelrepo_dir + - pkg: install_createrepo + manager_sbin: file.recurse: - name: /usr/sbin @@ -123,6 +145,13 @@ so-repo-mirrorlist: - user: socore - group: socore +so-repo-kernel-mirrorlist: + file.managed: + - name: /opt/so/conf/reposync/mirror-kernel.txt + - source: salt://manager/files/mirror-kernel.txt + - user: socore + - group: socore + so-repo-sync: {% if MANAGERMERGED.reposync.enabled %} cron.present: diff --git a/salt/manager/tools/sbin/so-repo-sync b/salt/manager/tools/sbin/so-repo-sync index a0393a36b..6c1b9d509 100755 --- a/salt/manager/tools/sbin/so-repo-sync +++ b/salt/manager/tools/sbin/so-repo-sync @@ -10,5 +10,16 @@ NOROOT=1 set -e curl --retry 5 --retry-delay 60 -A "reposync/$(sync_options)" https://sigs.securityonion.net/checkup --output /tmp/checkup + dnf reposync --norepopath -g --delete -m -c /opt/so/conf/reposync/repodownload.conf --repoid=securityonionsync --download-metadata -p /nsm/repo/ createrepo /nsm/repo + +# The kernel repo section is deployed to repodownload.conf by the manager highstate, which +# runs AFTER this script during soup. On the first upgrade to a kernel-aware version the +# on-disk config still predates the section, so guard on its presence to avoid dnf's +# "Unknown repo: 'securityonionkernel'" aborting the sync (set -e). The next sync after the +# highstate deploys the section will pick it up. +if grep -q '^\[securityonionkernel\]' /opt/so/conf/reposync/repodownload.conf; then + dnf reposync --norepopath -g --delete -m -c /opt/so/conf/reposync/repodownload.conf --repoid=securityonionkernel --download-metadata -p /nsm/kernelrepo/ + createrepo /nsm/kernelrepo +fi diff --git a/salt/nginx/enabled.sls b/salt/nginx/enabled.sls index c50ad8f8f..3fa99eae2 100644 --- a/salt/nginx/enabled.sls +++ b/salt/nginx/enabled.sls @@ -60,6 +60,7 @@ so-nginx: - /opt/so/conf/navigator/layers/:/opt/socore/html/navigator/assets/so:ro - /opt/so/conf/navigator/config.json:/opt/socore/html/navigator/assets/config.json:ro - /nsm/repo:/opt/socore/html/repo:ro + - /nsm/kernelrepo:/opt/socore/html/kernelrepo:ro - /nsm/rules:/nsm/rules:ro {% if NGINXMERGED.external_suricata %} - /opt/so/rules/nids/suri:/surirules:ro diff --git a/salt/nginx/etc/nginx.conf b/salt/nginx/etc/nginx.conf index 8150265f5..b7a70da2b 100644 --- a/salt/nginx/etc/nginx.conf +++ b/salt/nginx/etc/nginx.conf @@ -323,6 +323,16 @@ http { autoindex_localtime on; } + location /kernelrepo/ { + allow all; + sendfile on; + sendfile_max_chunk 1m; + autoindex on; + autoindex_exact_size off; + autoindex_format html; + autoindex_localtime on; + } + location /influxdb/ { auth_request /auth/sessions/whoami; rewrite /influxdb/api/(.*) /api/$1 break; diff --git a/salt/repo/client/oracle.sls b/salt/repo/client/oracle.sls index 70f529830..bf0a02751 100644 --- a/salt/repo/client/oracle.sls +++ b/salt/repo/client/oracle.sls @@ -6,6 +6,10 @@ {% from 'repo/client/map.jinja' import REPOPATH with context %} {% from 'vars/globals.map.jinja' import GLOBALS %} +{% import_yaml 'salt/minion.defaults.yaml' as saltversion %} +{% set saltversion = saltversion.salt.minion.version %} +{% set INSTALLEDSALTVERSION = grains.saltversion %} + {% set role = grains.id.split('_') | last %} {% set MANAGER = salt['grains.get']('master') %} {% if grains['os'] == 'OEL' %} @@ -57,6 +61,32 @@ so_repo: - enabled: 1 - gpgcheck: 1 +# Only assign the kernel repo once this node's running salt matches the version this +# SO release ships. During a soup the grid is mid-salt-upgrade; gating here keeps the +# UEK8 kernel repo (and the kernel update it enables) from activating until the node is +# fully on the target salt, the same way other states defer across the upgrade window. +{% if saltversion | string == INSTALLEDSALTVERSION | string %} +so_kernel_repo: + pkgrepo.managed: + - name: securityonionkernel + - humanname: Security Onion Kernel Repo + {% if GLOBALS.is_manager %} + - baseurl: file:///nsm/kernelrepo/ + {% else %} + - baseurl: https://{{ GLOBALS.repo_host }}/kernelrepo + {% endif %} + - enabled: 1 + - gpgcheck: 1 + # Supplementary kernel repo: tolerate it being empty/unreachable (e.g. before the + # manager has populated /nsm/kernelrepo) so a missing repomd.xml can't make every + # dnf/pkg operation on the grid fail. + - skip_if_unavailable: 1 + # Only assign the kernel repo once physical NIC names are pinned by MAC, so the + # UEK8 kernel update can't renumber interfaces SO binds by name (see pin_nic_names + # in salt/common/init.sls, which drops this marker via /usr/sbin/so-nic-pin). + - onlyif: 'test -e /opt/so/state/nic_names_pinned' +{% endif %} + {% endif %} # TODO: Add a pillar entry for custom repos diff --git a/setup/so-functions b/setup/so-functions index 8859aef97..8ac53fd95 100755 --- a/setup/so-functions +++ b/setup/so-functions @@ -886,6 +886,7 @@ create_repo() { title "Create the repo directory" logCmd "dnf -y install yum-utils createrepo_c" logCmd "createrepo /nsm/repo" + logCmd "createrepo /nsm/kernelrepo" } @@ -1812,6 +1813,16 @@ securityonion_repo() { echo "mirrorlist=file:///etc/yum/mirror.txt" >> /etc/yum.repos.d/securityonion.repo echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo + echo "https://repo.securityonion.net/file/so-repo/prod/3/oracle/9-uek8" > /etc/yum/mirror-kernel.txt + echo "https://so-repo-east.s3.us-east-005.backblazeb2.com/prod/3/oracle/9-uek8" >> /etc/yum/mirror-kernel.txt + echo "[securityonionkernel]" > /etc/yum.repos.d/securityonionkernel.repo + echo "name=Security Onion Kernel Repo repo" >> /etc/yum.repos.d/securityonionkernel.repo + echo "mirrorlist=file:///etc/yum/mirror-kernel.txt" >> /etc/yum.repos.d/securityonionkernel.repo + echo "enabled=1" >> /etc/yum.repos.d/securityonionkernel.repo + echo "gpgcheck=1" >> /etc/yum.repos.d/securityonionkernel.repo + # Supplementary kernel repo: tolerate it being empty/unreachable so a missing + # repomd.xml can't make every dnf operation fail before the repo is populated. + echo "skip_if_unavailable=1" >> /etc/yum.repos.d/securityonionkernel.repo logCmd "dnf repolist" else echo "[securityonion]" > /etc/yum.repos.d/securityonion.repo @@ -1820,6 +1831,13 @@ securityonion_repo() { echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo echo "sslverify=0" >> /etc/yum.repos.d/securityonion.repo + echo "[securityonionkernel]" > /etc/yum.repos.d/securityonionkernel.repo + echo "name=Security Onion Kernel Repo" >> /etc/yum.repos.d/securityonionkernel.repo + echo "baseurl=https://$MSRV/kernelrepo" >> /etc/yum.repos.d/securityonionkernel.repo + echo "enabled=1" >> /etc/yum.repos.d/securityonionkernel.repo + echo "gpgcheck=1" >> /etc/yum.repos.d/securityonionkernel.repo + echo "sslverify=0" >> /etc/yum.repos.d/securityonionkernel.repo + echo "skip_if_unavailable=1" >> /etc/yum.repos.d/securityonionkernel.repo logCmd "dnf repolist" fi elif [[ ! $waitforstate ]]; then @@ -1829,12 +1847,25 @@ securityonion_repo() { echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo echo "sslverify=0" >> /etc/yum.repos.d/securityonion.repo + echo "[securityonionkernel]" > /etc/yum.repos.d/securityonionkernel.repo + echo "name=Security Onion Kernel Repo" >> /etc/yum.repos.d/securityonionkernel.repo + echo "baseurl=https://$MSRV/kernelrepo" >> /etc/yum.repos.d/securityonionkernel.repo + echo "enabled=1" >> /etc/yum.repos.d/securityonionkernel.repo + echo "gpgcheck=1" >> /etc/yum.repos.d/securityonionkernel.repo + echo "sslverify=0" >> /etc/yum.repos.d/securityonionkernel.repo + echo "skip_if_unavailable=1" >> /etc/yum.repos.d/securityonionkernel.repo elif [[ $waitforstate ]]; then echo "[securityonion]" > /etc/yum.repos.d/securityonion.repo echo "name=Security Onion Repo" >> /etc/yum.repos.d/securityonion.repo echo "baseurl=file:///nsm/repo/" >> /etc/yum.repos.d/securityonion.repo echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo + echo "[securityonionkernel]" > /etc/yum.repos.d/securityonionkernel.repo + echo "name=Security Onion Kernel Repo" >> /etc/yum.repos.d/securityonionkernel.repo + echo "baseurl=file:///nsm/kernelrepo/" >> /etc/yum.repos.d/securityonionkernel.repo + echo "enabled=1" >> /etc/yum.repos.d/securityonionkernel.repo + echo "gpgcheck=1" >> /etc/yum.repos.d/securityonionkernel.repo + echo "skip_if_unavailable=1" >> /etc/yum.repos.d/securityonionkernel.repo fi logCmd "dnf repolist all" if [[ $waitforstate ]]; then @@ -1850,9 +1881,12 @@ repo_sync_local() { # Sync the repo from the SO repo locally. info "Adding Repo Download Configuration" mkdir -p /nsm/repo + mkdir -p /nsm/kernelrepo mkdir -p /opt/so/conf/reposync/cache echo "https://repo.securityonion.net/file/so-repo/prod/3/oracle/9" > /opt/so/conf/reposync/mirror.txt echo "https://repo-alt.securityonion.net/prod/3/oracle/9" >> /opt/so/conf/reposync/mirror.txt + echo "https://repo.securityonion.net/file/so-repo/prod/3/oracle/9-uek8" > /opt/so/conf/reposync/mirror-kernel.txt + echo "https://repo-alt.securityonion.net/prod/3/oracle/9-uek8" >> /opt/so/conf/reposync/mirror-kernel.txt echo "[main]" > /opt/so/conf/reposync/repodownload.conf echo "gpgcheck=1" >> /opt/so/conf/reposync/repodownload.conf echo "installonly_limit=3" >> /opt/so/conf/reposync/repodownload.conf @@ -1866,12 +1900,18 @@ repo_sync_local() { echo "mirrorlist=file:///opt/so/conf/reposync/mirror.txt" >> /opt/so/conf/reposync/repodownload.conf echo "enabled=1" >> /opt/so/conf/reposync/repodownload.conf echo "gpgcheck=1" >> /opt/so/conf/reposync/repodownload.conf + echo "[securityonionkernel]" >> /opt/so/conf/reposync/repodownload.conf + echo "name=Security Onion Kernel Repo repo" >> /opt/so/conf/reposync/repodownload.conf + echo "mirrorlist=file:///opt/so/conf/reposync/mirror-kernel.txt" >> /opt/so/conf/reposync/repodownload.conf + echo "enabled=1" >> /opt/so/conf/reposync/repodownload.conf + echo "gpgcheck=1" >> /opt/so/conf/reposync/repodownload.conf logCmd "dnf repolist" if [[ ! $is_airgap ]]; then curl --retry 5 --retry-delay 60 -A "netinstall/$SOVERSION/$OS/$(uname -r)/1" https://sigs.securityonion.net/checkup --output /tmp/install retry 5 60 "dnf reposync --norepopath -g --delete -m -c /opt/so/conf/reposync/repodownload.conf --repoid=securityonionsync --download-metadata -p /nsm/repo/" >> "$setup_log" 2>&1 || fail_setup + retry 5 60 "dnf reposync --norepopath -g --delete -m -c /opt/so/conf/reposync/repodownload.conf --repoid=securityonionkernel --download-metadata -p /nsm/kernelrepo/" >> "$setup_log" 2>&1 || fail_setup # After the download is complete run createrepo create_repo fi @@ -2228,6 +2268,13 @@ update_sudoers_for_testing() { } update_packages() { + # Pin physical NIC names by MAC BEFORE pulling packages, so the UEK8 kernel that + # the update below installs can't renumber the interfaces SO binds by name. Doing + # it here (instead of waiting for the common highstate) also drops the + # /opt/so/state/nic_names_pinned marker that gates the kernel repo, so the kernel + # repo is assigned on the very first highstate and the kernel isn't downgraded and + # then re-upgraded. Run-once: so-nic-pin no-ops if the marker already exists. + logCmd "bash ../salt/common/tools/sbin/so-nic-pin" logCmd "dnf repolist" logCmd "dnf -y update --allowerasing --exclude=salt*,docker*,containerd*" RMREPOFILES=("oracle-linux-ol9.repo" "uek-ol9.repo" "virt-ol9.repo")