Setup Script & Actual Firewall DNS Scripts. As well as optional functions to do automated setups
This commit is contained in:
parent
dbff960aad
commit
4d6f810100
9 changed files with 404 additions and 14 deletions
53
core/assets/sudo_scripts/dns
Normal file
53
core/assets/sudo_scripts/dns
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ "$EUID" -ne 0 ]]; then
|
||||||
|
echo "[killswitch] ERROR: must be run as root" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ACTION="${1:-}"
|
||||||
|
IFACE="${2:-}"
|
||||||
|
DNS="${3:-}"
|
||||||
|
|
||||||
|
|
||||||
|
_check_prereqs() {
|
||||||
|
[[ -z "$DNS" ]] && { echo "Error: DNS IP required" >&2; exit 1; }
|
||||||
|
|
||||||
|
# ✓ Check it's a valid IPv4 address:
|
||||||
|
if ! [[ "$DNS" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}$ ]]; then
|
||||||
|
echo "Error: Invalid IP: $DNS" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ✓ checks interface exists before configuring
|
||||||
|
if ! ip link show "$IFACE" &>/dev/null; then
|
||||||
|
echo "Error: Interface $IFACE not found" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_set_dns() {
|
||||||
|
resolvectl dns "$IFACE" "$DNS" || {
|
||||||
|
echo "ERROR: Failed to set DNS to $DNS" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
resolvectl domain "$IFACE" '~.' || {
|
||||||
|
echo "ERROR: Failed to set domain routing" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
resolvectl default-route "$IFACE" true || {
|
||||||
|
echo "ERROR: Failed to set default route" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "$ACTION" == "set" ]]; then
|
||||||
|
_check_prereqs
|
||||||
|
_set_dns
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$ACTION" == "revert" ]]; then
|
||||||
|
resolvectl revert "$IFACE" 2>/dev/null || true
|
||||||
|
|
||||||
|
fi
|
||||||
120
core/assets/sudo_scripts/firewall
Normal file
120
core/assets/sudo_scripts/firewall
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ "$EUID" -ne 0 ]]; then
|
||||||
|
echo "[killswitch] ERROR: must be run as root" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ACTION="${1:-}"
|
||||||
|
SERVER_IP="${2:-}"
|
||||||
|
TUNNEL_IF="${3:-}"
|
||||||
|
INTERNAL_SUBNET="${4:-}"
|
||||||
|
TABLE="hydraveil"
|
||||||
|
|
||||||
|
if [[ "$ACTION" != "arm" && "$ACTION" != "disarm" && "$ACTION" != "status" ]]; then
|
||||||
|
echo "[killswitch] ERROR: invalid action '$ACTION'. Usage: arm <server_ip> <tunnel_if> [internal_subnet] | disarm | status" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_default_iface() {
|
||||||
|
ip route show default 2>/dev/null | awk 'NR==1{print $5}'
|
||||||
|
}
|
||||||
|
|
||||||
|
_log() {
|
||||||
|
local level="$1"; shift
|
||||||
|
echo "[killswitch] [$level] $* — $(date '+%Y-%m-%d %H:%M:%S')" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "$ACTION" == "status" ]]; then
|
||||||
|
if nft list table inet "$TABLE" &>/dev/null 2>&1; then
|
||||||
|
echo "armed"
|
||||||
|
else
|
||||||
|
echo "disarmed"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$ACTION" == "disarm" ]]; then
|
||||||
|
if nft list table inet "$TABLE" &>/dev/null 2>&1; then
|
||||||
|
nft delete table inet "$TABLE"
|
||||||
|
_log "INFO" "disarmed"
|
||||||
|
else
|
||||||
|
_log "INFO" "already disarmed"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ -z "$SERVER_IP" ]] && { _log "ERROR" "server_ip required for arm"; exit 1; }
|
||||||
|
[[ -z "$TUNNEL_IF" ]] && { _log "ERROR" "tunnel_if required for arm"; exit 1; }
|
||||||
|
|
||||||
|
if ! [[ "$SERVER_IP" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
||||||
|
_log "ERROR" "invalid IPv4: $SERVER_IP"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
IFS='.' read -r o1 o2 o3 o4 <<< "$SERVER_IP"
|
||||||
|
for oct in "$o1" "$o2" "$o3" "$o4"; do
|
||||||
|
if (( oct > 255 )); then
|
||||||
|
_log "ERROR" "invalid IPv4 octet ($oct) in $SERVER_IP"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
WAN_IFACE=$(_default_iface)
|
||||||
|
if [[ -z "$WAN_IFACE" ]]; then
|
||||||
|
_log "ERROR" "could not detect primary network interface"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
INTERNAL_RULE=""
|
||||||
|
if [[ -n "$INTERNAL_SUBNET" ]]; then
|
||||||
|
INTERNAL_RULE=" ip daddr ${INTERNAL_SUBNET} accept"
|
||||||
|
fi
|
||||||
|
|
||||||
|
nft list table inet "$TABLE" &>/dev/null 2>&1 && nft delete table inet "$TABLE" || true
|
||||||
|
|
||||||
|
nft -f - << NFTEOF
|
||||||
|
table inet ${TABLE} {
|
||||||
|
chain output {
|
||||||
|
type filter hook output priority filter; policy drop;
|
||||||
|
oifname "lo" accept
|
||||||
|
ether type arp drop
|
||||||
|
ip6 daddr != ::1 drop
|
||||||
|
ip daddr 224.0.0.0/4 drop
|
||||||
|
ip daddr 255.255.255.255 drop
|
||||||
|
ip daddr 192.168.1.0/24 drop
|
||||||
|
|
||||||
|
oifname "${WAN_IFACE}" ip daddr ${SERVER_IP} accept
|
||||||
|
oifname "${TUNNEL_IF}" accept
|
||||||
|
log prefix "hydraveil-drop " drop
|
||||||
|
}
|
||||||
|
|
||||||
|
chain input {
|
||||||
|
type filter hook input priority filter; policy drop;
|
||||||
|
iifname "lo" accept
|
||||||
|
|
||||||
|
ether type arp drop
|
||||||
|
ip6 saddr != ::1 drop
|
||||||
|
ip daddr 224.0.0.0/4 drop
|
||||||
|
ip daddr 255.255.255.255 drop
|
||||||
|
|
||||||
|
ct state established,related accept
|
||||||
|
iifname "${WAN_IFACE}" ip saddr ${SERVER_IP} accept
|
||||||
|
iifname "${TUNNEL_IF}" accept
|
||||||
|
|
||||||
|
log prefix "hydraveil-drop " drop
|
||||||
|
}
|
||||||
|
chain forward {
|
||||||
|
type filter hook forward priority filter; policy drop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NFTEOF
|
||||||
|
|
||||||
|
|
||||||
|
_log "INFO" "armed — wan=${WAN_IFACE} server=${SERVER_IP} tunnel=${TUNNEL_IF} internal=${INTERNAL_SUBNET:-none}"
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
102
core/assets/sudo_scripts/setup.sh
Normal file
102
core/assets/sudo_scripts/setup.sh
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
ORIGINAL_FOLDER="${ORIGINAL_FOLDER:-$(pwd)}"
|
||||||
|
TARGET_FOLDER="${TARGET_FOLDER:-/opt/hydra-veil}"
|
||||||
|
LINUX_USER="${LINUX_USER:-$SUDO_USER}"
|
||||||
|
|
||||||
|
add_sudoers_rule() {
|
||||||
|
sudo tee /etc/sudoers.d/zzzzzzzzzzzzzzzzzzz > /dev/null <<EOF
|
||||||
|
${LINUX_USER} ALL=(root) NOPASSWD: /opt/hydra-veil/firewall
|
||||||
|
${LINUX_USER} ALL=(root) NOPASSWD: /opt/hydra-veil/dns
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
echo "Error: This script must be run as root (use sudo)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validate environment variables
|
||||||
|
if [[ -z "$ORIGINAL_FOLDER" ]]; then
|
||||||
|
echo "Error: ORIGINAL_FOLDER environment variable not set" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$TARGET_FOLDER" ]]; then
|
||||||
|
echo "Error: TARGET_FOLDER environment variable not set" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validate that source folder exists
|
||||||
|
if [[ ! -d "$ORIGINAL_FOLDER" ]]; then
|
||||||
|
echo "Error: ORIGINAL_FOLDER does not exist: $ORIGINAL_FOLDER" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create target folder if it doesn't exist
|
||||||
|
if [[ ! -d "$TARGET_FOLDER" ]]; then
|
||||||
|
echo "Creating target folder: $TARGET_FOLDER"
|
||||||
|
mkdir -p "$TARGET_FOLDER"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the setup script's own filename, because we'll exclude it from being copied,
|
||||||
|
SCRIPT_NAME="$(basename "$0")"
|
||||||
|
|
||||||
|
echo "Starting file copy from $ORIGINAL_FOLDER to $TARGET_FOLDER"
|
||||||
|
echo "Script name to exclude: $SCRIPT_NAME"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Counter for tracking progress
|
||||||
|
COPIED=0
|
||||||
|
SKIPPED=0
|
||||||
|
|
||||||
|
# Loop through all files in source folder
|
||||||
|
while IFS= read -r -d '' file; do
|
||||||
|
filename="$(basename "$file")"
|
||||||
|
|
||||||
|
# Skip if this is the script itself
|
||||||
|
if [[ "$filename" == "$SCRIPT_NAME" ]]; then
|
||||||
|
echo "⊘ Skipping: $filename (this script)"
|
||||||
|
((SKIPPED++))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy the file
|
||||||
|
if cp "$file" "$TARGET_FOLDER/"; then
|
||||||
|
echo "✓ Copied: $filename"
|
||||||
|
((COPIED++))
|
||||||
|
|
||||||
|
# Set permissions to 755
|
||||||
|
if chmod 755 "$TARGET_FOLDER/$filename"; then
|
||||||
|
echo " └─ chmod 755 applied"
|
||||||
|
else
|
||||||
|
echo " └─ WARNING: chmod 755 failed for $filename" >&2
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "✗ ERROR: Failed to copy $filename" >&2
|
||||||
|
((SKIPPED++))
|
||||||
|
fi
|
||||||
|
|
||||||
|
done < <(find "$ORIGINAL_FOLDER" -maxdepth 1 -type f -print0)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Copy complete!"
|
||||||
|
echo "Files copied: $COPIED"
|
||||||
|
echo "Files skipped: $SKIPPED"
|
||||||
|
echo "Target folder: $TARGET_FOLDER"
|
||||||
|
echo "=========================================="
|
||||||
|
|
||||||
|
# Try to apply the rules, if not emit 1
|
||||||
|
if add_sudoers_rule; then
|
||||||
|
echo "Operation successful"
|
||||||
|
else
|
||||||
|
echo "Operation failed - sudoers rule not applied"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -65,6 +65,14 @@ class Configuration:
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
did_sudo_setup: Optional[bool] = field(
|
||||||
|
default=False,
|
||||||
|
metadata=config(
|
||||||
|
undefined=dataclasses_json.Undefined.EXCLUDE,
|
||||||
|
exclude=lambda value: value is None
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def save(self: Self):
|
def save(self: Self):
|
||||||
|
|
||||||
config_file_contents = f'{self.to_json(indent=4)}\n'
|
config_file_contents = f'{self.to_json(indent=4)}\n'
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,28 @@
|
||||||
from core.Constants import Constants
|
from core.Constants import Constants
|
||||||
from core.errors.logger import logger
|
from core.errors.logger import logger
|
||||||
|
|
||||||
|
# generic
|
||||||
|
from pathlib import Path
|
||||||
import shutil
|
import shutil
|
||||||
import os
|
import os
|
||||||
|
|
||||||
def assets_folder_setup():
|
def assets_folder_setup():
|
||||||
initial_appimage_assets = f"{Constants.APPDIR_HOME}/assets"
|
initial_appimage_assets = f"{Constants.APPDIR_HOME}/assets"
|
||||||
current_assets_folder = f"{Constants.HV_DATA_HOME}/assets"
|
current_assets_folder = f"{Constants.HV_DATA_HOME}/assets"
|
||||||
|
|
||||||
if os.path.exists(current_assets_folder):
|
if os.path.exists(current_assets_folder):
|
||||||
return True
|
return True
|
||||||
|
return copy_folders(initial_appimage_assets, current_assets_folder)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def sudo_assets_folder_setup() -> bool:
|
||||||
|
# initial_appimage_assets = f"{Constants.APPDIR_HOME}/assets/sudo_scripts"
|
||||||
|
initial_appimage_assets = f"/home/a/VPN/code/DEV/sp-hydra-veil-core/core/assets/sudo_scripts"
|
||||||
|
current_assets_folder = f"{Constants.HOME}/Downloads/hydraveil_sudo_scripts"
|
||||||
|
return copy_folders(initial_appimage_assets, current_assets_folder)
|
||||||
|
|
||||||
|
|
||||||
|
def copy_folders(initial_appimage_assets: str, current_assets_folder: str) -> bool:
|
||||||
try:
|
try:
|
||||||
os.makedirs(current_assets_folder, exist_ok=True)
|
os.makedirs(current_assets_folder, exist_ok=True)
|
||||||
for item in os.listdir(initial_appimage_assets):
|
for item in os.listdir(initial_appimage_assets):
|
||||||
|
|
@ -20,9 +32,22 @@ def assets_folder_setup():
|
||||||
shutil.copytree(src, dst)
|
shutil.copytree(src, dst)
|
||||||
else:
|
else:
|
||||||
shutil.copy2(src, dst)
|
shutil.copy2(src, dst)
|
||||||
|
logger.info(f"[MANAGE ASSETS] Successfully copied over the folder.")
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"initial_appimage_assets is {initial_appimage_assets}")
|
logger.error(f"[MANAGE ASSETS] initial_appimage_assets is {initial_appimage_assets}")
|
||||||
logger.error(f"current_assets_folder is {current_assets_folder}")
|
logger.error(f"[MANAGE ASSETS] current_assets_folder is {current_assets_folder}")
|
||||||
logger.error(f"ERROR: {e}")
|
logger.error(f"[MANAGE ASSETS] ERROR: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup_setup_dir():
|
||||||
|
"""After install completes"""
|
||||||
|
delete_this_folder = f"{Constants.HOME}/Downloads/hydraveil_sudo_scripts"
|
||||||
|
try:
|
||||||
|
shutil.rmtree(delete_this_folder)
|
||||||
|
logger.info(f"[MANAGE ASSETS] Cleaned up {delete_this_folder}")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[MANAGE ASSETS] We could not delete {delete_this_folder} because {e}")
|
||||||
return False
|
return False
|
||||||
|
|
|
||||||
67
core/services/helpers/setup_sudo_scripts.py
Normal file
67
core/services/helpers/setup_sudo_scripts.py
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
from core.services.helpers.manage_assets import sudo_assets_folder_setup
|
||||||
|
from core.utils.basic_operations.confirm_files_exist import confirm_files_and_folders_exist
|
||||||
|
from core.models.Result import Result, ResultError
|
||||||
|
from core.Constants import Constants
|
||||||
|
from core.errors.logger import logger
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
import shutil
|
||||||
|
import os
|
||||||
|
from subprocess import CalledProcessError
|
||||||
|
import copy
|
||||||
|
|
||||||
|
FILES_TO_CHECK = ["setup.sh", "firewall", "dns"]
|
||||||
|
TARGET_FOLDER = "/opt/hydra-veil"
|
||||||
|
|
||||||
|
def auto_install_sudo_script() -> Result:
|
||||||
|
setup_dir = Path(f"{Constants.HOME}/Downloads/hydraveil_sudo_scripts")
|
||||||
|
setup_script = Path(setup_dir, 'setup.sh')
|
||||||
|
original_linux_user = os.getlogin()
|
||||||
|
|
||||||
|
# Make sure the folder exists
|
||||||
|
files_exist = confirm_files_and_folders_exist(
|
||||||
|
folder_path=setup_dir, files_to_check=FILES_TO_CHECK
|
||||||
|
)
|
||||||
|
|
||||||
|
if not files_exist:
|
||||||
|
copied = sudo_assets_folder_setup()
|
||||||
|
if not copied:
|
||||||
|
return Result(valid=False, message="Could not copy scripts to begin.")
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
['pkexec', 'env', f'ORIGINAL_FOLDER={setup_dir}', f'TARGET_FOLDER={TARGET_FOLDER}', f'LINUX_USER={original_linux_user}', 'bash', setup_script],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
if result.returncode == 0:
|
||||||
|
logger.info("Sudo Setup Ran. Now testing..")
|
||||||
|
return Result(valid=True)
|
||||||
|
else:
|
||||||
|
logger.error(f"Sudo setup setup failed: {result.stderr.strip()}")
|
||||||
|
return Result(valid=False, message=result.stderr.strip())
|
||||||
|
except CalledProcessError as e:
|
||||||
|
return Result(valid=False, message=e)
|
||||||
|
except Exception as e:
|
||||||
|
return Result(valid=False, message=e)
|
||||||
|
|
||||||
|
def test_if_in_sudo_folder() -> Result:
|
||||||
|
final_sudo_folder = Path("/opt/hydra-veil/")
|
||||||
|
_files_to_check = FILES_TO_CHECK.copy() # to not affect the other functions.
|
||||||
|
|
||||||
|
# setup script itself doesn't get copied over:
|
||||||
|
_files_to_check.remove("setup.sh")
|
||||||
|
|
||||||
|
# Now verify it copied them:
|
||||||
|
sudo_files_copied = confirm_files_and_folders_exist(
|
||||||
|
folder_path=final_sudo_folder, files_to_check=_files_to_check
|
||||||
|
)
|
||||||
|
|
||||||
|
if sudo_files_copied:
|
||||||
|
return Result(valid=True, message="Sudo Script Setup Completed Successfully!")
|
||||||
|
else:
|
||||||
|
error_msg = "We failed to find the files in the sudo folder."
|
||||||
|
logger.error(error_msg)
|
||||||
|
return Result(valid=False, message=error_msg)
|
||||||
|
|
||||||
|
|
@ -3,12 +3,10 @@ from core.Constants import Constants
|
||||||
from core.models.Result import Result, ResultError
|
from core.models.Result import Result, ResultError
|
||||||
from core.errors.logger import logger
|
from core.errors.logger import logger
|
||||||
|
|
||||||
# generic
|
|
||||||
import subprocess
|
import subprocess
|
||||||
from subprocess import CalledProcessError
|
from subprocess import CalledProcessError
|
||||||
|
|
||||||
# temp location:
|
DNS_SCRIPT = f"/opt/hydra-veil/dns"
|
||||||
DNS_SCRIPT = f"/opt/hydra-veil/dns_script"
|
|
||||||
|
|
||||||
|
|
||||||
# requires script to have sudo
|
# requires script to have sudo
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
import subprocess
|
import subprocess
|
||||||
from core.Constants import Constants
|
|
||||||
from core.models.Result import Result, ResultError
|
from core.models.Result import Result, ResultError
|
||||||
from core.errors.logger import logger
|
from core.errors.logger import logger
|
||||||
|
|
||||||
_C = Constants()
|
|
||||||
# _C.KILLSWITCH_WRAPPER
|
|
||||||
|
|
||||||
TESTING_KILLSWITCH = "/opt/hydra-veil/test" # needs chmod 755
|
KILLSWITCH_WRAPPER = "/opt/hydra-veil/firewall" # needs chmod 755
|
||||||
|
|
||||||
def arm(server_ip: str, tunnel_if: str, internal_subnet: str = None) -> Result:
|
def arm(server_ip: str, tunnel_if: str, internal_subnet: str = None) -> Result:
|
||||||
cmd = ["sudo", TESTING_KILLSWITCH, "arm", server_ip, tunnel_if]
|
cmd = ["sudo", KILLSWITCH_WRAPPER, "arm", server_ip, tunnel_if]
|
||||||
if internal_subnet:
|
if internal_subnet:
|
||||||
cmd.append(internal_subnet)
|
cmd.append(internal_subnet)
|
||||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||||
|
|
@ -23,7 +20,7 @@ def arm(server_ip: str, tunnel_if: str, internal_subnet: str = None) -> Result:
|
||||||
|
|
||||||
def disarm() -> bool:
|
def disarm() -> bool:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["sudo", TESTING_KILLSWITCH, "disarm"],
|
["sudo", KILLSWITCH_WRAPPER, "disarm"],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
)
|
)
|
||||||
|
|
@ -37,7 +34,7 @@ def disarm() -> bool:
|
||||||
|
|
||||||
def status() -> bool:
|
def status() -> bool:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["sudo", TESTING_KILLSWITCH, "status"],
|
["sudo", KILLSWITCH_WRAPPER, "status"],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
20
core/utils/basic_operations/confirm_files_exist.py
Normal file
20
core/utils/basic_operations/confirm_files_exist.py
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
from core.errors.logger import logger
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
def confirm_files_and_folders_exist(folder_path, files_to_check):
|
||||||
|
if folder_path.is_dir():
|
||||||
|
logger.info(f"Folder exists: {folder_path}")
|
||||||
|
|
||||||
|
# Check each file
|
||||||
|
for filename in files_to_check:
|
||||||
|
file_path = folder_path / filename
|
||||||
|
if file_path.is_file():
|
||||||
|
logger.info(f"✓ {filename} exists")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
logger.error(f"✗ {filename} NOT found")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
logger.error("Folder does not exist")
|
||||||
|
return False
|
||||||
|
|
||||||
Loading…
Reference in a new issue