Compare commits
19 Commits
83d5cf2f8d
...
main
Author | SHA1 | Date | |
---|---|---|---|
40ab4608e2 | |||
47ddb93fef | |||
e73b81e229 | |||
39e37d0f76 | |||
31e66864ad | |||
0006eefcf1 | |||
abfaf765e6 | |||
1f2bd31380 | |||
93cea874a8 | |||
a898ebc59d | |||
78cc8cbcf3 | |||
495d0bb03b | |||
7a7d23f36c | |||
84f3ca3b0e | |||
f9f32612bb | |||
09063bfee4 | |||
5bbaff89e9 | |||
5a8561ea84 | |||
2fa32a5eb7 |
@@ -1,19 +1,25 @@
|
|||||||
#Boilerplate and support functions
|
#!/bin/bash
|
||||||
FrameworkIncludeFiles="$(ls -1 --color=none ../../../Framework-Includes/*)"
|
|
||||||
|
|
||||||
IFS=$'\n\t'
|
export PROJECT_ROOT_PATH
|
||||||
for file in ${FrameworkIncludeFiles[@]}; do
|
PROJECT_ROOT_PATH="$(realpath ../../../)"
|
||||||
source "$file"
|
|
||||||
|
#Framework variables are read from hee
|
||||||
|
|
||||||
|
export GIT_VENDOR_PATH_ROOT
|
||||||
|
GIT_VENDOR_PATH_ROOT="$PROJECT_ROOT_PATH/vendor/git@git.knownelement.com/29418/"
|
||||||
|
|
||||||
|
export KNELShellFrameworkRoot
|
||||||
|
KNELShellFrameworkRoot="$GIT_VENDOR_PATH_ROOT/KNEL/KNELShellFramework"
|
||||||
|
|
||||||
|
source $KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars
|
||||||
|
|
||||||
|
for framework_include_file in $KNELShellFrameworkRoot/Framework-Includes/*; do
|
||||||
|
source "$framework_include_file"
|
||||||
done
|
done
|
||||||
unset IFS
|
|
||||||
|
|
||||||
ProjectIncludeFiles="$(ls -1 --color=none ../../../Project-Includes/*)"
|
for project_include_file in ../../../Project-Includes/*; do
|
||||||
IFS=$'\n\t'
|
source "$project_include_file"
|
||||||
for file in ${ProjectIncludeFiles[@]}; do
|
|
||||||
source "$file"
|
|
||||||
done
|
done
|
||||||
unset IFS
|
|
||||||
|
|
||||||
|
|
||||||
print_info "Setting up librenms agent..."
|
print_info "Setting up librenms agent..."
|
||||||
|
|
||||||
|
@@ -4,19 +4,35 @@
|
|||||||
# Implements 2FA for SSH, Cockpit, and Webmin services
|
# Implements 2FA for SSH, Cockpit, and Webmin services
|
||||||
# Uses Google Authenticator (TOTP) for time-based tokens
|
# Uses Google Authenticator (TOTP) for time-based tokens
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# Source framework functions
|
#####
|
||||||
# Script can be called from different contexts, so use absolute path resolution
|
#Core framework functions...
|
||||||
SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
|
#####
|
||||||
PROJECT_ROOT="$(dirname "$(dirname "$(dirname "$SCRIPT_DIR")")")"
|
|
||||||
|
|
||||||
# Set up framework variables expected by includes
|
export PROJECT_ROOT_PATH
|
||||||
export PROJECT_ROOT_PATH="$PROJECT_ROOT"
|
PROJECT_ROOT_PATH="$(realpath ../../../)"
|
||||||
|
|
||||||
source "$PROJECT_ROOT/Framework-Includes/PrettyPrint.sh"
|
#Framework variables are read from hee
|
||||||
source "$PROJECT_ROOT/Framework-Includes/Logging.sh"
|
|
||||||
source "$PROJECT_ROOT/Framework-Includes/ErrorHandling.sh"
|
|
||||||
|
export GIT_VENDOR_PATH_ROOT
|
||||||
|
GIT_VENDOR_PATH_ROOT="$PROJECT_ROOT_PATH/vendor/git@git.knownelement.com/29418/"
|
||||||
|
|
||||||
|
export KNELShellFrameworkRoot
|
||||||
|
KNELShellFrameworkRoot="$GIT_VENDOR_PATH_ROOT/KNEL/KNELShellFramework"
|
||||||
|
|
||||||
|
source $KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars
|
||||||
|
|
||||||
|
for framework_include_file in $KNELShellFrameworkRoot/Framework-Includes/*; do
|
||||||
|
source "$framework_include_file"
|
||||||
|
done
|
||||||
|
|
||||||
|
for project_include_file in ../../../Project-Includes/*; do
|
||||||
|
source "$project_include_file"
|
||||||
|
done
|
||||||
|
|
||||||
|
#Framework variables are read from hee
|
||||||
|
source $KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars
|
||||||
|
|
||||||
# 2FA Configuration
|
# 2FA Configuration
|
||||||
BACKUP_DIR="/root/backup/2fa"
|
BACKUP_DIR="/root/backup/2fa"
|
||||||
|
@@ -1,31 +1,30 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -o errexit
|
#####
|
||||||
set -o nounset
|
#Core framework functions...
|
||||||
set -o pipefail
|
#####
|
||||||
set -o functrace
|
|
||||||
|
|
||||||
export PS4='(${BASH_SOURCE}:${LINENO}): - [${SHLVL},${BASH_SUBSHELL},$?] $ '
|
export PROJECT_ROOT_PATH
|
||||||
|
PROJECT_ROOT_PATH="$(realpath ../../)"
|
||||||
|
|
||||||
function error_out()
|
#Framework variables are read from hee
|
||||||
{
|
|
||||||
echo "Bailing out. See above for reason...."
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
function handle_failure() {
|
export GIT_VENDOR_PATH_ROOT
|
||||||
local lineno=$1
|
GIT_VENDOR_PATH_ROOT="$PROJECT_ROOT_PATH/vendor/git@git.knownelement.com/29418/"
|
||||||
local fn=$2
|
|
||||||
local exitstatus=$3
|
export KNELShellFrameworkRoot
|
||||||
local msg=$4
|
KNELShellFrameworkRoot="$GIT_VENDOR_PATH_ROOT/KNEL/KNELShellFramework"
|
||||||
local lineno_fns=${0% 0}
|
|
||||||
if [[ "$lineno_fns" != "-1" ]] ; then
|
source $KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars
|
||||||
lineno="${lineno} ${lineno_fns}"
|
|
||||||
fi
|
for framework_include_file in $KNELShellFrameworkRoot/Framework-Includes/*; do
|
||||||
echo "${BASH_SOURCE[0]}: Function: ${fn} Line Number : [${lineno}] Failed with status ${exitstatus}: $msg"
|
source "$framework_include_file"
|
||||||
}
|
done
|
||||||
|
|
||||||
|
for project_include_file in ../Project-Includes/*; do
|
||||||
|
source "$project_include_file"
|
||||||
|
done
|
||||||
|
|
||||||
trap 'handle_failure "${BASH_LINENO[*]}" "$LINENO" "${FUNCNAME[*]:-script}" "$?" "$BASH_COMMAND"' ERR
|
|
||||||
|
|
||||||
export DL_ROOT
|
export DL_ROOT
|
||||||
DL_ROOT="https://dl.knownelement.com/KNEL/FetchApply/"
|
DL_ROOT="https://dl.knownelement.com/KNEL/FetchApply/"
|
||||||
|
@@ -1,21 +1,40 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
#Core framework functions...
|
||||||
|
#########################################
|
||||||
|
|
||||||
|
export PROJECT_ROOT_PATH
|
||||||
|
PROJECT_ROOT_PATH="$(realpath ../../../)"
|
||||||
|
|
||||||
#Framework variables are read from hee
|
#Framework variables are read from hee
|
||||||
source $PROJECT_ROOT_PATH/Framework-ConfigFiles/FrameworkVars
|
|
||||||
|
|
||||||
#Boilerplate and support functions
|
|
||||||
|
|
||||||
for framework_include_file in ../Framework-Includes/*; do
|
export GIT_VENDOR_PATH_ROOT
|
||||||
|
GIT_VENDOR_PATH_ROOT="$PROJECT_ROOT_PATH/vendor/git@git.knownelement.com/29418/"
|
||||||
|
|
||||||
|
export KNELShellFrameworkRoot
|
||||||
|
KNELShellFrameworkRoot="$GIT_VENDOR_PATH_ROOT/KNEL/KNELShellFramework"
|
||||||
|
|
||||||
|
source $KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars
|
||||||
|
|
||||||
|
for framework_include_file in $KNELShellFrameworkRoot/Framework-Includes/*; do
|
||||||
source "$framework_include_file"
|
source "$framework_include_file"
|
||||||
done
|
done
|
||||||
|
|
||||||
for project_include_file in ../Project-Includes/*; do
|
for project_include_file in ../../../Project-Includes/*; do
|
||||||
source "$project_include_file"
|
source "$project_include_file"
|
||||||
done
|
done
|
||||||
|
|
||||||
# Actual script logic starts here
|
#Framework variables are read from hee
|
||||||
|
source $KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars
|
||||||
|
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
# Core script code begins here
|
||||||
|
#########################################
|
||||||
|
|
||||||
# Sourced from
|
# Sourced from
|
||||||
|
|
||||||
# https://complianceascode.readthedocs.io/en/latest/manual/developer/01_introduction.html
|
# https://complianceascode.readthedocs.io/en/latest/manual/developer/01_introduction.html
|
||||||
|
@@ -1,6 +1,24 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
for framework_include_file in ../../../Framework-Includes/*; do
|
#########################################
|
||||||
|
#Core framework functions...
|
||||||
|
#########################################
|
||||||
|
|
||||||
|
export PROJECT_ROOT_PATH
|
||||||
|
PROJECT_ROOT_PATH="$(realpath ../../../)"
|
||||||
|
|
||||||
|
#Framework variables are read from here
|
||||||
|
|
||||||
|
|
||||||
|
export GIT_VENDOR_PATH_ROOT
|
||||||
|
GIT_VENDOR_PATH_ROOT="$PROJECT_ROOT_PATH/vendor/git@git.knownelement.com/29418/"
|
||||||
|
|
||||||
|
export KNELShellFrameworkRoot
|
||||||
|
KNELShellFrameworkRoot="$GIT_VENDOR_PATH_ROOT/KNEL/KNELShellFramework"
|
||||||
|
|
||||||
|
source $KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars
|
||||||
|
|
||||||
|
for framework_include_file in $KNELShellFrameworkRoot/Framework-Includes/*; do
|
||||||
source "$framework_include_file"
|
source "$framework_include_file"
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -8,6 +26,14 @@ for project_include_file in ../../../Project-Includes/*; do
|
|||||||
source "$project_include_file"
|
source "$project_include_file"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
#Framework variables are read from hee
|
||||||
|
source $KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars
|
||||||
|
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
# Core script code begins here
|
||||||
|
#########################################
|
||||||
|
|
||||||
export SUBODEV_CHECK
|
export SUBODEV_CHECK
|
||||||
SUBODEV_CHECK="$(getent passwd | grep -c subodev || true)"
|
SUBODEV_CHECK="$(getent passwd | grep -c subodev || true)"
|
||||||
|
|
||||||
|
@@ -1,5 +1,38 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
#Core framework functions...
|
||||||
|
#########################################
|
||||||
|
|
||||||
|
export PROJECT_ROOT_PATH
|
||||||
|
PROJECT_ROOT_PATH="$(realpath ../../../)"
|
||||||
|
|
||||||
|
#Framework variables are read from here
|
||||||
|
|
||||||
|
export GIT_VENDOR_PATH_ROOT
|
||||||
|
GIT_VENDOR_PATH_ROOT="$PROJECT_ROOT_PATH/vendor/git@git.knownelement.com/29418/"
|
||||||
|
|
||||||
|
export KNELShellFrameworkRoot
|
||||||
|
KNELShellFrameworkRoot="$GIT_VENDOR_PATH_ROOT/KNEL/KNELShellFramework"
|
||||||
|
|
||||||
|
source $KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars
|
||||||
|
|
||||||
|
for framework_include_file in $KNELShellFrameworkRoot/Framework-Includes/*; do
|
||||||
|
source "$framework_include_file"
|
||||||
|
done
|
||||||
|
|
||||||
|
for project_include_file in ../../../Project-Includes/*; do
|
||||||
|
source "$project_include_file"
|
||||||
|
done
|
||||||
|
|
||||||
|
#Framework variables are read from hee
|
||||||
|
source $KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars
|
||||||
|
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
# Core script code begins here
|
||||||
|
#########################################
|
||||||
|
|
||||||
# We don't want to run this on the wazuh server, otherwise bad things happen...
|
# We don't want to run this on the wazuh server, otherwise bad things happen...
|
||||||
|
|
||||||
export TSYS_NSM_CHECK
|
export TSYS_NSM_CHECK
|
||||||
|
@@ -4,13 +4,22 @@
|
|||||||
#Core framework functions...
|
#Core framework functions...
|
||||||
#####
|
#####
|
||||||
|
|
||||||
|
|
||||||
export PROJECT_ROOT_PATH
|
export PROJECT_ROOT_PATH
|
||||||
PROJECT_ROOT_PATH="$(realpath ../)"
|
PROJECT_ROOT_PATH="$(realpath ../)"
|
||||||
|
|
||||||
#Framework variables are read from hee
|
#Framework variables are read from hee
|
||||||
source $PROJECT_ROOT_PATH/Framework-ConfigFiles/FrameworkVars
|
|
||||||
|
|
||||||
for framework_include_file in ../Framework-Includes/*; do
|
|
||||||
|
export GIT_VENDOR_PATH_ROOT
|
||||||
|
GIT_VENDOR_PATH_ROOT="$PROJECT_ROOT_PATH/vendor/git@git.knownelement.com/29418/"
|
||||||
|
|
||||||
|
export KNELShellFrameworkRoot
|
||||||
|
KNELShellFrameworkRoot="$GIT_VENDOR_PATH_ROOT/KNEL/KNELShellFramework"
|
||||||
|
|
||||||
|
source $KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars
|
||||||
|
|
||||||
|
for framework_include_file in $KNELShellFrameworkRoot/Framework-Includes/*; do
|
||||||
source "$framework_include_file"
|
source "$framework_include_file"
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -26,6 +35,9 @@ done
|
|||||||
|
|
||||||
apt-get -y install git sudo dmidecode curl
|
apt-get -y install git sudo dmidecode curl
|
||||||
|
|
||||||
|
export UBUNTU_CHECK
|
||||||
|
UBUNTU_CHECK="$(distro | grep -c Ubuntu || true)"
|
||||||
|
|
||||||
export IS_PHYSICAL_HOST
|
export IS_PHYSICAL_HOST
|
||||||
IS_PHYSICAL_HOST="$(/usr/sbin/dmidecode -t System | grep -c Dell || true)"
|
IS_PHYSICAL_HOST="$(/usr/sbin/dmidecode -t System | grep -c Dell || true)"
|
||||||
|
|
||||||
@@ -97,18 +109,16 @@ function global-installPackages() {
|
|||||||
|
|
||||||
#Remove stuff we don't want
|
#Remove stuff we don't want
|
||||||
|
|
||||||
export UBUNTU_CHECK
|
export DEBIAN_FRONTEND="noninteractive" \
|
||||||
UBUNTU_CHECK="$(distro | grep -c Ubuntu || true)"
|
&& apt-get -qq --yes --purge \
|
||||||
|
remove \
|
||||||
if [ "$UBUNTU_CHECK" -eq 1 ]; then
|
systemd-timesyncd \
|
||||||
apt-get --yes --purge remove chrony telnet inetutils-telnet
|
chrony \
|
||||||
fi
|
telnet \
|
||||||
|
inetutils-telnet \
|
||||||
if [ "$UBUNTU_CHECK" -eq 0 ]; then
|
nano \
|
||||||
apt-get --yes --purge remove systemd-timesyncd chrony telnet inetutils-telnet
|
multipath-tools \
|
||||||
fi
|
|| true
|
||||||
|
|
||||||
#export DEBIAN_FRONTEND="noninteractive" && apt-get -qq --yes -o Dpkg::Options::="--force-confold" --purge remove nano
|
|
||||||
|
|
||||||
# add stuff we want
|
# add stuff we want
|
||||||
|
|
||||||
@@ -148,6 +158,7 @@ function global-installPackages() {
|
|||||||
vim \
|
vim \
|
||||||
command-not-found \
|
command-not-found \
|
||||||
lldpd \
|
lldpd \
|
||||||
|
ansible-core \
|
||||||
net-tools \
|
net-tools \
|
||||||
dos2unix \
|
dos2unix \
|
||||||
gpg \
|
gpg \
|
||||||
@@ -337,7 +348,7 @@ function global-postPackageConfiguration() {
|
|||||||
function secharden-ssh() {
|
function secharden-ssh() {
|
||||||
print_info "Now running $FUNCNAME"
|
print_info "Now running $FUNCNAME"
|
||||||
|
|
||||||
cd ./Modules/Security
|
cd ./Modules/Security || exit
|
||||||
bash ./secharden-ssh.sh
|
bash ./secharden-ssh.sh
|
||||||
cd -
|
cd -
|
||||||
|
|
||||||
@@ -346,7 +357,33 @@ function secharden-ssh() {
|
|||||||
|
|
||||||
function secharden-wazuh() {
|
function secharden-wazuh() {
|
||||||
print_info "Now running $FUNCNAME"
|
print_info "Now running $FUNCNAME"
|
||||||
bash ./Modules/Security/secharden-wazuh.sh
|
cd ./Modules/Security || exit
|
||||||
|
bash ./secharden-wazuh.sh
|
||||||
|
cd -
|
||||||
|
print_info "Completed running $FUNCNAME"
|
||||||
|
}
|
||||||
|
|
||||||
|
function secharden-2fa() {
|
||||||
|
print_info "Now running $FUNCNAME"
|
||||||
|
cd ./Modules/Security || exit
|
||||||
|
bash ./secharden-2fa.sh
|
||||||
|
cd -
|
||||||
|
print_info "Completed running $FUNCNAME"
|
||||||
|
}
|
||||||
|
|
||||||
|
function secharden-scap-stig() {
|
||||||
|
print_info "Now running $FUNCNAME"
|
||||||
|
cd ./Modules/Security || exit
|
||||||
|
bash ./secharden-scap-stig.sh
|
||||||
|
cd -
|
||||||
|
print_info "Completed running $FUNCNAME"
|
||||||
|
}
|
||||||
|
|
||||||
|
function secharden-agents() {
|
||||||
|
print_info "Now running $FUNCNAME"
|
||||||
|
cd ./Modules/Security || exit
|
||||||
|
bash ./secharden-audit-agents.sh
|
||||||
|
cd -
|
||||||
print_info "Completed running $FUNCNAME"
|
print_info "Completed running $FUNCNAME"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,23 +393,8 @@ function secharden-auto-upgrades() {
|
|||||||
print_info "Completed running $FUNCNAME"
|
print_info "Completed running $FUNCNAME"
|
||||||
}
|
}
|
||||||
|
|
||||||
function secharden-2fa() {
|
|
||||||
print_info "Now running $FUNCNAME"
|
|
||||||
bash ./Modules/Security/secharden-2fa.sh
|
|
||||||
print_info "Completed running $FUNCNAME"
|
|
||||||
}
|
|
||||||
|
|
||||||
function secharden-agents() {
|
|
||||||
print_info "Now running $FUNCNAME"
|
|
||||||
#curl --silent ${DL_ROOT}/Modules/Security/secharden-audit-agents.sh|$(which bash)
|
|
||||||
print_info "Completed running $FUNCNAME"
|
|
||||||
}
|
|
||||||
|
|
||||||
function secharden-scap-stig() {
|
|
||||||
print_info "Now running $FUNCNAME"
|
|
||||||
bash ./Modules/Security/secharden-scap-stig.sh
|
|
||||||
print_info "Completed running $FUNCNAME"
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
# Authentication
|
# Authentication
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
function DebugMe() {
|
function DebugMe() {
|
||||||
[[ $script_debug = 1 ]] && "$@" || :
|
[[ $script_debug = 1 ]] && "$@" || :
|
||||||
|
|
||||||
|
273
vendor/git@git.knownelement.com/29418/KNEL/KNELShellFramework/Framework-Includes/SafeDownload.sh
vendored
Executable file
273
vendor/git@git.knownelement.com/29418/KNEL/KNELShellFramework/Framework-Includes/SafeDownload.sh
vendored
Executable file
@@ -0,0 +1,273 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Safe Download Framework
|
||||||
|
# Provides robust download operations with error handling, retries, and validation
|
||||||
|
# Author: TSYS Development Team
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Source framework dependencies
|
||||||
|
source "$(dirname "${BASH_SOURCE[0]}")/PrettyPrint.sh" 2>/dev/null || echo "Warning: PrettyPrint.sh not found"
|
||||||
|
source "$(dirname "${BASH_SOURCE[0]}")/Logging.sh" 2>/dev/null || echo "Warning: Logging.sh not found"
|
||||||
|
|
||||||
|
# Download configuration
|
||||||
|
declare -g DOWNLOAD_TIMEOUT=60
|
||||||
|
declare -g DOWNLOAD_CONNECT_TIMEOUT=30
|
||||||
|
declare -g DOWNLOAD_MAX_ATTEMPTS=3
|
||||||
|
declare -g DOWNLOAD_RETRY_DELAY=5
|
||||||
|
|
||||||
|
# Safe download with retry logic and error handling
|
||||||
|
function safe_download() {
|
||||||
|
local url="$1"
|
||||||
|
local dest="$2"
|
||||||
|
local expected_checksum="${3:-}"
|
||||||
|
local max_attempts="${4:-$DOWNLOAD_MAX_ATTEMPTS}"
|
||||||
|
|
||||||
|
local attempt=1
|
||||||
|
local temp_file="${dest}.tmp.$$"
|
||||||
|
|
||||||
|
# Validate inputs
|
||||||
|
if [[ -z "$url" || -z "$dest" ]]; then
|
||||||
|
print_error "safe_download: URL and destination are required"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create destination directory if needed
|
||||||
|
local dest_dir
|
||||||
|
dest_dir="$(dirname "$dest")"
|
||||||
|
if [[ ! -d "$dest_dir" ]]; then
|
||||||
|
if ! mkdir -p "$dest_dir"; then
|
||||||
|
print_error "Failed to create directory: $dest_dir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_info "Downloading: $(basename "$dest") from $url"
|
||||||
|
|
||||||
|
while [[ $attempt -le $max_attempts ]]; do
|
||||||
|
if curl --silent --show-error --fail \
|
||||||
|
--connect-timeout "$DOWNLOAD_CONNECT_TIMEOUT" \
|
||||||
|
--max-time "$DOWNLOAD_TIMEOUT" \
|
||||||
|
--location \
|
||||||
|
--user-agent "TSYS-FetchApply/1.0" \
|
||||||
|
"$url" > "$temp_file"; then
|
||||||
|
|
||||||
|
# Verify checksum if provided
|
||||||
|
if [[ -n "$expected_checksum" ]]; then
|
||||||
|
if verify_checksum "$temp_file" "$expected_checksum"; then
|
||||||
|
mv "$temp_file" "$dest"
|
||||||
|
print_success "Downloaded and verified: $(basename "$dest")"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
print_error "Checksum verification failed for: $(basename "$dest")"
|
||||||
|
rm -f "$temp_file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
mv "$temp_file" "$dest"
|
||||||
|
print_success "Downloaded: $(basename "$dest")"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
print_warning "Download attempt $attempt failed: $(basename "$dest")"
|
||||||
|
rm -f "$temp_file"
|
||||||
|
|
||||||
|
if [[ $attempt -lt $max_attempts ]]; then
|
||||||
|
print_info "Retrying in ${DOWNLOAD_RETRY_DELAY}s..."
|
||||||
|
sleep "$DOWNLOAD_RETRY_DELAY"
|
||||||
|
fi
|
||||||
|
|
||||||
|
((attempt++))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
print_error "Failed to download after $max_attempts attempts: $(basename "$dest")"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Verify file checksum
|
||||||
|
function verify_checksum() {
|
||||||
|
local file="$1"
|
||||||
|
local expected_checksum="$2"
|
||||||
|
|
||||||
|
if [[ ! -f "$file" ]]; then
|
||||||
|
print_error "File not found for checksum verification: $file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local actual_checksum
|
||||||
|
actual_checksum=$(sha256sum "$file" | cut -d' ' -f1)
|
||||||
|
|
||||||
|
if [[ "$actual_checksum" == "$expected_checksum" ]]; then
|
||||||
|
print_success "Checksum verified: $(basename "$file")"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
print_error "Checksum mismatch for $(basename "$file")"
|
||||||
|
print_error "Expected: $expected_checksum"
|
||||||
|
print_error "Actual: $actual_checksum"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Batch download multiple files
|
||||||
|
function batch_download() {
|
||||||
|
local -n download_map=$1
|
||||||
|
local failed_downloads=0
|
||||||
|
|
||||||
|
print_info "Starting batch download of ${#download_map[@]} files..."
|
||||||
|
|
||||||
|
for url in "${!download_map[@]}"; do
|
||||||
|
local dest="${download_map[$url]}"
|
||||||
|
if ! safe_download "$url" "$dest"; then
|
||||||
|
((failed_downloads++))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ $failed_downloads -eq 0 ]]; then
|
||||||
|
print_success "All batch downloads completed successfully"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
print_error "$failed_downloads batch downloads failed"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Download with progress indication for large files
|
||||||
|
function safe_download_with_progress() {
|
||||||
|
local url="$1"
|
||||||
|
local dest="$2"
|
||||||
|
local expected_checksum="${3:-}"
|
||||||
|
|
||||||
|
print_info "Downloading with progress: $(basename "$dest")"
|
||||||
|
|
||||||
|
if curl --progress-bar --show-error --fail \
|
||||||
|
--connect-timeout "$DOWNLOAD_CONNECT_TIMEOUT" \
|
||||||
|
--max-time "$DOWNLOAD_TIMEOUT" \
|
||||||
|
--location \
|
||||||
|
--user-agent "TSYS-FetchApply/1.0" \
|
||||||
|
"$url" -o "$dest"; then
|
||||||
|
|
||||||
|
# Verify checksum if provided
|
||||||
|
if [[ -n "$expected_checksum" ]]; then
|
||||||
|
if verify_checksum "$dest" "$expected_checksum"; then
|
||||||
|
print_success "Downloaded and verified: $(basename "$dest")"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
rm -f "$dest"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
print_success "Downloaded: $(basename "$dest")"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
print_error "Failed to download: $(basename "$dest")"
|
||||||
|
rm -f "$dest"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if URL is accessible
|
||||||
|
function check_url_accessibility() {
|
||||||
|
local url="$1"
|
||||||
|
|
||||||
|
if curl --silent --head --fail \
|
||||||
|
--connect-timeout "$DOWNLOAD_CONNECT_TIMEOUT" \
|
||||||
|
--max-time 10 \
|
||||||
|
"$url" >/dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validate all required URLs before starting deployment
|
||||||
|
function validate_required_urls() {
|
||||||
|
local -a urls=("$@")
|
||||||
|
local failed_urls=0
|
||||||
|
|
||||||
|
print_info "Validating accessibility of ${#urls[@]} URLs..."
|
||||||
|
|
||||||
|
for url in "${urls[@]}"; do
|
||||||
|
if check_url_accessibility "$url"; then
|
||||||
|
print_success "✓ $url"
|
||||||
|
else
|
||||||
|
print_error "✗ $url"
|
||||||
|
((failed_urls++))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ $failed_urls -eq 0 ]]; then
|
||||||
|
print_success "All URLs are accessible"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
print_error "$failed_urls URLs are not accessible"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Download configuration files with backup
|
||||||
|
function safe_config_download() {
|
||||||
|
local url="$1"
|
||||||
|
local dest="$2"
|
||||||
|
local backup_suffix="${3:-.bak.$(date +%Y%m%d-%H%M%S)}"
|
||||||
|
|
||||||
|
# Backup existing file if it exists
|
||||||
|
if [[ -f "$dest" ]]; then
|
||||||
|
local backup_file="${dest}${backup_suffix}"
|
||||||
|
if cp "$dest" "$backup_file"; then
|
||||||
|
print_info "Backed up existing config: $backup_file"
|
||||||
|
else
|
||||||
|
print_error "Failed to backup existing config: $dest"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Download new configuration
|
||||||
|
if safe_download "$url" "$dest"; then
|
||||||
|
print_success "Configuration updated: $(basename "$dest")"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
# Restore backup if download failed and backup exists
|
||||||
|
local backup_file="${dest}${backup_suffix}"
|
||||||
|
if [[ -f "$backup_file" ]]; then
|
||||||
|
if mv "$backup_file" "$dest"; then
|
||||||
|
print_warning "Restored backup after failed download: $(basename "$dest")"
|
||||||
|
else
|
||||||
|
print_error "Failed to restore backup: $(basename "$dest")"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test network connectivity to common endpoints
|
||||||
|
function test_network_connectivity() {
|
||||||
|
local test_urls=(
|
||||||
|
"https://archive.ubuntu.com"
|
||||||
|
"https://github.com"
|
||||||
|
"https://curl.haxx.se"
|
||||||
|
)
|
||||||
|
|
||||||
|
print_info "Testing network connectivity..."
|
||||||
|
|
||||||
|
for url in "${test_urls[@]}"; do
|
||||||
|
if check_url_accessibility "$url"; then
|
||||||
|
print_success "Network connectivity confirmed: $url"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
print_error "No network connectivity detected"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Export functions for use in other scripts
|
||||||
|
export -f safe_download
|
||||||
|
export -f verify_checksum
|
||||||
|
export -f batch_download
|
||||||
|
export -f safe_download_with_progress
|
||||||
|
export -f check_url_accessibility
|
||||||
|
export -f validate_required_urls
|
||||||
|
export -f safe_config_download
|
||||||
|
export -f test_network_connectivity
|
Reference in New Issue
Block a user