Compare commits

...

5 Commits

Author SHA1 Message Date
Mike Reeves
3910e83436 Update Validation 2025-12-15 09:57:42 -05:00
Mike Reeves
26b329a9bd Update Validation 2025-12-15 09:47:57 -05:00
Mike Reeves
506cbc62bb Update Validation 2025-12-15 09:42:38 -05:00
Jason Ertel
285b0e4af9 Merge pull request #15308 from Security-Onion-Solutions/idstools-refactor
Add trailing nl if it doesnt already exist
2025-12-14 15:35:24 -05:00
DefensiveDepth
f9edfd6391 Add trailing nl if it doesnt already exist 2025-12-14 12:03:44 -05:00
4 changed files with 192 additions and 13 deletions

View File

@@ -126,16 +126,130 @@ ADVPILLARFILE=/opt/so/saltstack/local/pillar/minions/adv_$MINION_ID.sls
function getinstallinfo() {
log "INFO" "Getting install info for minion $MINION_ID"
# Pull from file
INSTALLVARS=$(sudo salt "$MINION_ID" cp.get_file_str /opt/so/install.txt --out=newline_values_only)
if [ $? -ne 0 ]; then
local install_json
local install_text
# Reset any prior values so we fail closed if the file is missing keys
MAINIP=""
MNIC=""
NODE_DESCRIPTION=""
ES_HEAP_SIZE=""
PATCHSCHEDULENAME=""
INTERFACE=""
NODETYPE=""
CORECOUNT=""
LSHOSTNAME=""
LSHEAP=""
CPUCORES=""
IDH_MGTRESTRICT=""
IDH_SERVICES=""
# Pull from file (treat it as data, not code)
install_json=$(sudo salt "$MINION_ID" cp.get_file_str /opt/so/install.txt --out=json 2>/dev/null)
if [ $? -ne 0 ] || [ -z "$install_json" ]; then
log "ERROR" "Failed to get install info from $MINION_ID"
return 1
fi
source <(echo $INSTALLVARS)
if [ $? -ne 0 ]; then
log "ERROR" "Failed to source install variables"
install_text=$(jq -r --arg id "$MINION_ID" '.[$id] // empty' <<<"$install_json" 2>/dev/null)
if [ $? -ne 0 ] || [ -z "$install_text" ] || [ "$install_text" == "null" ]; then
log "ERROR" "Failed to parse install info response for $MINION_ID"
return 1
fi
while IFS= read -r line; do
# Trim trailing CR (in case of CRLF files)
line=${line%$'\r'}
# Skip empty/comment lines
[[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
if [[ "$line" =~ ^[[:space:]]*([A-Z0-9_]+)[[:space:]]*=(.*)$ ]]; then
local key="${BASH_REMATCH[1]}"
local value="${BASH_REMATCH[2]}"
# Trim leading whitespace from value (writers shouldn't include it, but tolerate it)
value="${value#"${value%%[![:space:]]*}"}"
# Strip a single layer of surrounding quotes
if [[ "$value" =~ ^\".*\"$ ]]; then
value="${value:1:${#value}-2}"
elif [[ "$value" =~ ^\'.*\'$ ]]; then
value="${value:1:${#value}-2}"
fi
case "$key" in
MAINIP)
[[ "$value" =~ ^[A-Za-z0-9.:-]+$ ]] || { log "ERROR" "Invalid MAINIP in install info"; return 1; }
MAINIP="$value"
;;
MNIC)
[[ "$value" =~ ^[A-Za-z0-9_.:-]+$ ]] || { log "ERROR" "Invalid MNIC in install info"; return 1; }
MNIC="$value"
;;
NODE_DESCRIPTION)
# Allow spaces and common punctuation, but reject control chars
[[ "$value" =~ ^[[:print:]]{0,256}$ ]] || { log "ERROR" "Invalid NODE_DESCRIPTION in install info"; return 1; }
NODE_DESCRIPTION="$value"
;;
ES_HEAP_SIZE)
[[ "$value" =~ ^[0-9]+[kKmMgGtTpPeE]?$ ]] || { log "ERROR" "Invalid ES_HEAP_SIZE in install info"; return 1; }
ES_HEAP_SIZE="$value"
;;
PATCHSCHEDULENAME)
[[ "$value" =~ ^[A-Za-z0-9._-]*$ ]] || { log "ERROR" "Invalid PATCHSCHEDULENAME in install info"; return 1; }
PATCHSCHEDULENAME="$value"
;;
INTERFACE)
[[ "$value" =~ ^[A-Za-z0-9._:,-]+$ ]] || { log "ERROR" "Invalid INTERFACE in install info"; return 1; }
INTERFACE="$value"
;;
NODETYPE)
[[ "$value" =~ ^[A-Z0-9_]+$ ]] || { log "ERROR" "Invalid NODETYPE in install info"; return 1; }
if ! declare -F "create${value}" >/dev/null; then
log "ERROR" "Unknown NODETYPE '$value' in install info"
return 1
fi
NODETYPE="$value"
;;
CORECOUNT)
[[ "$value" =~ ^[0-9]+$ ]] || { log "ERROR" "Invalid CORECOUNT in install info"; return 1; }
CORECOUNT="$value"
;;
LSHOSTNAME)
[[ "$value" =~ ^[A-Za-z0-9.-]+$ ]] || { log "ERROR" "Invalid LSHOSTNAME in install info"; return 1; }
LSHOSTNAME="$value"
;;
LSHEAP)
[[ "$value" =~ ^[0-9]+[kKmMgGtTpPeE]?$ ]] || { log "ERROR" "Invalid LSHEAP in install info"; return 1; }
LSHEAP="$value"
;;
CPUCORES)
[[ "$value" =~ ^[0-9]+$ ]] || { log "ERROR" "Invalid CPUCORES in install info"; return 1; }
CPUCORES="$value"
;;
IDH_MGTRESTRICT)
[[ "$value" == "True" || "$value" == "False" ]] || { log "ERROR" "Invalid IDH_MGTRESTRICT in install info"; return 1; }
IDH_MGTRESTRICT="$value"
;;
IDH_SERVICES)
[[ "$value" =~ ^[[:print:]]{0,512}$ ]] || { log "ERROR" "Invalid IDH_SERVICES in install info"; return 1; }
IDH_SERVICES="$value"
;;
*)
# Ignore unknown keys for forward compatibility
:
;;
esac
else
log "ERROR" "Invalid install info line from $MINION_ID"
return 1
fi
done <<<"$install_text"
if [[ -z "$NODETYPE" || -z "$MAINIP" || -z "$MNIC" ]]; then
log "ERROR" "Missing required install variables from $MINION_ID"
return 1
fi
}
@@ -996,7 +1110,7 @@ function setupMinionFiles() {
log "INFO" "Setting up minion files for $MINION_ID"
# Check to see if nodetype is set
if [ -z $NODETYPE ]; then
if [ -z "$NODETYPE" ]; then
error_msg="No node type specified"
log "ERROR" "$error_msg"
echo "$error_msg"
@@ -1018,7 +1132,12 @@ function setupMinionFiles() {
fi
# Create node-specific configuration
create$NODETYPE || return 1
local create_func="create${NODETYPE}"
if ! declare -F "$create_func" >/dev/null; then
log "ERROR" "Unknown node type '$NODETYPE'"
return 1
fi
"$create_func" || return 1
# Ensure proper ownership after all content is written
ensure_socore_ownership || return 1

View File

@@ -1174,11 +1174,12 @@ hash_normalized_file() {
return 1
fi
sed -E \
# Ensure trailing newline for consistent hashing regardless of source file
{ sed -E \
-e 's/^[[:space:]]+//; s/[[:space:]]+$//' \
-e '/^$/d' \
-e 's|--url=http://[^:]+:7788|--url=http://MANAGER:7788|' \
"$file" | sha256sum | awk '{print $1}'
"$file"; echo; } | sed '/^$/d' | sha256sum | awk '{print $1}'
}
# Known-default hashes for so-rule-update (ETOPEN ruleset)

View File

@@ -1504,7 +1504,13 @@ networking_needful() {
if [[ $reinit_networking ]] || ! [[ -f $net_init_file ]]; then
collect_hostname
fi
[[ ! ( $is_eval || $is_import ) ]] && whiptail_node_description
if [[ ! ( $is_eval || $is_import ) ]]; then
whiptail_node_description
while [[ "$NODE_DESCRIPTION" =~ [[:cntrl:]] ]]; do
whiptail_error_message "Node description cannot contain control characters. Please enter a new description."
whiptail_node_description
done
fi
if [[ $reinit_networking ]] || ! [[ -f $net_init_file ]]; then
network_init_whiptail
else
@@ -1756,6 +1762,50 @@ backup_dir() {
}
drop_install_options() {
# Ensure values written to install.txt won't later fail manager-side parsing in so-minion
strip_control_chars() {
# bash: remove ASCII control characters (incl. newlines/tabs/ESC)
printf '%s' "$1" | tr -d '[:cntrl:]'
}
validate_install_txt_vars() {
# Sanitize first (fail closed if still invalid)
MAINIP="$(strip_control_chars "$MAINIP")"
MNIC="$(strip_control_chars "$MNIC")"
NODE_DESCRIPTION="$(strip_control_chars "$NODE_DESCRIPTION")"
ES_HEAP_SIZE="$(strip_control_chars "$ES_HEAP_SIZE")"
PATCHSCHEDULENAME="$(strip_control_chars "$PATCHSCHEDULENAME")"
INTERFACE="$(strip_control_chars "$INTERFACE")"
HOSTNAME="$(strip_control_chars "$HOSTNAME")"
LS_HEAP_SIZE="$(strip_control_chars "$LS_HEAP_SIZE")"
IDH_MGTRESTRICT="$(strip_control_chars "$IDH_MGTRESTRICT")"
IDH_SERVICES="$(strip_control_chars "$IDH_SERVICES")"
valid_ip4 "$MAINIP" || return 1
[[ "$MNIC" =~ ^[A-Za-z0-9_.:-]+$ ]] || return 1
[[ "$NODE_DESCRIPTION" =~ ^[[:print:]]{0,256}$ ]] || return 1
[[ "$ES_HEAP_SIZE" =~ ^[0-9]+[kKmMgGtTpPeE]?$ ]] || return 1
[[ "$PATCHSCHEDULENAME" =~ ^[A-Za-z0-9._-]*$ ]] || return 1
[[ "$INTERFACE" =~ ^[A-Za-z0-9._:,-]+$ ]] || return 1
valid_hostname "$HOSTNAME" || return 1
[[ "$LS_HEAP_SIZE" =~ ^[0-9]+[kKmMgGtTpPeE]?$ ]] || return 1
[[ "$lb_procs" =~ ^[0-9]+$ ]] || return 1
[[ "$num_cpu_cores" =~ ^[0-9]+$ ]] || return 1
[[ -z "$IDH_MGTRESTRICT" || "$IDH_MGTRESTRICT" == "True" || "$IDH_MGTRESTRICT" == "False" ]] || return 1
[[ -z "$IDH_SERVICES" || "$IDH_SERVICES" =~ ^[[:print:]]{0,512}$ ]] || return 1
return 0
}
if ! validate_install_txt_vars; then
if declare -F whiptail_error_message >/dev/null; then
whiptail_error_message "One or more setup values were invalid and would cause the manager to reject this node when adding it. Please re-run setup and verify hostname, management IP/interface, and node description."
else
echo "Error: invalid setup values detected; refusing to write /opt/so/install.txt"
fi
return 1
fi
# Drop the install Variable
echo "MAINIP=$MAINIP" > /opt/so/install.txt
echo "MNIC=$MNIC" >> /opt/so/install.txt

View File

@@ -903,8 +903,9 @@ whiptail_management_nic() {
local exitstatus=$?
whiptail_check_exitstatus $exitstatus
while [ -z "$MNIC" ]
while [ -z "$MNIC" ] || [[ "$MNIC" =~ [[:cntrl:]] ]] || [[ ! "$MNIC" =~ ^[A-Za-z0-9_.:-]+$ ]]
do
whiptail_invalid_input
MNIC=$(whiptail --title "$whiptail_title" --menu "Please select the NIC you would like to use for management.\n\nUse the arrow keys to move around and the Enter key to select." 22 75 12 "${nic_list_management[@]}" 3>&1 1>&2 2>&3 )
local exitstatus=$?
whiptail_check_exitstatus $exitstatus
@@ -1098,6 +1099,14 @@ whiptail_node_description() {
local exitstatus=$?
whiptail_check_exitstatus $exitstatus
while [[ "$NODE_DESCRIPTION" =~ [[:cntrl:]] ]]; do
whiptail_error_message "Node description cannot contain control characters. Please enter a new description."
NODE_DESCRIPTION=$(whiptail --title "$whiptail_title" \
--inputbox "Enter a short description for the node or press ENTER to leave blank:" 10 75 3>&1 1>&2 2>&3)
local exitstatus=$?
whiptail_check_exitstatus $exitstatus
done
}
whiptail_ntp_ask() {