From 3afbb17fbea43b7d78b3c070b82cc9f80920086a Mon Sep 17 00:00:00 2001 From: dingenbohs Date: Mon, 3 Nov 2025 14:58:33 +0000 Subject: [PATCH] Add 'k3os/toolbox.sh' --- k3os/toolbox.sh | 259 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 259 insertions(+) create mode 100644 k3os/toolbox.sh diff --git a/k3os/toolbox.sh b/k3os/toolbox.sh new file mode 100644 index 0000000..2a4e865 --- /dev/null +++ b/k3os/toolbox.sh @@ -0,0 +1,259 @@ +#!/bin/sh +# k3os-config.sh +# A configuration utility for k3os environments (BusyBox/Alpine compatible) + +# --- Global Variables and Constants --- + +CONNMAN_CONFIG="/var/lib/connman/default.config" +HOSTNAME_FILE="/var/lib/rancher/k3os/hostname" +SSHD_CONFIG="/etc/ssh/sshd_config" + +# Get current user's home directory for Kubeconfig +USER_HOME=$(getent passwd "$(whoami)" | cut -d: -f6) +KUBECONFIG_PATH="$USER_HOME/.kube/config" + +# --- Utility Functions --- + +# Function to display system status indicators +show_status() { + printf "\n" + printf "\033[44;1m--- K3OS Node Status ---\033[0m\n" + + # 1. Hostname + CURRENT_HOSTNAME=$(hostname) + + # 2. SSHD Password Auth Status (Requires reading a root-owned file, so we use sudo or check existence) + SSHD_STATUS="\033[31mError (Need Sudo)\033[0m" + if [ -f "$SSHD_CONFIG" ] && grep -q '^PasswordAuthentication yes' "$SSHD_CONFIG" 2>/dev/null; then + SSHD_STATUS="\033[32mEnabled\033[0m" + elif [ -f "$SSHD_CONFIG" ]; then + SSHD_STATUS="\033[33mDisabled\033[0m" + fi + + # 3. Static IP Configuration Check (from Connman config) + STATIC_IP="" + CONFIG_IFACE="" + # Use 'sudo cat' to read the root-owned config file + if sudo test -f "$CONNMAN_CONFIG"; then + CONNMAN_CONTENT=$(sudo cat "$CONNMAN_CONFIG" 2>/dev/null) + CONFIG_IFACE=$(echo "$CONNMAN_CONTENT" | grep '^\[service_' | head -n 1 | sed -e 's/^\[service_\(.*\)\].*$/\1/' | tr -d '[]') + STATIC_IP=$(echo "$CONNMAN_CONTENT" | grep -oE 'IPv4 = ([0-9]{1,3}\.){3}[0-9]{1,3}' 2>/dev/null | head -n 1 | awk '{print $3}' | cut -d'/' -f1) + fi + + # 4. Current/Active IP and DHCP status - Use the default route interface + ACTIVE_IFACE=$(ip route get 1.1.1.1 | grep -o 'dev [^ ]*' | awk '{print $2}' | head -n 1) + if [ -z "$ACTIVE_IFACE" ]; then + ACTIVE_IFACE="eth0" + fi + + CURRENT_IP=$(ip addr show "$ACTIVE_IFACE" 2>/dev/null | grep 'inet ' | awk '{print $2}' | cut -d/ -f1 | head -n 1) + + DHCP_STATUS="\033[31mN/A\033[0m" + IP_ADDRESS_STATUS="\033[31mNo Active Link\033[0m" + + if [ -n "$CURRENT_IP" ]; then + IP_ADDRESS_STATUS="$CURRENT_IP (\033[36m$ACTIVE_IFACE\033[0m)" + if [ -n "$STATIC_IP" ] && [ "$STATIC_IP" = "$CURRENT_IP" ]; then + DHCP_STATUS="\033[33mNo\033[0m (\033[36mStatic Configured\033[0m: $CONFIG_IFACE)" + else + DHCP_STATUS="\033[32mYes\033[0m (or Link-Local)" + fi + elif [ -n "$STATIC_IP" ]; then + IP_ADDRESS_STATUS="\033[33mStatic Configured\033[0m: $STATIC_IP (Inactive)" + DHCP_STATUS="\033[33mNo\033[0m (Check Link)" + fi + + # Display results using printf for aligned columns + printf "\033[1m%-30s\033[0m: %s\n" "Hostname" "$CURRENT_HOSTNAME" + printf "\033[1m%-30s\033[0m: %s\n" "Active IP Address (Interface)" "$IP_ADDRESS_STATUS" + printf "\033[1m%-30s\033[0m: %s\n" "DHCP Assigned" "$DHCP_STATUS" + printf "\033[1m%-30s\033[0m: %s\n" "SSHD Password Authentication" "$SSHD_STATUS" + printf "\n" +} + +# Function to notify user about reboot +notify_reboot() { + printf "\n\033[33;1m*** Configuration Applied ***\033[0m\n" + printf "For the new settings (Hostname, IP) to take full effect, you must reboot.\n" + printf "\033[36m(Note: SSH changes are active, but a reboot is safer).\033[0m\n" +} + +# Helper to run a command that modifies a root-owned file +run_privileged() { + printf "\n\033[34;1m[ACTION REQUIRING SUDO]\033[0m\n" + # Use sudo sh -c to execute the command as root + if sudo sh -c "$1"; then + return 0 + else + printf "\n\033[31mError: Sudo command failed. Check password or permissions.\033[0m\n" + return 1 + fi +} + +# --- Menu Option Functions (1, 2, 3 require sudo via run_privileged) --- + +# a. Update hostname +update_hostname() { + printf "\n--- Update Hostname ---\n" + printf "The current hostname is: \033[36m%s\033[0m\n" "$(hostname)" + printf "Enter new hostname: " + read NEW_HOSTNAME + + if [ -z "$NEW_HOSTNAME" ]; then + printf "\033[31mHostname cannot be empty. Aborting.\033[0m\n" + return + fi + + # Use run_privileged for writing to the root-owned file + if run_privileged "echo '$NEW_HOSTNAME' > $HOSTNAME_FILE"; then + # This updates the *runtime* hostname, not just the file + hostname "$NEW_HOSTNAME" + printf "\n\033[32mSuccessfully updated hostname to: %s\033[0m\n" "$NEW_HOSTNAME" + notify_reboot + fi +} + +# b. Configure IP address (Static) +configure_ip() { + printf "\n--- Configure Static IP Address (Connman) ---\n" + + # 1. Detect Interface + IFACE=$(ip route get 1.1.1.1 2>/dev/null | grep -o 'dev [^ ]*' | awk '{print $2}' | head -n 1) + + if [ -z "$IFACE" ]; then + printf "\033[31mCould not detect a default network interface. Aborting.\033[0m\n" + return + fi + printf "Detected primary network interface: \033[36m%s\033[0m\n" "$IFACE" + + printf "Enter static IP address (e.g., 192.168.1.10): " + read IP_ADDR + + printf "Enter netmask prefix (e.g., 24 for 255.255.255.0): " + read MASK_PREFIX + + printf "Enter gateway address (e.g., 192.168.1.1): " + read GATEWAY + + printf "Enter nameserver IP (e.g., 8.8.8.8): " + read NAMESERVER + + if [ -z "$IP_ADDR" ] || [ -z "$MASK_PREFIX" ] || [ -z "$GATEWAY" ] || [ -z "$NAMESERVER" ]; then + printf "\033[31mAll fields are required. Aborting.\033[0m\n" + return + fi + + # Generate Connman config content in a shell variable + CONFIG_CONTENT="# Automatically generated by k3os-config.sh\n" + CONFIG_CONTENT="${CONFIG_CONTENT}[service_$IFACE]\n" + CONFIG_CONTENT="${CONFIG_CONTENT}Type = ethernet\n" + CONFIG_CONTENT="${CONFIG_CONTENT}Nameservers = $NAMESERVER\n" + CONFIG_CONTENT="${CONFIG_CONTENT}IPv4 = $IP_ADDR/$MASK_PREFIX/$GATEWAY\n" + + # Use run_privileged to write the configuration content + printf "Writing static configuration to %s...\n" "$CONNMAN_CONFIG" + + # We must escape the content slightly to pass it through 'sh -c' + # Use tee to safely overwrite the file as root. + PRIV_CMD="printf \"%b\" \"$CONFIG_CONTENT\" | tee $CONNMAN_CONFIG >/dev/null" + + if run_privileged "$PRIV_CMD"; then + printf "\n\033[32mStatic IP configuration saved for interface %s.\033[0m\n" "$IFACE" + printf "IP: %s/%s, Gateway: %s, Nameserver: %s\n" "$IP_ADDR" "$MASK_PREFIX" "$GATEWAY" "$NAMESERVER" + notify_reboot + fi +} + +# c. Toggle sshd password authentication +toggle_ssh_auth() { + printf "\n--- Toggle SSHD Password Authentication ---\n" + + # Check current status by reading the root-owned file + if sudo grep -q '^PasswordAuthentication yes' "$SSHD_CONFIG" 2>/dev/null; then + CURRENT_SETTING="yes" + NEW_SETTING="no" + else + CURRENT_SETTING="no" + NEW_SETTING="yes" + fi + + printf "Current setting: \033[36m%s\033[0m\n" "$CURRENT_SETTING" + + # The sed command needs to run as root + # 1. Check if line exists (commented or not) and replace it + # 2. If it doesn't exist, append it + + # We use a combined, double-quoted command for run_privileged + PRIV_CMD="if grep -q '^#*PasswordAuthentication' $SSHD_CONFIG; then + sed -i 's/^#*PasswordAuthentication .*/PasswordAuthentication $NEW_SETTING/g' $SSHD_CONFIG + else + echo 'PasswordAuthentication $NEW_SETTING' >> $SSHD_CONFIG + fi" + + if run_privileged "$PRIV_CMD"; then + printf "Setting changed to: \033[32m%s\033[0m\n" "$NEW_SETTING" + + printf "Restarting SSH service...\n" + # Restarting the service also requires sudo + if run_privileged "/etc/init.d/sshd restart"; then + printf "\n\033[32mSSHD service restarted. Password authentication is now set to %s.\033[0m\n" "$NEW_SETTING" + fi + fi +} + +# d. Download kubeconfig from master (NO SUDO REQUIRED) +download_kubeconfig() { + printf "\n--- Download Kubeconfig ---\n" + printf "Enter k3s master IP address: " + read MASTER_IP + + if [ -z "$MASTER_IP" ]; then + printf "\033[31mMaster IP cannot be empty. Aborting.\033[0m\n" + return + fi + + printf "Attempting to download /etc/rancher/k3s/k3s.yaml from rancher@%s\n" "$MASTER_IP" + printf "(You will be prompted for the 'rancher' user's password on the remote master.)\n" + + # Create .kube directory in the current user's home directory + mkdir -p "$USER_HOME/.kube" + + # Use scp to copy the file to the user's local path + if scp "rancher@$MASTER_IP:/etc/rancher/k3s/k3s.yaml" "$KUBECONFIG_PATH"; then + printf "\n\033[32mSuccessfully downloaded kubeconfig to %s\033[0m\n" "$KUBECONFIG_PATH" + printf "The config file is ready for use by 'kubectl' or 'k3s kubectl'.\n" + else + printf "\n\033[31mError: Kubeconfig download failed.\033[0m\n" + printf "Check the master IP, password for 'rancher', and SSH connectivity.\n" + fi +} + +# --- Main Menu Logic --- + +main_menu() { + while true; do + show_status + printf "\033[1mSelect an option (1, 2, 3 require sudo):\033[0m\n" + printf " \033[36m1\033[0m) Update hostname (k3os reboot required)\n" + printf " \033[36m2\033[0m) Configure static IP (k3os reboot required)\n" + printf " \033[36m3\033[0m) Toggle sshd PasswordAuthentication (SSHD service restart)\n" + printf " \033[36m4\033[0m) Download kubeconfig from master (Runs as user, NO local sudo)\n" + printf " \033[31mQ\033[0m) Quit\n" + printf "\nOption: " + read CHOICE + + case "$CHOICE" in + 1) update_hostname ;; + 2) configure_ip ;; + 3) toggle_ssh_auth ;; + 4) download_kubeconfig ;; + [Qq]*) printf "\nExiting K3OS configuration utility. Goodbye.\n"; exit 0 ;; + *) printf "\n\033[31mInvalid option. Please choose 1, 2, 3, 4, or Q.\033[0m\n" ;; + esac + printf "\nPress ENTER to return to the menu...\n" + read DUMMY + done +} + +# --- Script Execution --- +main_menu