mirror of
https://github.com/9technologygroup/patchmon.net.git
synced 2025-10-30 19:43:49 +00:00
Fixed permissions roles creation bug On initial deployment, made it so the agent being populated will be set as default and current Fixed host detail to include package numbers Added ability to add full name - fixed loads of other bugs caused by camelcase to snake_Case migration
1224 lines
44 KiB
Bash
Executable File
1224 lines
44 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# PatchMon Agent Script v1.2.6
|
|
# This script sends package update information to the PatchMon server using API credentials
|
|
|
|
# Configuration
|
|
PATCHMON_SERVER="${PATCHMON_SERVER:-http://localhost:3001}"
|
|
API_VERSION="v1"
|
|
AGENT_VERSION="1.2.6"
|
|
CONFIG_FILE="/etc/patchmon/agent.conf"
|
|
CREDENTIALS_FILE="/etc/patchmon/credentials"
|
|
LOG_FILE="/var/log/patchmon-agent.log"
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Logging function
|
|
log() {
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
# Error handling
|
|
error() {
|
|
echo -e "${RED}ERROR: $1${NC}" >&2
|
|
log "ERROR: $1"
|
|
exit 1
|
|
}
|
|
|
|
# Info logging
|
|
info() {
|
|
echo -e "${BLUE}INFO: $1${NC}"
|
|
log "INFO: $1"
|
|
}
|
|
|
|
# Success logging
|
|
success() {
|
|
echo -e "${GREEN}SUCCESS: $1${NC}"
|
|
log "SUCCESS: $1"
|
|
}
|
|
|
|
# Warning logging
|
|
warning() {
|
|
echo -e "${YELLOW}WARNING: $1${NC}"
|
|
log "WARNING: $1"
|
|
}
|
|
|
|
# Check if running as root
|
|
check_root() {
|
|
if [[ $EUID -ne 0 ]]; then
|
|
error "This script must be run as root"
|
|
fi
|
|
}
|
|
|
|
# Create necessary directories
|
|
setup_directories() {
|
|
mkdir -p /etc/patchmon
|
|
mkdir -p /var/log
|
|
touch "$LOG_FILE"
|
|
chmod 600 "$LOG_FILE"
|
|
}
|
|
|
|
# Load configuration
|
|
load_config() {
|
|
if [[ -f "$CONFIG_FILE" ]]; then
|
|
source "$CONFIG_FILE"
|
|
fi
|
|
}
|
|
|
|
# Load API credentials
|
|
load_credentials() {
|
|
if [[ ! -f "$CREDENTIALS_FILE" ]]; then
|
|
error "Credentials file not found at $CREDENTIALS_FILE. Please configure API credentials first."
|
|
fi
|
|
|
|
source "$CREDENTIALS_FILE"
|
|
|
|
if [[ -z "$API_ID" ]] || [[ -z "$API_KEY" ]]; then
|
|
error "API_ID and API_KEY must be configured in $CREDENTIALS_FILE"
|
|
fi
|
|
|
|
# Use PATCHMON_URL from credentials if available, otherwise use default
|
|
if [[ -n "$PATCHMON_URL" ]]; then
|
|
PATCHMON_SERVER="$PATCHMON_URL"
|
|
fi
|
|
}
|
|
|
|
# Configure API credentials
|
|
configure_credentials() {
|
|
info "Setting up API credentials..."
|
|
|
|
if [[ -z "$1" ]] || [[ -z "$2" ]]; then
|
|
echo "Usage: $0 configure <API_ID> <API_KEY> [SERVER_URL]"
|
|
echo ""
|
|
echo "Example:"
|
|
echo " $0 configure patchmon_1a2b3c4d abcd1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
|
|
echo " $0 configure patchmon_1a2b3c4d abcd1234567890abcdef1234567890abcdef1234567890abcdef1234567890 http://patchmon.example.com"
|
|
echo ""
|
|
echo "Contact your PatchMon administrator to get your API credentials."
|
|
exit 1
|
|
fi
|
|
|
|
local api_id="$1"
|
|
local api_key="$2"
|
|
local server_url="${3:-$PATCHMON_SERVER}"
|
|
|
|
# Validate API ID format
|
|
if [[ ! "$api_id" =~ ^patchmon_[a-f0-9]{16}$ ]]; then
|
|
error "Invalid API ID format. API ID should be in format: patchmon_xxxxxxxxxxxxxxxx"
|
|
fi
|
|
|
|
# Validate API Key format (64 hex characters)
|
|
if [[ ! "$api_key" =~ ^[a-f0-9]{64}$ ]]; then
|
|
error "Invalid API Key format. API Key should be 64 hexadecimal characters."
|
|
fi
|
|
|
|
# Validate server URL format
|
|
if [[ ! "$server_url" =~ ^https?:// ]]; then
|
|
error "Invalid server URL format. Must start with http:// or https://"
|
|
fi
|
|
|
|
# Create credentials file
|
|
cat > "$CREDENTIALS_FILE" << EOF
|
|
# PatchMon API Credentials
|
|
# Generated on $(date)
|
|
PATCHMON_URL="$server_url"
|
|
API_ID="$api_id"
|
|
API_KEY="$api_key"
|
|
EOF
|
|
|
|
chmod 600 "$CREDENTIALS_FILE"
|
|
success "API credentials configured successfully"
|
|
info "Credentials saved to: $CREDENTIALS_FILE"
|
|
|
|
# Test credentials
|
|
info "Testing API credentials..."
|
|
test_credentials
|
|
}
|
|
|
|
# Test API credentials
|
|
test_credentials() {
|
|
load_credentials
|
|
|
|
local response=$(curl -s -X POST \
|
|
-H "Content-Type: application/json" \
|
|
-H "X-API-ID: $API_ID" \
|
|
-H "X-API-KEY: $API_KEY" \
|
|
"$PATCHMON_SERVER/api/$API_VERSION/hosts/ping")
|
|
|
|
if [[ $? -eq 0 ]] && echo "$response" | grep -q "success"; then
|
|
success "API credentials are valid"
|
|
local hostname=$(echo "$response" | grep -o '"hostname":"[^"]*' | cut -d'"' -f4)
|
|
if [[ -n "$hostname" ]]; then
|
|
info "Connected as host: $hostname"
|
|
fi
|
|
else
|
|
error "API credentials test failed: $response"
|
|
fi
|
|
}
|
|
|
|
# Detect OS and version
|
|
detect_os() {
|
|
if [[ -f /etc/os-release ]]; then
|
|
source /etc/os-release
|
|
OS_TYPE=$(echo "$ID" | tr '[:upper:]' '[:lower:]')
|
|
OS_VERSION="$VERSION_ID"
|
|
|
|
# Map OS variations to their appropriate categories
|
|
case "$OS_TYPE" in
|
|
"pop"|"linuxmint"|"elementary")
|
|
OS_TYPE="ubuntu"
|
|
;;
|
|
"opensuse"|"opensuse-leap"|"opensuse-tumbleweed")
|
|
OS_TYPE="suse"
|
|
;;
|
|
"rocky"|"almalinux")
|
|
OS_TYPE="rhel"
|
|
;;
|
|
esac
|
|
|
|
elif [[ -f /etc/redhat-release ]]; then
|
|
if grep -q "CentOS" /etc/redhat-release; then
|
|
OS_TYPE="centos"
|
|
elif grep -q "Red Hat" /etc/redhat-release; then
|
|
OS_TYPE="rhel"
|
|
fi
|
|
OS_VERSION=$(grep -oE '[0-9]+\.[0-9]+' /etc/redhat-release | head -1)
|
|
else
|
|
error "Unable to detect OS version"
|
|
fi
|
|
|
|
ARCHITECTURE=$(uname -m)
|
|
HOSTNAME=$(hostname)
|
|
IP_ADDRESS=$(hostname -I | awk '{print $1}')
|
|
}
|
|
|
|
# Get repository information based on OS
|
|
get_repository_info() {
|
|
local repos_json="["
|
|
local first=true
|
|
|
|
case "$OS_TYPE" in
|
|
"ubuntu"|"debian")
|
|
get_apt_repositories repos_json first
|
|
;;
|
|
"centos"|"rhel"|"fedora")
|
|
get_yum_repositories repos_json first
|
|
;;
|
|
*)
|
|
# Return empty array for unsupported OS
|
|
;;
|
|
esac
|
|
|
|
repos_json+="]"
|
|
echo "$repos_json"
|
|
}
|
|
|
|
# Get repository info for APT-based systems
|
|
get_apt_repositories() {
|
|
local -n repos_ref=$1
|
|
local -n first_ref=$2
|
|
|
|
# Parse traditional .list files
|
|
local sources_files="/etc/apt/sources.list"
|
|
if [[ -d "/etc/apt/sources.list.d" ]]; then
|
|
sources_files="$sources_files $(find /etc/apt/sources.list.d -name '*.list' 2>/dev/null)"
|
|
fi
|
|
|
|
for file in $sources_files; do
|
|
if [[ -f "$file" ]]; then
|
|
while IFS= read -r line; do
|
|
# Skip comments and empty lines
|
|
if [[ "$line" =~ ^[[:space:]]*# ]] || [[ -z "$line" ]]; then
|
|
continue
|
|
fi
|
|
|
|
# Parse repository line (deb or deb-src)
|
|
if [[ "$line" =~ ^[[:space:]]*(deb|deb-src)[[:space:]]+ ]]; then
|
|
# Clean the line and extract components
|
|
local clean_line=$(echo "$line" | xargs)
|
|
local repo_type=$(echo "$clean_line" | awk '{print $1}')
|
|
|
|
# Handle modern APT format with options like [signed-by=...]
|
|
local url=""
|
|
local distribution=""
|
|
local components=""
|
|
|
|
if [[ "$clean_line" =~ \[.*\] ]]; then
|
|
# Modern format: deb [options] URL distribution components
|
|
# Extract URL (first field after the options)
|
|
url=$(echo "$clean_line" | sed 's/deb[^[:space:]]* \[[^]]*\] //' | awk '{print $1}')
|
|
distribution=$(echo "$clean_line" | sed 's/deb[^[:space:]]* \[[^]]*\] //' | awk '{print $2}')
|
|
components=$(echo "$clean_line" | sed 's/deb[^[:space:]]* \[[^]]*\] [^[:space:]]* [^[:space:]]* //')
|
|
else
|
|
# Traditional format: deb URL distribution components
|
|
url=$(echo "$clean_line" | awk '{print $2}')
|
|
distribution=$(echo "$clean_line" | awk '{print $3}')
|
|
components=$(echo "$clean_line" | cut -d' ' -f4- | xargs)
|
|
fi
|
|
|
|
# Skip if URL doesn't look like a valid URL
|
|
if [[ ! "$url" =~ ^https?:// ]] && [[ ! "$url" =~ ^ftp:// ]]; then
|
|
continue
|
|
fi
|
|
|
|
# Skip if distribution is empty or looks malformed
|
|
if [[ -z "$distribution" ]] || [[ "$distribution" =~ \[.*\] ]]; then
|
|
continue
|
|
fi
|
|
|
|
# Determine if repository uses HTTPS
|
|
local is_secure=false
|
|
if [[ "$url" =~ ^https:// ]]; then
|
|
is_secure=true
|
|
fi
|
|
|
|
# Generate repository name from URL and distribution
|
|
local repo_name="$distribution"
|
|
|
|
# Extract meaningful name from URL for better identification
|
|
if [[ "$url" =~ archive\.ubuntu\.com ]]; then
|
|
repo_name="ubuntu-$distribution"
|
|
elif [[ "$url" =~ security\.ubuntu\.com ]]; then
|
|
repo_name="ubuntu-$distribution-security"
|
|
elif [[ "$url" =~ deb\.nodesource\.com ]]; then
|
|
repo_name="nodesource-$distribution"
|
|
elif [[ "$url" =~ packagecloud\.io ]]; then
|
|
repo_name="packagecloud-$(echo "$url" | cut -d'/' -f4-5 | tr '/' '-')"
|
|
elif [[ "$url" =~ ppa\.launchpad ]]; then
|
|
repo_name="ppa-$(echo "$url" | cut -d'/' -f4-5 | tr '/' '-')"
|
|
elif [[ "$url" =~ packages\.microsoft\.com ]]; then
|
|
repo_name="microsoft-$(echo "$url" | cut -d'/' -f4-)"
|
|
elif [[ "$url" =~ download\.docker\.com ]]; then
|
|
repo_name="docker-$distribution"
|
|
else
|
|
# Fallback: use domain name + distribution
|
|
local domain=$(echo "$url" | cut -d'/' -f3 | cut -d':' -f1)
|
|
repo_name="$domain-$distribution"
|
|
fi
|
|
|
|
# Add component suffix if relevant
|
|
if [[ "$components" =~ updates ]]; then
|
|
repo_name="$repo_name-updates"
|
|
elif [[ "$components" =~ security ]]; then
|
|
repo_name="$repo_name-security"
|
|
elif [[ "$components" =~ backports ]]; then
|
|
repo_name="$repo_name-backports"
|
|
fi
|
|
|
|
if [[ "$first_ref" == true ]]; then
|
|
first_ref=false
|
|
else
|
|
repos_ref+=","
|
|
fi
|
|
|
|
repos_ref+="{\"name\":\"$repo_name\",\"url\":\"$url\",\"distribution\":\"$distribution\",\"components\":\"$components\",\"repoType\":\"$repo_type\",\"isEnabled\":true,\"isSecure\":$is_secure}"
|
|
fi
|
|
done < "$file"
|
|
fi
|
|
done
|
|
|
|
# Parse modern DEB822 format (.sources files)
|
|
if [[ -d "/etc/apt/sources.list.d" ]]; then
|
|
local sources_files_deb822=$(find /etc/apt/sources.list.d -name '*.sources' 2>/dev/null)
|
|
for file in $sources_files_deb822; do
|
|
if [[ -f "$file" ]]; then
|
|
local deb822_result=$(parse_deb822_sources_simple "$file")
|
|
if [[ -n "$deb822_result" ]]; then
|
|
if [[ "$first_ref" == true ]]; then
|
|
first_ref=false
|
|
repos_ref+="$deb822_result"
|
|
else
|
|
repos_ref+=",$deb822_result"
|
|
fi
|
|
fi
|
|
fi
|
|
done
|
|
fi
|
|
}
|
|
|
|
# Simple DEB822 parser that returns JSON string
|
|
parse_deb822_sources_simple() {
|
|
local file=$1
|
|
local result=""
|
|
local enabled=""
|
|
local types=""
|
|
local uris=""
|
|
local suites=""
|
|
local components=""
|
|
local name=""
|
|
local first_entry=true
|
|
|
|
while IFS= read -r line; do
|
|
# Skip empty lines and comments
|
|
if [[ -z "$line" ]] || [[ "$line" =~ ^[[:space:]]*# ]]; then
|
|
continue
|
|
fi
|
|
|
|
# Parse key-value pairs
|
|
if [[ "$line" =~ ^([^:]+):[[:space:]]*(.*)$ ]]; then
|
|
local key="${BASH_REMATCH[1]}"
|
|
local value="${BASH_REMATCH[2]}"
|
|
|
|
case "$key" in
|
|
"Enabled")
|
|
enabled="$value"
|
|
;;
|
|
"Types")
|
|
types="$value"
|
|
;;
|
|
"URIs")
|
|
uris="$value"
|
|
;;
|
|
"Suites")
|
|
suites="$value"
|
|
;;
|
|
"Components")
|
|
components="$value"
|
|
;;
|
|
"X-Repolib-Name")
|
|
name="$value"
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
# Process repository entry when we hit a blank line
|
|
if [[ -z "$line" ]] || [[ "$line" =~ ^[[:space:]]*$ ]]; then
|
|
if [[ -n "$uris" && -n "$suites" && "$enabled" == "yes" ]]; then
|
|
local entry_result=$(process_deb822_entry_simple "$name" "$types" "$uris" "$suites" "$components")
|
|
if [[ -n "$entry_result" ]]; then
|
|
if [[ "$first_entry" == true ]]; then
|
|
first_entry=false
|
|
result="$entry_result"
|
|
else
|
|
result="$result,$entry_result"
|
|
fi
|
|
fi
|
|
fi
|
|
# Reset variables for next entry
|
|
enabled=""
|
|
types=""
|
|
uris=""
|
|
suites=""
|
|
components=""
|
|
name=""
|
|
fi
|
|
done < "$file"
|
|
|
|
# Process the last entry if file doesn't end with blank line
|
|
if [[ -n "$uris" && -n "$suites" && "$enabled" == "yes" ]]; then
|
|
local entry_result=$(process_deb822_entry_simple "$name" "$types" "$uris" "$suites" "$components")
|
|
if [[ -n "$entry_result" ]]; then
|
|
if [[ "$first_entry" == true ]]; then
|
|
result="$entry_result"
|
|
else
|
|
result="$result,$entry_result"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
echo "$result"
|
|
}
|
|
|
|
# Process a DEB822 repository entry and return JSON
|
|
process_deb822_entry_simple() {
|
|
local name=$1
|
|
local types=$2
|
|
local uris=$3
|
|
local suites=$4
|
|
local components=$5
|
|
local result=""
|
|
local first_entry=true
|
|
|
|
# Handle multiple URIs
|
|
for uri in $uris; do
|
|
# Skip if URI doesn't look like a valid URL
|
|
if [[ ! "$uri" =~ ^https?:// ]] && [[ ! "$uri" =~ ^ftp:// ]]; then
|
|
continue
|
|
fi
|
|
|
|
# Handle multiple suites
|
|
for suite in $suites; do
|
|
# Skip if suite looks malformed
|
|
if [[ -z "$suite" ]]; then
|
|
continue
|
|
fi
|
|
|
|
# Determine if repository uses HTTPS
|
|
local is_secure=false
|
|
if [[ "$uri" =~ ^https:// ]]; then
|
|
is_secure=true
|
|
fi
|
|
|
|
# Generate repository name
|
|
local repo_name=""
|
|
if [[ -n "$name" ]]; then
|
|
repo_name=$(echo "$name" | tr ' ' '-' | tr '[:upper:]' '[:lower:]')
|
|
else
|
|
repo_name="$suite"
|
|
fi
|
|
|
|
# Extract meaningful name from URI for better identification
|
|
if [[ "$uri" =~ apt\.pop-os\.org/ubuntu ]]; then
|
|
repo_name="pop-os-ubuntu-$suite"
|
|
elif [[ "$uri" =~ apt\.pop-os\.org/release ]]; then
|
|
repo_name="pop-os-release-$suite"
|
|
elif [[ "$uri" =~ apt\.pop-os\.org/proprietary ]]; then
|
|
repo_name="pop-os-apps-$suite"
|
|
elif [[ "$uri" =~ archive\.ubuntu\.com ]]; then
|
|
repo_name="ubuntu-$suite"
|
|
elif [[ "$uri" =~ security\.ubuntu\.com ]]; then
|
|
repo_name="ubuntu-$suite-security"
|
|
else
|
|
# Fallback: use domain name + suite
|
|
local domain=$(echo "$uri" | cut -d'/' -f3 | cut -d':' -f1)
|
|
repo_name="$domain-$suite"
|
|
fi
|
|
|
|
# Add component suffix if relevant and not already included
|
|
if [[ "$suite" != *"security"* && "$components" =~ security ]]; then
|
|
repo_name="$repo_name-security"
|
|
elif [[ "$suite" != *"updates"* && "$components" =~ updates ]]; then
|
|
repo_name="$repo_name-updates"
|
|
elif [[ "$suite" != *"backports"* && "$components" =~ backports ]]; then
|
|
repo_name="$repo_name-backports"
|
|
fi
|
|
|
|
# Determine repo type (prefer deb over deb-src)
|
|
local repo_type="deb"
|
|
if [[ "$types" =~ deb-src ]] && [[ ! "$types" =~ ^deb[[:space:]] ]]; then
|
|
repo_type="deb-src"
|
|
fi
|
|
|
|
local json_entry="{\"name\":\"$repo_name\",\"url\":\"$uri\",\"distribution\":\"$suite\",\"components\":\"$components\",\"repoType\":\"$repo_type\",\"isEnabled\":true,\"isSecure\":$is_secure}"
|
|
|
|
if [[ "$first_entry" == true ]]; then
|
|
first_entry=false
|
|
result="$json_entry"
|
|
else
|
|
result="$result,$json_entry"
|
|
fi
|
|
done
|
|
done
|
|
|
|
echo "$result"
|
|
}
|
|
|
|
# Get repository info for YUM-based systems
|
|
get_yum_repositories() {
|
|
local -n repos_ref=$1
|
|
local -n first_ref=$2
|
|
|
|
# Parse yum/dnf repository configuration
|
|
if command -v dnf >/dev/null 2>&1; then
|
|
local repo_info=$(dnf repolist all --verbose 2>/dev/null | grep -E "^Repo-id|^Repo-baseurl|^Repo-name|^Repo-status")
|
|
elif command -v yum >/dev/null 2>&1; then
|
|
local repo_info=$(yum repolist all -v 2>/dev/null | grep -E "^Repo-id|^Repo-baseurl|^Repo-name|^Repo-status")
|
|
fi
|
|
|
|
# This is a simplified implementation - would need more work for full YUM support
|
|
# For now, return empty for non-APT systems
|
|
}
|
|
|
|
# Get package information based on OS
|
|
get_package_info() {
|
|
local packages_json="["
|
|
local first=true
|
|
|
|
case "$OS_TYPE" in
|
|
"ubuntu"|"debian")
|
|
get_apt_packages packages_json first
|
|
;;
|
|
"centos"|"rhel"|"fedora")
|
|
get_yum_packages packages_json first
|
|
;;
|
|
*)
|
|
error "Unsupported OS type: $OS_TYPE"
|
|
;;
|
|
esac
|
|
|
|
packages_json+="]"
|
|
echo "$packages_json"
|
|
}
|
|
|
|
# Get package info for APT-based systems
|
|
get_apt_packages() {
|
|
local -n packages_ref=$1
|
|
local -n first_ref=$2
|
|
|
|
# Update package lists
|
|
apt-get update -qq
|
|
|
|
# Get upgradable packages
|
|
local upgradable=$(apt list --upgradable 2>/dev/null | grep -v "WARNING")
|
|
|
|
while IFS= read -r line; do
|
|
if [[ "$line" =~ ^([^/]+)/([^[:space:]]+)[[:space:]]+([^[:space:]]+)[[:space:]]+.*[[:space:]]([^[:space:]]+)[[:space:]]*(\[.*\])? ]]; then
|
|
local package_name="${BASH_REMATCH[1]}"
|
|
local current_version="${BASH_REMATCH[4]}"
|
|
local available_version="${BASH_REMATCH[3]}"
|
|
local is_security_update=false
|
|
|
|
# Check if it's a security update
|
|
if echo "$line" | grep -q "security"; then
|
|
is_security_update=true
|
|
fi
|
|
|
|
if [[ "$first_ref" == true ]]; then
|
|
first_ref=false
|
|
else
|
|
packages_ref+=","
|
|
fi
|
|
|
|
packages_ref+="{\"name\":\"$package_name\",\"currentVersion\":\"$current_version\",\"availableVersion\":\"$available_version\",\"needsUpdate\":true,\"isSecurityUpdate\":$is_security_update}"
|
|
fi
|
|
done <<< "$upgradable"
|
|
|
|
# Get installed packages that are up to date
|
|
local installed=$(dpkg-query -W -f='${Package} ${Version}\n' | head -100)
|
|
|
|
while IFS=' ' read -r package_name version; do
|
|
if [[ -n "$package_name" && -n "$version" ]]; then
|
|
# Check if this package is not in the upgrade list
|
|
if ! echo "$upgradable" | grep -q "^$package_name/"; then
|
|
if [[ "$first_ref" == true ]]; then
|
|
first_ref=false
|
|
else
|
|
packages_ref+=","
|
|
fi
|
|
|
|
packages_ref+="{\"name\":\"$package_name\",\"currentVersion\":\"$version\",\"needsUpdate\":false,\"isSecurityUpdate\":false}"
|
|
fi
|
|
fi
|
|
done <<< "$installed"
|
|
}
|
|
|
|
# Get package info for YUM/DNF-based systems
|
|
get_yum_packages() {
|
|
local -n packages_ref=$1
|
|
local -n first_ref=$2
|
|
|
|
local package_manager="yum"
|
|
if command -v dnf &> /dev/null; then
|
|
package_manager="dnf"
|
|
fi
|
|
|
|
# Get upgradable packages
|
|
local upgradable=$($package_manager check-update 2>/dev/null | grep -v "^$" | grep -v "^Loaded" | grep -v "^Last metadata" | tail -n +2)
|
|
|
|
while IFS= read -r line; do
|
|
if [[ "$line" =~ ^([^[:space:]]+)[[:space:]]+([^[:space:]]+)[[:space:]]+([^[:space:]]+) ]]; then
|
|
local package_name="${BASH_REMATCH[1]}"
|
|
local available_version="${BASH_REMATCH[2]}"
|
|
local repo="${BASH_REMATCH[3]}"
|
|
|
|
# Get current version
|
|
local current_version=$($package_manager list installed "$package_name" 2>/dev/null | grep "^$package_name" | awk '{print $2}')
|
|
|
|
local is_security_update=false
|
|
if echo "$repo" | grep -q "security"; then
|
|
is_security_update=true
|
|
fi
|
|
|
|
if [[ "$first_ref" == true ]]; then
|
|
first_ref=false
|
|
else
|
|
packages_ref+=","
|
|
fi
|
|
|
|
packages_ref+="{\"name\":\"$package_name\",\"currentVersion\":\"$current_version\",\"availableVersion\":\"$available_version\",\"needsUpdate\":true,\"isSecurityUpdate\":$is_security_update}"
|
|
fi
|
|
done <<< "$upgradable"
|
|
|
|
# Get some installed packages that are up to date
|
|
local installed=$($package_manager list installed 2>/dev/null | grep -v "^Loaded" | grep -v "^Installed" | head -100)
|
|
|
|
while IFS= read -r line; do
|
|
if [[ "$line" =~ ^([^[:space:]]+)[[:space:]]+([^[:space:]]+) ]]; then
|
|
local package_name="${BASH_REMATCH[1]}"
|
|
local version="${BASH_REMATCH[2]}"
|
|
|
|
# Check if this package is not in the upgrade list
|
|
if ! echo "$upgradable" | grep -q "^$package_name "; then
|
|
if [[ "$first_ref" == true ]]; then
|
|
first_ref=false
|
|
else
|
|
packages_ref+=","
|
|
fi
|
|
|
|
packages_ref+="{\"name\":\"$package_name\",\"currentVersion\":\"$version\",\"needsUpdate\":false,\"isSecurityUpdate\":false}"
|
|
fi
|
|
fi
|
|
done <<< "$installed"
|
|
}
|
|
|
|
# Get hardware information
|
|
get_hardware_info() {
|
|
local cpu_model=""
|
|
local cpu_cores=0
|
|
local ram_installed=0
|
|
local swap_size=0
|
|
local disk_details="[]"
|
|
|
|
# CPU Information
|
|
if command -v lscpu >/dev/null 2>&1; then
|
|
cpu_model=$(lscpu | grep "Model name" | cut -d':' -f2 | xargs)
|
|
cpu_cores=$(lscpu | grep "^CPU(s):" | cut -d':' -f2 | xargs)
|
|
elif [[ -f /proc/cpuinfo ]]; then
|
|
cpu_model=$(grep "model name" /proc/cpuinfo | head -1 | cut -d':' -f2 | xargs)
|
|
cpu_cores=$(grep -c "^processor" /proc/cpuinfo)
|
|
fi
|
|
|
|
# Memory Information
|
|
if command -v free >/dev/null 2>&1; then
|
|
ram_installed=$(free -g | grep "^Mem:" | awk '{print $2}')
|
|
swap_size=$(free -g | grep "^Swap:" | awk '{print $2}')
|
|
elif [[ -f /proc/meminfo ]]; then
|
|
ram_installed=$(grep "MemTotal" /proc/meminfo | awk '{print int($2/1024/1024)}')
|
|
swap_size=$(grep "SwapTotal" /proc/meminfo | awk '{print int($2/1024/1024)}')
|
|
fi
|
|
|
|
# Disk Information
|
|
if command -v lsblk >/dev/null 2>&1; then
|
|
disk_details=$(lsblk -J -o NAME,SIZE,TYPE,MOUNTPOINT | jq -c '[.blockdevices[] | select(.type == "disk") | {name: .name, size: .size, mountpoint: .mountpoint}]')
|
|
elif command -v df >/dev/null 2>&1; then
|
|
disk_details=$(df -h | grep -E "^/dev/" | awk '{print "{\"name\":\""$1"\",\"size\":\""$2"\",\"mountpoint\":\""$6"\"}"}' | jq -s .)
|
|
fi
|
|
|
|
echo "{\"cpuModel\":\"$cpu_model\",\"cpuCores\":$cpu_cores,\"ramInstalled\":$ram_installed,\"swapSize\":$swap_size,\"diskDetails\":$disk_details}"
|
|
}
|
|
|
|
# Get network information
|
|
get_network_info() {
|
|
local gateway_ip=""
|
|
local dns_servers="[]"
|
|
local network_interfaces="[]"
|
|
|
|
# Gateway IP
|
|
if command -v ip >/dev/null 2>&1; then
|
|
gateway_ip=$(ip route | grep default | head -1 | awk '{print $3}')
|
|
elif command -v route >/dev/null 2>&1; then
|
|
gateway_ip=$(route -n | grep '^0.0.0.0' | head -1 | awk '{print $2}')
|
|
fi
|
|
|
|
# DNS Servers
|
|
if [[ -f /etc/resolv.conf ]]; then
|
|
dns_servers=$(grep "nameserver" /etc/resolv.conf | awk '{print $2}' | jq -R . | jq -s .)
|
|
fi
|
|
|
|
# Network Interfaces
|
|
if command -v ip >/dev/null 2>&1; then
|
|
network_interfaces=$(ip -j addr show | jq -c '[.[] | {name: .ifname, type: .link_type, addresses: [.addr_info[]? | {address: .local, family: .family}]}]')
|
|
elif command -v ifconfig >/dev/null 2>&1; then
|
|
network_interfaces=$(ifconfig -a | grep -E "^[a-zA-Z]" | awk '{print $1}' | jq -R . | jq -s .)
|
|
fi
|
|
|
|
echo "{\"gatewayIp\":\"$gateway_ip\",\"dnsServers\":$dns_servers,\"networkInterfaces\":$network_interfaces}"
|
|
}
|
|
|
|
# Get system information
|
|
get_system_info() {
|
|
local kernel_version=""
|
|
local selinux_status=""
|
|
local system_uptime=""
|
|
local load_average="[]"
|
|
|
|
# Kernel Version
|
|
if [[ -f /proc/version ]]; then
|
|
kernel_version=$(cat /proc/version | awk '{print $3}')
|
|
elif command -v uname >/dev/null 2>&1; then
|
|
kernel_version=$(uname -r)
|
|
fi
|
|
|
|
# SELinux Status
|
|
if command -v getenforce >/dev/null 2>&1; then
|
|
selinux_status=$(getenforce 2>/dev/null | tr '[:upper:]' '[:lower:]')
|
|
elif [[ -f /etc/selinux/config ]]; then
|
|
selinux_status=$(grep "^SELINUX=" /etc/selinux/config | cut -d'=' -f2 | tr '[:upper:]' '[:lower:]')
|
|
else
|
|
selinux_status="disabled"
|
|
fi
|
|
|
|
# System Uptime
|
|
if [[ -f /proc/uptime ]]; then
|
|
local uptime_seconds=$(cat /proc/uptime | awk '{print int($1)}')
|
|
local days=$((uptime_seconds / 86400))
|
|
local hours=$(((uptime_seconds % 86400) / 3600))
|
|
local minutes=$(((uptime_seconds % 3600) / 60))
|
|
system_uptime="${days}d ${hours}h ${minutes}m"
|
|
elif command -v uptime >/dev/null 2>&1; then
|
|
system_uptime=$(uptime | awk -F'up ' '{print $2}' | awk -F', load' '{print $1}')
|
|
fi
|
|
|
|
# Load Average
|
|
if [[ -f /proc/loadavg ]]; then
|
|
load_average=$(cat /proc/loadavg | awk '{print "["$1","$2","$3"]"}')
|
|
elif command -v uptime >/dev/null 2>&1; then
|
|
load_average=$(uptime | awk -F'load average: ' '{print "["$2"]"}' | tr -d ' ')
|
|
fi
|
|
|
|
echo "{\"kernelVersion\":\"$kernel_version\",\"selinuxStatus\":\"$selinux_status\",\"systemUptime\":\"$system_uptime\",\"loadAverage\":$load_average}"
|
|
}
|
|
|
|
# Send package update to server
|
|
send_update() {
|
|
load_credentials
|
|
|
|
info "Collecting package information..."
|
|
local packages_json=$(get_package_info)
|
|
|
|
info "Collecting repository information..."
|
|
local repositories_json=$(get_repository_info)
|
|
|
|
info "Collecting hardware information..."
|
|
local hardware_json=$(get_hardware_info)
|
|
|
|
info "Collecting network information..."
|
|
local network_json=$(get_network_info)
|
|
|
|
info "Collecting system information..."
|
|
local system_json=$(get_system_info)
|
|
|
|
info "Sending update to PatchMon server..."
|
|
|
|
# Merge all JSON objects into one
|
|
local merged_json=$(echo "$hardware_json $network_json $system_json" | jq -s '.[0] * .[1] * .[2]')
|
|
# Create the base payload and merge with system info
|
|
local base_payload=$(cat <<EOF
|
|
{
|
|
"packages": $packages_json,
|
|
"repositories": $repositories_json,
|
|
"osType": "$OS_TYPE",
|
|
"osVersion": "$OS_VERSION",
|
|
"hostname": "$HOSTNAME",
|
|
"ip": "$IP_ADDRESS",
|
|
"architecture": "$ARCHITECTURE",
|
|
"agentVersion": "$AGENT_VERSION"
|
|
}
|
|
EOF
|
|
)
|
|
|
|
# Merge the base payload with the system information
|
|
local payload=$(echo "$base_payload $merged_json" | jq -s '.[0] * .[1]')
|
|
|
|
|
|
local response=$(curl -s -X POST \
|
|
-H "Content-Type: application/json" \
|
|
-H "X-API-ID: $API_ID" \
|
|
-H "X-API-KEY: $API_KEY" \
|
|
-d "$payload" \
|
|
"$PATCHMON_SERVER/api/$API_VERSION/hosts/update")
|
|
|
|
if [[ $? -eq 0 ]]; then
|
|
if echo "$response" | grep -q "success"; then
|
|
success "Update sent successfully"
|
|
echo "$response" | grep -o '"packagesProcessed":[0-9]*' | cut -d':' -f2 | xargs -I {} info "Processed {} packages"
|
|
|
|
# Check for auto-update instructions (look specifically in autoUpdate section)
|
|
if echo "$response" | grep -q '"autoUpdate":{'; then
|
|
local auto_update_section=$(echo "$response" | grep -o '"autoUpdate":{[^}]*}')
|
|
local should_update=$(echo "$auto_update_section" | grep -o '"shouldUpdate":true' | cut -d':' -f2)
|
|
if [[ "$should_update" == "true" ]]; then
|
|
local latest_version=$(echo "$auto_update_section" | grep -o '"latestVersion":"[^"]*' | cut -d'"' -f4)
|
|
local current_version=$(echo "$auto_update_section" | grep -o '"currentVersion":"[^"]*' | cut -d'"' -f4)
|
|
local update_message=$(echo "$auto_update_section" | grep -o '"message":"[^"]*' | cut -d'"' -f4)
|
|
|
|
info "Auto-update detected: $update_message"
|
|
info "Current version: $current_version, Latest version: $latest_version"
|
|
|
|
# Automatically run update-agent command
|
|
info "Automatically updating agent to latest version..."
|
|
if "$0" update-agent; then
|
|
success "Agent auto-update completed successfully"
|
|
else
|
|
warning "Agent auto-update failed, but data was sent successfully"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Check for crontab update instructions (look specifically in crontabUpdate section)
|
|
if echo "$response" | grep -q '"crontabUpdate":{'; then
|
|
local crontab_update_section=$(echo "$response" | grep -o '"crontabUpdate":{[^}]*}')
|
|
local should_update_crontab=$(echo "$crontab_update_section" | grep -o '"shouldUpdate":true' | cut -d':' -f2)
|
|
if [[ "$should_update_crontab" == "true" ]]; then
|
|
local crontab_message=$(echo "$crontab_update_section" | grep -o '"message":"[^"]*' | cut -d'"' -f4)
|
|
local crontab_command=$(echo "$crontab_update_section" | grep -o '"command":"[^"]*' | cut -d'"' -f4)
|
|
|
|
if [[ -n "$crontab_message" ]]; then
|
|
info "Crontab update detected: $crontab_message"
|
|
fi
|
|
|
|
if [[ "$crontab_command" == "update-crontab" ]]; then
|
|
info "Automatically updating crontab with new interval..."
|
|
if "$0" update-crontab; then
|
|
success "Crontab updated successfully"
|
|
else
|
|
warning "Crontab update failed, but data was sent successfully"
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
else
|
|
error "Update failed: $response"
|
|
fi
|
|
else
|
|
error "Failed to send update"
|
|
fi
|
|
}
|
|
|
|
# Ping server to check connectivity
|
|
ping_server() {
|
|
load_credentials
|
|
|
|
local response=$(curl -s -X POST \
|
|
-H "Content-Type: application/json" \
|
|
-H "X-API-ID: $API_ID" \
|
|
-H "X-API-KEY: $API_KEY" \
|
|
"$PATCHMON_SERVER/api/$API_VERSION/hosts/ping")
|
|
|
|
if [[ $? -eq 0 ]] && echo "$response" | grep -q "success"; then
|
|
success "Ping successful"
|
|
local hostname=$(echo "$response" | grep -o '"hostname":"[^"]*' | cut -d'"' -f4)
|
|
if [[ -n "$hostname" ]]; then
|
|
info "Connected as host: $hostname"
|
|
fi
|
|
|
|
# Check for crontab update trigger
|
|
local should_update_crontab=$(echo "$response" | grep -o '"shouldUpdate":true' | cut -d':' -f2)
|
|
if [[ "$should_update_crontab" == "true" ]]; then
|
|
local message=$(echo "$response" | grep -o '"message":"[^"]*' | cut -d'"' -f4)
|
|
local command=$(echo "$response" | grep -o '"command":"[^"]*' | cut -d'"' -f4)
|
|
|
|
if [[ -n "$message" ]]; then
|
|
info "$message"
|
|
fi
|
|
|
|
if [[ "$command" == "update-crontab" ]]; then
|
|
info "Automatically updating crontab with new interval..."
|
|
if "$0" update-crontab; then
|
|
success "Crontab updated successfully"
|
|
else
|
|
warning "Crontab update failed, but ping was successful"
|
|
fi
|
|
fi
|
|
fi
|
|
else
|
|
error "Ping failed: $response"
|
|
fi
|
|
}
|
|
|
|
# Check for agent updates
|
|
check_version() {
|
|
load_credentials
|
|
|
|
info "Checking for agent updates..."
|
|
|
|
local response=$(curl -s -X GET "$PATCHMON_SERVER/api/$API_VERSION/hosts/agent/version")
|
|
|
|
if [[ $? -eq 0 ]]; then
|
|
local current_version=$(echo "$response" | grep -o '"currentVersion":"[^"]*' | cut -d'"' -f4)
|
|
local download_url=$(echo "$response" | grep -o '"downloadUrl":"[^"]*' | cut -d'"' -f4)
|
|
local release_notes=$(echo "$response" | grep -o '"releaseNotes":"[^"]*' | cut -d'"' -f4)
|
|
|
|
if [[ -n "$current_version" ]]; then
|
|
if [[ "$current_version" != "$AGENT_VERSION" ]]; then
|
|
warning "Agent update available!"
|
|
echo " Current version: $AGENT_VERSION"
|
|
echo " Latest version: $current_version"
|
|
if [[ -n "$release_notes" ]]; then
|
|
echo " Release notes: $release_notes"
|
|
fi
|
|
echo " Download URL: $download_url"
|
|
echo ""
|
|
echo "To update, run: $0 update-agent"
|
|
else
|
|
success "Agent is up to date (version $AGENT_VERSION)"
|
|
fi
|
|
else
|
|
warning "Could not determine current version from server"
|
|
fi
|
|
else
|
|
error "Failed to check for updates"
|
|
fi
|
|
}
|
|
|
|
# Update agent script
|
|
update_agent() {
|
|
load_credentials
|
|
|
|
info "Updating agent script..."
|
|
|
|
local response=$(curl -s -X GET "$PATCHMON_SERVER/api/$API_VERSION/hosts/agent/version")
|
|
|
|
if [[ $? -eq 0 ]]; then
|
|
local download_url=$(echo "$response" | grep -o '"downloadUrl":"[^"]*' | cut -d'"' -f4)
|
|
|
|
if [[ -z "$download_url" ]]; then
|
|
download_url="$PATCHMON_SERVER/api/$API_VERSION/hosts/agent/download"
|
|
elif [[ "$download_url" =~ ^/ ]]; then
|
|
# If download_url is relative, prepend the server URL
|
|
download_url="$PATCHMON_SERVER$download_url"
|
|
fi
|
|
|
|
info "Downloading latest agent from: $download_url"
|
|
|
|
# Create backup of current script
|
|
cp "$0" "$0.backup.$(date +%Y%m%d_%H%M%S)"
|
|
|
|
# Download new version
|
|
if curl -s -o "/tmp/patchmon-agent-new.sh" "$download_url"; then
|
|
# Verify the downloaded script is valid
|
|
if bash -n "/tmp/patchmon-agent-new.sh" 2>/dev/null; then
|
|
# Replace current script
|
|
mv "/tmp/patchmon-agent-new.sh" "$0"
|
|
chmod +x "$0"
|
|
success "Agent updated successfully"
|
|
info "Backup saved as: $0.backup.$(date +%Y%m%d_%H%M%S)"
|
|
|
|
# Get the new version number
|
|
local new_version=$(grep '^AGENT_VERSION=' "$0" | cut -d'"' -f2)
|
|
info "Updated to version: $new_version"
|
|
|
|
# Automatically run update to send new information to PatchMon
|
|
info "Sending updated information to PatchMon..."
|
|
if "$0" update; then
|
|
success "Successfully sent updated information to PatchMon"
|
|
else
|
|
warning "Failed to send updated information to PatchMon (this is not critical)"
|
|
fi
|
|
else
|
|
error "Downloaded script is invalid"
|
|
rm -f "/tmp/patchmon-agent-new.sh"
|
|
fi
|
|
else
|
|
error "Failed to download new agent script"
|
|
fi
|
|
else
|
|
error "Failed to get update information"
|
|
fi
|
|
}
|
|
|
|
# Update crontab with current policy
|
|
update_crontab() {
|
|
load_credentials
|
|
info "Updating crontab with current policy..."
|
|
local response=$(curl -s -X GET "$PATCHMON_SERVER/api/$API_VERSION/settings/update-interval")
|
|
if [[ $? -eq 0 ]]; then
|
|
local update_interval=$(echo "$response" | grep -o '"updateInterval":[0-9]*' | cut -d':' -f2)
|
|
if [[ -n "$update_interval" ]]; then
|
|
# Generate the expected crontab entry
|
|
local expected_crontab=""
|
|
if [[ $update_interval -eq 60 ]]; then
|
|
# Hourly updates starting at current minute
|
|
local current_minute=$(date +%M)
|
|
expected_crontab="$current_minute * * * * /usr/local/bin/patchmon-agent.sh update >/dev/null 2>&1"
|
|
else
|
|
# Custom interval updates
|
|
expected_crontab="*/$update_interval * * * * /usr/local/bin/patchmon-agent.sh update >/dev/null 2>&1"
|
|
fi
|
|
|
|
# Get current crontab
|
|
local current_crontab=$(crontab -l 2>/dev/null | grep "patchmon-agent.sh update" | head -1)
|
|
|
|
# Check if crontab needs updating
|
|
if [[ "$current_crontab" == "$expected_crontab" ]]; then
|
|
info "Crontab is already up to date (interval: $update_interval minutes)"
|
|
return 0
|
|
fi
|
|
|
|
info "Setting update interval to $update_interval minutes"
|
|
echo "$expected_crontab" | crontab -
|
|
success "Crontab updated successfully"
|
|
else
|
|
error "Could not determine update interval from server"
|
|
fi
|
|
else
|
|
error "Failed to get update interval policy"
|
|
fi
|
|
}
|
|
|
|
# Show detailed system diagnostics
|
|
show_diagnostics() {
|
|
info "PatchMon Agent Diagnostics v$AGENT_VERSION"
|
|
echo ""
|
|
|
|
# System information
|
|
echo "=== System Information ==="
|
|
echo "OS: $(uname -s)"
|
|
echo "Architecture: $(uname -m)"
|
|
echo "Kernel: $(uname -r)"
|
|
echo "Hostname: $(hostname)"
|
|
echo "Uptime: $(uptime -p 2>/dev/null || uptime)"
|
|
echo ""
|
|
|
|
# Agent information
|
|
echo "=== Agent Information ==="
|
|
echo "Version: $AGENT_VERSION"
|
|
echo "Script Path: $0"
|
|
echo "Config File: $CONFIG_FILE"
|
|
echo "Credentials File: $CREDENTIALS_FILE"
|
|
echo "Log File: $LOG_FILE"
|
|
echo "Script Size: $(stat -c%s "$0" 2>/dev/null || echo "Unknown") bytes"
|
|
echo "Last Modified: $(stat -c%y "$0" 2>/dev/null || echo "Unknown")"
|
|
echo ""
|
|
|
|
# Configuration
|
|
if [[ -f "$CONFIG_FILE" ]]; then
|
|
echo "=== Configuration ==="
|
|
cat "$CONFIG_FILE"
|
|
echo ""
|
|
else
|
|
echo "=== Configuration ==="
|
|
echo "No configuration file found at $CONFIG_FILE"
|
|
echo ""
|
|
fi
|
|
|
|
# Credentials status
|
|
echo "=== Credentials Status ==="
|
|
if [[ -f "$CREDENTIALS_FILE" ]]; then
|
|
echo "Credentials file exists: Yes"
|
|
echo "File size: $(stat -c%s "$CREDENTIALS_FILE" 2>/dev/null || echo "Unknown") bytes"
|
|
echo "File permissions: $(stat -c%a "$CREDENTIALS_FILE" 2>/dev/null || echo "Unknown")"
|
|
else
|
|
echo "Credentials file exists: No"
|
|
fi
|
|
echo ""
|
|
|
|
# Crontab status
|
|
echo "=== Crontab Status ==="
|
|
local crontab_entries=$(crontab -l 2>/dev/null | grep patchmon-agent || echo "None")
|
|
if [[ "$crontab_entries" != "None" ]]; then
|
|
echo "Crontab entries:"
|
|
echo "$crontab_entries"
|
|
else
|
|
echo "No crontab entries found"
|
|
fi
|
|
echo ""
|
|
|
|
# Network connectivity
|
|
echo "=== Network Connectivity ==="
|
|
if ping -c 1 -W 3 "$(echo "$PATCHMON_SERVER" | sed 's|http://||' | sed 's|https://||' | cut -d: -f1)" >/dev/null 2>&1; then
|
|
echo "Server reachable: Yes"
|
|
else
|
|
echo "Server reachable: No"
|
|
fi
|
|
echo "Server URL: $PATCHMON_SERVER"
|
|
echo ""
|
|
|
|
# Recent logs
|
|
echo "=== Recent Logs (last 10 lines) ==="
|
|
if [[ -f "$LOG_FILE" ]]; then
|
|
tail -10 "$LOG_FILE" 2>/dev/null || echo "Could not read log file"
|
|
else
|
|
echo "Log file does not exist"
|
|
fi
|
|
}
|
|
|
|
# Show current configuration
|
|
show_config() {
|
|
info "Current Configuration:"
|
|
echo " Server: ${PATCHMON_SERVER}"
|
|
echo " API Version: ${API_VERSION}"
|
|
echo " Agent Version: ${AGENT_VERSION}"
|
|
echo " Config File: ${CONFIG_FILE}"
|
|
echo " Credentials File: ${CREDENTIALS_FILE}"
|
|
echo " Log File: ${LOG_FILE}"
|
|
|
|
if [[ -f "$CREDENTIALS_FILE" ]]; then
|
|
source "$CREDENTIALS_FILE"
|
|
echo " API ID: ${API_ID}"
|
|
echo " API Key: ${API_KEY:0:8}..." # Show only first 8 characters
|
|
else
|
|
echo " API Credentials: Not configured"
|
|
fi
|
|
}
|
|
|
|
# Main function
|
|
main() {
|
|
case "$1" in
|
|
"configure")
|
|
check_root
|
|
setup_directories
|
|
load_config
|
|
configure_credentials "$2" "$3"
|
|
;;
|
|
"test")
|
|
check_root
|
|
setup_directories
|
|
load_config
|
|
test_credentials
|
|
;;
|
|
"update")
|
|
check_root
|
|
setup_directories
|
|
load_config
|
|
detect_os
|
|
send_update
|
|
;;
|
|
"ping")
|
|
check_root
|
|
setup_directories
|
|
load_config
|
|
ping_server
|
|
;;
|
|
"config")
|
|
load_config
|
|
show_config
|
|
;;
|
|
"check-version")
|
|
check_root
|
|
setup_directories
|
|
load_config
|
|
check_version
|
|
;;
|
|
"update-agent")
|
|
check_root
|
|
setup_directories
|
|
load_config
|
|
update_agent
|
|
;;
|
|
"update-crontab")
|
|
check_root
|
|
setup_directories
|
|
load_config
|
|
update_crontab
|
|
;;
|
|
"diagnostics")
|
|
show_diagnostics
|
|
;;
|
|
*)
|
|
echo "PatchMon Agent v$AGENT_VERSION - API Credential Based"
|
|
echo "Usage: $0 {configure|test|update|ping|config|check-version|update-agent|update-crontab|diagnostics}"
|
|
echo ""
|
|
echo "Commands:"
|
|
echo " configure <API_ID> <API_KEY> - Configure API credentials for this host"
|
|
echo " test - Test API credentials connectivity"
|
|
echo " update - Send package update information to server"
|
|
echo " ping - Test connectivity to server"
|
|
echo " config - Show current configuration"
|
|
echo " check-version - Check for agent updates"
|
|
echo " update-agent - Update agent to latest version"
|
|
echo " update-crontab - Update crontab with current policy"
|
|
echo " diagnostics - Show detailed system diagnostics"
|
|
echo ""
|
|
echo "Setup Process:"
|
|
echo " 1. Contact your PatchMon administrator to create a host entry"
|
|
echo " 2. Run: $0 configure <API_ID> <API_KEY> (provided by admin)"
|
|
echo " 3. Run: $0 test (to verify connection)"
|
|
echo " 4. Run: $0 update (to send initial package data)"
|
|
echo ""
|
|
echo "Configuration:"
|
|
echo " Edit $CONFIG_FILE to customize server settings"
|
|
echo " PATCHMON_SERVER=http://your-server:3001"
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Run main function
|
|
main "$@"
|