Route every host built by this project through the new pfv-netinfra-01 (192.168.3.252) / pfv-netinfra-02 (192.168.3.253) pair for both name resolution and time, with automatic failover. - NTP: replace the single pfv-netboot.knel.net upstream with both netinfra servers (iburst) so time sync survives either one failing. - DNS: add a managed static /etc/resolv.conf (new ConfigFiles/Resolv/). The repo previously had no resolver configuration at all. Both servers are listed so glibc falls through to the secondary on failure. - DHCP: request domain-name-servers/domain-search/ntp-servers and supersede them to the netinfra pair, so a DHCP renew can't silently revert to whatever the DHCP server advertises. - SetupNewSystem.sh: deploy resolv.conf (robustly replacing any systemd-resolved/NetworkManager symlink) and add pfv-netinfra to the NTP-server self-exclusion guard so those boxes don't client off themselves. LAN IPs are used throughout (not the knel.net hostnames) because those hostnames resolve to Tailscale CGNAT addresses, not the LAN addresses, and NTP must come up before DNS. Add a validation test asserting the config is present and both servers actually answer DNS and NTP queries. 🤖 Generated with [Crush](https://github.com/charmassociates/crush) Assisted-by: GLM-5 via Crush <crush@charm.land>
432 lines
11 KiB
Bash
432 lines
11 KiB
Bash
#!/usr/bin/bash
|
|
|
|
#####
|
|
#Core framework functions...
|
|
#####
|
|
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
export PROJECT_ROOT_PATH
|
|
PROJECT_ROOT_PATH="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
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"
|
|
|
|
export CONFIGFILES_PATH
|
|
CONFIGFILES_PATH="$PROJECT_ROOT_PATH/ProjectCode/ConfigFiles"
|
|
|
|
export MODULES_PATH
|
|
MODULES_PATH="$PROJECT_ROOT_PATH/ProjectCode/Modules"
|
|
|
|
export SCRIPTS_PATH
|
|
SCRIPTS_PATH="$PROJECT_ROOT_PATH/ProjectCode/scripts"
|
|
|
|
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_ROOT_PATH"/Project-Includes/*; do
|
|
source "$project_include_file"
|
|
done
|
|
|
|
# Start actual script logic here...
|
|
|
|
#################
|
|
#Global variables
|
|
#################
|
|
|
|
apt-get -y install git sudo dmidecode curl
|
|
|
|
export UBUNTU_CHECK
|
|
UBUNTU_CHECK="$(distro | grep -c Ubuntu || true)"
|
|
|
|
export IS_PHYSICAL_HOST
|
|
IS_PHYSICAL_HOST="$(/usr/sbin/dmidecode -t System | grep -c Dell || true)"
|
|
|
|
export SUBODEV_CHECK
|
|
SUBODEV_CHECK="$(getent passwd | grep -c subodev || true)"
|
|
|
|
export LOCALUSER_CHECK
|
|
LOCALUSER_CHECK="$(getent passwd | grep -c localuser || true)"
|
|
|
|
#######################
|
|
# Support functions
|
|
#######################
|
|
|
|
function global-oam() {
|
|
print_info "Now running $FUNCNAME...."
|
|
|
|
cat "$SCRIPTS_PATH/up2date.sh" >/usr/local/bin/up2date.sh && chmod +x /usr/local/bin/up2date.sh
|
|
|
|
bash "$MODULES_PATH/OAM/oam-librenms.sh"
|
|
|
|
print_info "Completed running $FUNCNAME"
|
|
|
|
}
|
|
|
|
function global-systemServiceConfigurationFiles() {
|
|
print_info "Now running $FUNCNAME...."
|
|
|
|
cat "$CONFIGFILES_PATH/ZSH/tsys-zshrc" >/etc/zshrc
|
|
cat "$CONFIGFILES_PATH/SMTP/aliases" >/etc/aliases
|
|
cat "$CONFIGFILES_PATH/Syslog/rsyslog.conf" >/etc/rsyslog.conf
|
|
|
|
newaliases
|
|
|
|
print_info "Completed running $FUNCNAME"
|
|
}
|
|
|
|
function global-installPackages() {
|
|
print_info "Now running $FUNCNAME...."
|
|
|
|
# Setup webmin repo, used for RBAC/2fa PAM
|
|
|
|
curl https://raw.githubusercontent.com/webmin/webmin/master/webmin-setup-repo.sh >/tmp/webmin-setup.sh
|
|
sh /tmp/webmin-setup.sh -f && rm -f /tmp/webmin-setup.sh
|
|
|
|
# Setup tailscale
|
|
|
|
curl -fsSL https://tailscale.com/install.sh | sh
|
|
|
|
#
|
|
#Patch the system
|
|
#
|
|
|
|
/usr/local/bin/up2date.sh
|
|
|
|
#Remove stuff we don't want
|
|
|
|
export DEBIAN_FRONTEND="noninteractive" \
|
|
&& apt-get -qq --yes --purge \
|
|
remove \
|
|
systemd-timesyncd \
|
|
chrony \
|
|
telnet \
|
|
inetutils-telnet \
|
|
wpasupplicant \
|
|
modemmanager \
|
|
nano \
|
|
multipath-tools \
|
|
|| true
|
|
|
|
apt-get -y --purge autoremove
|
|
|
|
# add stuff we want
|
|
|
|
print_info ""Now installing all the packages...""
|
|
|
|
DEBIAN_FRONTEND="noninteractive" apt-get -qq --yes -o Dpkg::Options::="--force-confold" install \
|
|
virt-what \
|
|
auditd \
|
|
audispd-plugins \
|
|
cloud-guest-utils \
|
|
aide \
|
|
htop \
|
|
snmpd \
|
|
ncdu \
|
|
iftop \
|
|
iotop \
|
|
cockpit \
|
|
cockpit-bridge \
|
|
cockpit-doc \
|
|
cockpit-networkmanager \
|
|
cockpit-packagekit \
|
|
cockpit-pcp \
|
|
cockpit-sosreport \
|
|
cockpit-storaged \
|
|
cockpit-system \
|
|
cockpit-ws \
|
|
nethogs \
|
|
sysstat \
|
|
ngrep \
|
|
acct \
|
|
lsb-release \
|
|
screen \
|
|
tailscale \
|
|
tmux \
|
|
vim \
|
|
command-not-found \
|
|
lldpd \
|
|
ansible-core \
|
|
net-tools \
|
|
dos2unix \
|
|
gpg \
|
|
molly-guard \
|
|
lshw \
|
|
fzf \
|
|
ripgrep \
|
|
sudo \
|
|
mailutils \
|
|
clamav \
|
|
sl \
|
|
logwatch \
|
|
git \
|
|
net-tools \
|
|
tshark \
|
|
tcpdump \
|
|
lynis \
|
|
glances \
|
|
zsh \
|
|
zsh-autosuggestions \
|
|
zsh-syntax-highlighting \
|
|
fonts-powerline \
|
|
webmin \
|
|
usermin \
|
|
ntpsec \
|
|
ntpsec-ntpdate \
|
|
tuned \
|
|
cockpit \
|
|
iptables \
|
|
netfilter-persistent \
|
|
iptables-persistent \
|
|
pflogsumm \
|
|
postfix
|
|
|
|
export KALI_CHECK
|
|
KALI_CHECK="$(distro | grep -c kali || true)"
|
|
|
|
export VIRT_TYPE
|
|
VIRT_TYPE="$(virt-what)"
|
|
|
|
export IS_VIRT_GUEST
|
|
IS_VIRT_GUEST="$(echo "$VIRT_TYPE" | egrep -c 'hyperv|kvm' || true)"
|
|
|
|
export IS_KVM_GUEST
|
|
IS_KVM_GUEST="$(echo "$VIRT_TYPE" | grep -c 'kvm' || true)"
|
|
|
|
if [[ $IS_KVM_GUEST = 1 ]]; then
|
|
apt -y install qemu-guest-agent
|
|
fi
|
|
|
|
if [[ $KALI_CHECK -eq 0 ]];then
|
|
DEBIAN_FRONTEND="noninteractive" apt-get -qq --yes -o Dpkg::Options::="--force-confold" install \
|
|
latencytop \
|
|
cockpit-tests || true
|
|
fi
|
|
|
|
if [[ $IS_PHYSICAL_HOST -gt 0 ]]; then
|
|
export DEBIAN_FRONTEND="noninteractive" && apt-get -qq --yes -o Dpkg::Options::="--force-confold" install \
|
|
i7z \
|
|
thermald \
|
|
cpufrequtils \
|
|
linux-cpupower
|
|
# power-profiles-daemon
|
|
fi
|
|
|
|
############################
|
|
# Secrets agents
|
|
############################
|
|
|
|
# bitwarden cli
|
|
|
|
# vault cli
|
|
|
|
print_info "Completed running $FUNCNAME"
|
|
}
|
|
|
|
function global-postPackageConfiguration() {
|
|
|
|
print_info "Now running $FUNCNAME"
|
|
|
|
systemctl --now enable auditd
|
|
|
|
systemctl stop postfix
|
|
|
|
cat "$CONFIGFILES_PATH/SMTP/postfix_generic" >/etc/postfix/generic
|
|
postmap /etc/postfix/generic
|
|
|
|
postconf -e "inet_protocols = ipv4"
|
|
postconf -e "inet_interfaces = 127.0.0.1"
|
|
postconf -e "mydestination= 127.0.0.1"
|
|
postconf -e "relayhost = tsys-cloudron.knel.net"
|
|
postconf -e "smtp_generic_maps = hash:/etc/postfix/generic"
|
|
# smtp_generic_maps = hash:/etc/postfix/generic
|
|
|
|
systemctl restart postfix
|
|
|
|
#This is under test/dev and may fail
|
|
echo "hi from root to root" | mail -s "hi directly to root from $(hostname)" root
|
|
|
|
chsh -s $(which zsh) root
|
|
|
|
if [ "$LOCALUSER_CHECK" -gt 0 ]; then
|
|
chsh -s "$(which zsh)" localuser
|
|
fi
|
|
|
|
if [ "$SUBODEV_CHECK" -gt 0 ]; then
|
|
chsh -s "$(which zsh)" subodev
|
|
fi
|
|
|
|
###Post package deployment bits
|
|
|
|
cat "$CONFIGFILES_PATH/DHCP/dhclient.conf" >/etc/dhcp/dhclient.conf
|
|
|
|
# Authoritative recursive DNS via the redundant pfv-netinfra-01/02 pair.
|
|
# Replace whatever is at /etc/resolv.conf (including a systemd-resolved or
|
|
# NetworkManager symlink) with the managed static file so every lookup goes
|
|
# to our servers and nothing else rewrites it behind our backs.
|
|
rm -f /etc/resolv.conf
|
|
cat "$CONFIGFILES_PATH/Resolv/resolv.conf" >/etc/resolv.conf
|
|
chmod 644 /etc/resolv.conf
|
|
|
|
systemctl stop snmpd && /etc/init.d/snmpd stop
|
|
|
|
cat "$CONFIGFILES_PATH/SNMP/snmp-sudo.conf" >/etc/sudoers.d/Debian-snmp
|
|
sed -i "s|-Lsd|-LS6d|" /lib/systemd/system/snmpd.service
|
|
|
|
pi-detect
|
|
|
|
if [ "$IS_RASPI" = 1 ]; then
|
|
cat "$CONFIGFILES_PATH/SNMP/snmpd-rpi.conf" >/etc/snmp/snmpd.conf || true
|
|
fi
|
|
|
|
if [ "$IS_PHYSICAL_HOST" = 1 ]; then
|
|
cat "$CONFIGFILES_PATH/SNMP/snmpd-physicalhost.conf" >/etc/snmp/snmpd.conf || true
|
|
fi
|
|
|
|
if [ "$IS_VIRT_GUEST" = 1 ]; then
|
|
cat "$CONFIGFILES_PATH/SNMP/snmpd.conf" >/etc/snmp/snmpd.conf || true
|
|
fi
|
|
|
|
systemctl daemon-reload && systemctl restart snmpd && /etc/init.d/snmpd restart
|
|
|
|
cat "$CONFIGFILES_PATH/NetworkDiscovery/lldpd" >/etc/default/lldpd
|
|
systemctl restart lldpd
|
|
|
|
cat "$CONFIGFILES_PATH/Cockpit/disallowed-users" >/etc/cockpit/disallowed-users
|
|
systemctl restart cockpit
|
|
|
|
export LIBRENMS_CHECK
|
|
LIBRENMS_CHECK="$(hostname | grep -c tsys-librenms || true)"
|
|
|
|
if [ "$LIBRENMS_CHECK" -eq 0 ]; then
|
|
DEBIAN_FRONTEND="noninteractive" apt-get -qq --yes -o Dpkg::Options::="--force-confold" install rsyslog
|
|
systemctl stop rsyslog
|
|
systemctl start rsyslog
|
|
fi
|
|
|
|
export NTP_SERVER_CHECK
|
|
NTP_SERVER_CHECK="$(hostname | egrep -c 'pfv-netboot|pfvsvrpi|pfv-netinfra' || true)"
|
|
|
|
if [ "$NTP_SERVER_CHECK" -eq 0 ]; then
|
|
|
|
cat "$CONFIGFILES_PATH/NTP/ntp.conf" >/etc/ntpsec/ntp.conf
|
|
systemctl restart ntpsec.service
|
|
fi
|
|
|
|
systemctl stop postfix
|
|
systemctl start postfix
|
|
|
|
/usr/sbin/accton on
|
|
|
|
if [ "$IS_PHYSICAL_HOST" -gt 0 ]; then
|
|
cpufreq-set -r -g performance
|
|
cpupower frequency-set --governor performance
|
|
|
|
# Potentially merge the below if needed.
|
|
# power-profiles-daemon
|
|
# powerprofilesctl set performance
|
|
#tsys1# systemctl enable power-profiles-daemon
|
|
#tsys1# systemctl start power-profiles-daemon
|
|
|
|
fi
|
|
|
|
if [ "$IS_VIRT_GUEST" = 1 ]; then
|
|
tuned-adm profile virtual-guest
|
|
fi
|
|
|
|
print_info "Completed running $FUNCNAME"
|
|
}
|
|
|
|
####################################################################################################
|
|
# Run various modules
|
|
####################################################################################################
|
|
|
|
####################################################################################################
|
|
# Security Hardening
|
|
####################################################################################################
|
|
|
|
# SSH
|
|
|
|
function secharden-ssh() {
|
|
print_info "Now running $FUNCNAME"
|
|
|
|
bash "$MODULES_PATH/Security/secharden-ssh.sh"
|
|
|
|
print_info "Completed running $FUNCNAME"
|
|
}
|
|
|
|
function secharden-wazuh() {
|
|
print_info "Now running $FUNCNAME"
|
|
bash "$MODULES_PATH/Security/secharden-wazuh.sh"
|
|
print_info "Completed running $FUNCNAME"
|
|
}
|
|
|
|
function secharden-2fa() {
|
|
print_info "Now running $FUNCNAME"
|
|
bash "$MODULES_PATH/Security/secharden-2fa.sh"
|
|
print_info "Completed running $FUNCNAME"
|
|
}
|
|
|
|
function secharden-scap-stig() {
|
|
print_info "Now running $FUNCNAME"
|
|
bash "$MODULES_PATH/Security/secharden-scap-stig.sh"
|
|
print_info "Completed running $FUNCNAME"
|
|
}
|
|
|
|
function secharden-agents() {
|
|
print_info "Now running $FUNCNAME"
|
|
bash "$MODULES_PATH/Security/secharden-audit-agents.sh"
|
|
print_info "Completed running $FUNCNAME"
|
|
}
|
|
|
|
function secharden-auto-upgrades() {
|
|
print_info "Now running $FUNCNAME"
|
|
#curl --silent ${DL_ROOT}/Modules/Security/secharden-ssh.sh|$(which bash)
|
|
print_info "Completed running $FUNCNAME"
|
|
}
|
|
|
|
|
|
|
|
|
|
####################################################################################################
|
|
# Authentication
|
|
####################################################################################################
|
|
|
|
function auth-cloudron-ldap() {
|
|
print_info "Now running "$FUNCNAME""
|
|
#curl --silent ${DL_ROOT}/Modules/Auth/auth-cloudron-ldap.sh|$(which bash)
|
|
print_info "Completed running "$FUNCNAME""
|
|
}
|
|
|
|
####################################################################################################
|
|
# RUn the various functions in the correct order
|
|
####################################################################################################
|
|
|
|
echo >$LOGFILENAME
|
|
|
|
print_info "Execution starting at $CURRENT_TIMESTAMP..."
|
|
|
|
PreflightCheck
|
|
global-oam
|
|
global-installPackages
|
|
global-systemServiceConfigurationFiles
|
|
global-postPackageConfiguration
|
|
|
|
secharden-ssh
|
|
secharden-wazuh
|
|
secharden-scap-stig
|
|
secharden-2fa
|
|
#secharden-agents
|
|
#secharden-auto-upgrades
|
|
|
|
#auth-cloudron-ldap
|
|
|
|
print_info "Execution ended at $CURRENT_TIMESTAMP..."
|