mirror of
https://github.com/iio612/DEFENDER.git
synced 2026-02-13 11:14:23 +00:00
Adding 'make update' to update from git repository. remove previous installation.py file, the update of packages is done via install.py file.
This commit is contained in:
7
Makefile
7
Makefile
@@ -53,3 +53,10 @@ ifeq ($(OS), Linux)
|
|||||||
fi
|
fi
|
||||||
@export echo $DBUS_SESSION_BUS_ADDRESS && systemctl --user daemon-reload && echo "Systemd Daemon reloaded!"
|
@export echo $DBUS_SESSION_BUS_ADDRESS && systemctl --user daemon-reload && echo "Systemd Daemon reloaded!"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
update:
|
||||||
|
ifeq ($(OS), Linux)
|
||||||
|
$(info Starting update from the main repository...)
|
||||||
|
@. .pyenv/bin/activate && python core/install.py --git-update
|
||||||
|
$(info Update done!)
|
||||||
|
endif
|
||||||
|
|||||||
139
README.md
139
README.md
@@ -34,10 +34,11 @@ Il permet aux opérateurs de gérer efficacement un canal, tout en offrant aux u
|
|||||||
- Python version 3.10 ou supérieure
|
- Python version 3.10 ou supérieure
|
||||||
```bash
|
```bash
|
||||||
# Bash
|
# Bash
|
||||||
$ git clone https://github.com/adator85/IRC_DEFENDER_MODULES.git
|
$ git clone https://github.com/adator85/DEFENDER.git defender
|
||||||
|
$ cd defender/
|
||||||
# Renommer le fichier exemple_configuration.json en configuration.json
|
# Renommer le fichier exemple_configuration.json en configuration.json
|
||||||
# Configurer le fichier configuration.json
|
# Configurer le fichier configuration.json
|
||||||
$ python3 main.py
|
$ make install
|
||||||
```
|
```
|
||||||
Si votre configuration est bonne, votre service est censé etre connecté a votre réseau IRC
|
Si votre configuration est bonne, votre service est censé etre connecté a votre réseau IRC
|
||||||
Pour Les prochains lancement de defender vous devez utiliser la commande suivante:
|
Pour Les prochains lancement de defender vous devez utiliser la commande suivante:
|
||||||
@@ -49,11 +50,11 @@ Pour Les prochains lancement de defender vous devez utiliser la commande suivant
|
|||||||
# Installation manuelle:
|
# Installation manuelle:
|
||||||
```bash
|
```bash
|
||||||
# Bash
|
# Bash
|
||||||
$ git clone https://github.com/adator85/IRC_DEFENDER_MODULES.git
|
$ git clone https://github.com/adator85/DEFENDER.git defender
|
||||||
$ cd IRC_DEFENDER_MODULES
|
$ cd defender/
|
||||||
$ python3 -m venv .pyenv
|
$ python3 -m venv .pyenv
|
||||||
$ source .pyenv/bin/activate
|
$ source .pyenv/bin/activate
|
||||||
(pyenv)$ pip install sqlalchemy, psutil, requests, faker, unrealircd_rpc_py, pyyaml
|
(pyenv)$ pip install -r requirements.txt
|
||||||
|
|
||||||
# Créer un service nommé "defender.service"
|
# Créer un service nommé "defender.service"
|
||||||
# pour votre service et placer le dans "/PATH/TO/USER/.config/systemd/user/"
|
# pour votre service et placer le dans "/PATH/TO/USER/.config/systemd/user/"
|
||||||
@@ -104,87 +105,91 @@ Pour Les prochains lancement de defender vous devez utiliser la commande suivant
|
|||||||
GLINE_DURATION: Durée de bannissement temporaire d'un utilisateur en minutes. (default : "30")
|
GLINE_DURATION: Durée de bannissement temporaire d'un utilisateur en minutes. (default : "30")
|
||||||
|
|
||||||
DEBUG (Debug)
|
DEBUG (Debug)
|
||||||
DEBUG_LEVEL: Niveau de verbosité des messages de debug (plus grand est le nombre, plus il y a d'informations). (default : 20) Pour une production
|
DEBUG_LEVEL: Niveau de verbosité des messages de debug (plus petit est le nombre, plus il y a d'informations). (default : 20) Pour une production
|
||||||
|
DEBUG_HARD: Généralement utiliser pour les developpeurs.
|
||||||
|
|
||||||
```
|
```
|
||||||
Modification de la configuration
|
Modification de la configuration
|
||||||
|
|
||||||
Vous devez modifier le fichier configuration.json en remplaçant les valeurs par défaut avec vos propres informations. Assurez-vous de bien lire la description de chaque paramètre pour une configuration optimale du service.
|
Vous devez modifier le fichier configuration.yaml en remplaçant les valeurs par défaut avec vos propres informations. Assurez-vous de bien lire la description de chaque paramètre pour une configuration optimale du service.
|
||||||
|
|
||||||
## Exemple de configuration de base
|
## Exemple de configuration de base
|
||||||
```json
|
```yaml
|
||||||
{
|
configuration:
|
||||||
"SERVEUR_IP": "IP.DE.TON.SERVER",
|
SERVEUR_IP: "YOUR.SERVER.IP"
|
||||||
"SERVEUR_HOSTNAME": "HOST.DE.TON.SERVER",
|
SERVEUR_HOSTNAME: "YOUR.SERVER.HOST"
|
||||||
"SERVEUR_LINK": "LINK.DE.TON.SERVER",
|
SERVEUR_LINK: "LINK.DE.TON.SERVER"
|
||||||
"SERVEUR_PORT": 6901,
|
SERVEUR_PORT: 7002
|
||||||
"SERVEUR_PASSWORD": "MOT_DE_PASS_DE_TON_LINK",
|
SERVEUR_PASSWORD: "YOUR_LINK_PASSWORD"
|
||||||
"SERVEUR_ID": "10Z",
|
SERVEUR_ID: "006"
|
||||||
"SERVEUR_SSL": true,
|
SERVEUR_SSL: true
|
||||||
|
|
||||||
"SERVICE_NAME": "defender",
|
SERVICE_NAME: "defender"
|
||||||
"SERVICE_NICKNAME": "PyDefender",
|
SERVICE_NICKNAME: "PyDefender"
|
||||||
"SERVICE_REALNAME": "Python Defender Security",
|
SERVICE_REALNAME: "Python Defender Security"
|
||||||
"SERVICE_USERNAME": "PyDefender",
|
SERVICE_USERNAME: "PyDefender"
|
||||||
"SERVICE_HOST": "HOST.DE.TON.DEFENDER",
|
SERVICE_HOST: "HOST.DE.TON.DEFENDER"
|
||||||
|
SERVICE_INFO: "Network IRC Service"
|
||||||
|
SERVICE_CHANLOG: "#services"
|
||||||
|
SERVICE_SMODES: "+ioqBS"
|
||||||
|
SERVICE_CMODES: "ntsOP"
|
||||||
|
SERVICE_UMODES: "o"
|
||||||
|
SERVICE_PREFIX: "!"
|
||||||
|
|
||||||
"OWNER": "TON_NICK_NAME",
|
OWNER: "TON_NICK_NAME"
|
||||||
"PASSWORD": "TON_PASSWORD"
|
PASSWORD: "TON_PASSWORD"
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Exemple complet de configuration
|
## Exemple complet de configuration
|
||||||
```json
|
```yaml
|
||||||
{
|
configuration:
|
||||||
"SERVEUR_IP": "YOUR.SERVER.IP",
|
SERVEUR_IP: "YOUR.SERVER.IP"
|
||||||
"SERVEUR_HOSTNAME": "YOUR.SERVER.HOST",
|
SERVEUR_HOSTNAME: "YOUR.SERVER.HOST"
|
||||||
"SERVEUR_LINK": "LINK.DE.TON.SERVER",
|
SERVEUR_LINK: "LINK.DE.TON.SERVER"
|
||||||
"SERVEUR_PORT": 6901,
|
SERVEUR_PORT: 7002
|
||||||
"SERVEUR_PASSWORD": "YOUR_LINK_PASSWORD",
|
SERVEUR_PASSWORD: "YOUR_LINK_PASSWORD"
|
||||||
"SERVEUR_ID": "10Z",
|
SERVEUR_ID: "006"
|
||||||
"SERVEUR_SSL": true,
|
SERVEUR_SSL: true
|
||||||
|
|
||||||
"SERVICE_NAME": "defender",
|
SERVICE_NAME: "defender"
|
||||||
"SERVICE_NICKNAME": "PyDefender",
|
SERVICE_NICKNAME: "PyDefender"
|
||||||
"SERVICE_REALNAME": "Python Defender Security",
|
SERVICE_REALNAME: "Python Defender Security"
|
||||||
"SERVICE_USERNAME": "PyDefender",
|
SERVICE_USERNAME: "PyDefender"
|
||||||
"SERVICE_HOST": "HOST.DE.TON.DEFENDER",
|
SERVICE_HOST: "HOST.DE.TON.DEFENDER"
|
||||||
"SERVICE_INFO": "Network IRC Service",
|
SERVICE_INFO: "Network IRC Service"
|
||||||
"SERVICE_CHANLOG": "#services",
|
SERVICE_CHANLOG: "#services"
|
||||||
"SERVICE_SMODES": "+ioqBS",
|
SERVICE_SMODES: "+ioqBS"
|
||||||
"SERVICE_CMODES": "ntsOP",
|
SERVICE_CMODES: "ntsOP"
|
||||||
"SERVICE_UMODES": "o",
|
SERVICE_UMODES: "o"
|
||||||
"SERVICE_PREFIX": "!",
|
SERVICE_PREFIX: "!"
|
||||||
|
|
||||||
"OWNER": "TON_NICK_NAME",
|
OWNER: "TON_NICK_NAME"
|
||||||
"PASSWORD": "TON_PASSWORD",
|
PASSWORD: "TON_PASSWORD"
|
||||||
|
|
||||||
"JSONRPC_URL": "https://your.domaine.com:8600/api",
|
JSONRPC_URL: "https://your.domaine.com:8600/api"
|
||||||
"JSONRPC_PATH_TO_SOCKET_FILE": "/PATH/TO/YOUR/IRCD/data/rpc.socket",
|
JSONRPC_PATH_TO_SOCKET_FILE: "/PATH/TO/YOUR/IRCD/data/rpc.socket"
|
||||||
"JSONRPC_METHOD": "socket",
|
JSONRPC_METHOD: "unixsocket"
|
||||||
"JSONRPC_USER": "YOUR_RPC_USER",
|
JSONRPC_USER: "YOUR_RPC_USER"
|
||||||
"JSONRPC_PASSWORD": "YOUR_RPC_PASSWORD",
|
JSONRPC_PASSWORD: "YOUR_RPC_PASSWORD"
|
||||||
|
|
||||||
"SALON_JAIL": "#jail",
|
SALON_JAIL: "#jail"
|
||||||
"SALON_JAIL_MODES": "sS",
|
SALON_JAIL_MODES: "sS"
|
||||||
"SALON_LIBERER": "#welcome",
|
SALON_LIBERER: "#welcome"
|
||||||
|
|
||||||
"CLONE_CHANNEL": "#clones",
|
CLONE_CHANNEL: "#clones"
|
||||||
"CLONE_CMODES": "+nts",
|
CLONE_CMODES: "+nts"
|
||||||
"CLONE_LOG_HOST_EXEMPT": ["HOST.TO.SKIP"],
|
CLONE_LOG_HOST_EXEMPT: ["HOST.TO.SKIP"]
|
||||||
"CLONE_CHANNEL_PASSWORD": "YOUR_CHANNEL_PASSWORD",
|
CLONE_CHANNEL_PASSWORD: "YOUR_CHANNEL_PASSWORD"
|
||||||
|
|
||||||
"API_TIMEOUT": 2,
|
API_TIMEOUT: 2
|
||||||
|
|
||||||
"PORTS_TO_SCAN": [3028, 8080, 1080, 1085, 4145, 9050],
|
PORTS_TO_SCAN: [3028 8080 1080 1085 4145 9050]
|
||||||
"WHITELISTED_IP": ["127.0.0.1"],
|
WHITELISTED_IP: ["127.0.0.1"]
|
||||||
"GLINE_DURATION": "30",
|
GLINE_DURATION: "30"
|
||||||
|
|
||||||
"DEBUG_LEVEL": 20
|
DEBUG_LEVEL: 20
|
||||||
|
DEBUG_HARD: true
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# \\!/ Attention \\!/
|
# \\!/ Attention \\!/
|
||||||
@@ -192,7 +197,7 @@ Le mot de passe de l'administrateur et le mot de passe du service doivent être
|
|||||||
Ne partagez pas vos informations de connexion au serveur IRC avec des tiers.
|
Ne partagez pas vos informations de connexion au serveur IRC avec des tiers.
|
||||||
a votre premiere connexion vous devez tapez
|
a votre premiere connexion vous devez tapez
|
||||||
```
|
```
|
||||||
/msg [NomDuService] auth [nickname] [password]
|
/msg [NomDuService] firstauth [nickname] [password]
|
||||||
-- Une fois identifié tapez la commande suivante
|
-- Une fois identifié tapez la commande suivante
|
||||||
/msg [NomDuService] editaccess [nickname] [Nouveau-Password] 5
|
/msg [NomDuService] editaccess [nickname] [Nouveau-Password] 5
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ configuration:
|
|||||||
|
|
||||||
JSONRPC_URL: "https://your.domaine.com:8600/api"
|
JSONRPC_URL: "https://your.domaine.com:8600/api"
|
||||||
JSONRPC_PATH_TO_SOCKET_FILE: "/PATH/TO/YOUR/IRCD/data/rpc.socket"
|
JSONRPC_PATH_TO_SOCKET_FILE: "/PATH/TO/YOUR/IRCD/data/rpc.socket"
|
||||||
JSONRPC_METHOD: "socket"
|
JSONRPC_METHOD: "unixsocket"
|
||||||
JSONRPC_USER: "YOUR_RPC_USER"
|
JSONRPC_USER: "YOUR_RPC_USER"
|
||||||
JSONRPC_PASSWORD: "YOUR_RPC_PASSWORD"
|
JSONRPC_PASSWORD: "YOUR_RPC_PASSWORD"
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,99 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import json
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from subprocess import check_call, CalledProcessError, check_output
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from platform import python_version_tuple
|
from platform import python_version_tuple
|
||||||
|
import traceback
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="Python Installation Code")
|
parser = argparse.ArgumentParser(description="Python Installation Code")
|
||||||
parser.add_argument('--check-version', action='store_true', help='Check if the python version is ok!')
|
parser.add_argument('--check-version', action='store_true', help='Check if the python version is ok!')
|
||||||
parser.add_argument('--install', action='store_true', help='Run the installation')
|
parser.add_argument('--install', action='store_true', help='Run the installation')
|
||||||
|
parser.add_argument('--git-update', action='store_true', help='Update from git (main repository)')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
PYTHON_REQUIRED_VERSION = (3, 10, 0)
|
PYTHON_REQUIRED_VERSION = (3, 10, 0)
|
||||||
PYTHON_SYSTEM_VERSION = tuple(map(int, python_version_tuple()))
|
PYTHON_SYSTEM_VERSION = tuple(map(int, python_version_tuple()))
|
||||||
ROOT_PATH = os.getcwd()
|
ROOT_PATH = os.getcwd()
|
||||||
PYENV = Path(f'{ROOT_PATH}/.pyenv/bin/python')
|
PYENV = Path(ROOT_PATH).joinpath('.pyenv/bin/python') if os.name != 'nt' else Path(ROOT_PATH).joinpath('.pyenv/Scripts/python.exe')
|
||||||
|
PIPENV = Path(f'{ROOT_PATH}/.pyenv/bin/pip') if os.name != 'nt' else Path(f'{ROOT_PATH}/.pyenv/Scripts/pip.exe')
|
||||||
USER_HOME_DIRECTORY = Path.home()
|
USER_HOME_DIRECTORY = Path.home()
|
||||||
SYSTEMD_PATH = Path(USER_HOME_DIRECTORY).joinpath('.config', 'systemd', 'user')
|
SYSTEMD_PATH = Path(USER_HOME_DIRECTORY).joinpath('.config', 'systemd', 'user')
|
||||||
PY_EXEC = 'defender.py'
|
PY_EXEC = 'defender.py'
|
||||||
SERVICE_FILE_NAME = 'defender.service'
|
SERVICE_FILE_NAME = 'defender.service'
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Package:
|
||||||
|
name: str = None
|
||||||
|
version: str = None
|
||||||
|
|
||||||
|
def __load_required_package_versions() -> list[Package]:
|
||||||
|
"""This will create Package model with package names and required version
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
DB_PACKAGES: list[Package] = []
|
||||||
|
version_filename = Path(ROOT_PATH).joinpath('version.json') # f'.{os.sep}version.json'
|
||||||
|
with open(version_filename, 'r') as version_data:
|
||||||
|
package_info:dict[str, str] = json.load(version_data)
|
||||||
|
|
||||||
|
for name, version in package_info.items():
|
||||||
|
if name == 'version':
|
||||||
|
continue
|
||||||
|
DB_PACKAGES.append(
|
||||||
|
Package(name=name, version=version)
|
||||||
|
)
|
||||||
|
|
||||||
|
return DB_PACKAGES
|
||||||
|
|
||||||
|
except FileNotFoundError as fe:
|
||||||
|
print(f"File not found: {fe}")
|
||||||
|
except Exception as err:
|
||||||
|
print(f"General Error: {err}")
|
||||||
|
|
||||||
|
def update_packages() -> None:
|
||||||
|
try:
|
||||||
|
newVersion = False
|
||||||
|
db_packages = __load_required_package_versions()
|
||||||
|
print(ROOT_PATH)
|
||||||
|
if sys.prefix not in PYENV.__str__():
|
||||||
|
print(f"You are probably running a new installation or you are not using your virtual env {PYENV}")
|
||||||
|
return newVersion
|
||||||
|
|
||||||
|
print(f"> Checking for dependencies versions ==> WAIT")
|
||||||
|
for package in db_packages:
|
||||||
|
newVersion = False
|
||||||
|
_required_version = package.version
|
||||||
|
_installed_version: str = None
|
||||||
|
output = check_output([PIPENV, 'show', package.name])
|
||||||
|
for line in output.decode().splitlines():
|
||||||
|
if line.startswith('Version:'):
|
||||||
|
_installed_version = line.split(':')[1].strip()
|
||||||
|
break
|
||||||
|
|
||||||
|
required_version = tuple(map(int, _required_version.split('.')))
|
||||||
|
installed_version = tuple(map(int, _installed_version.split('.')))
|
||||||
|
|
||||||
|
if required_version > installed_version:
|
||||||
|
print(f'> New version of {package.name} is available {installed_version} ==> {required_version}')
|
||||||
|
newVersion = True
|
||||||
|
|
||||||
|
if newVersion:
|
||||||
|
check_call([PIPENV, 'install', '--upgrade', package.name])
|
||||||
|
|
||||||
|
print(f"> Dependencies versions ==> OK")
|
||||||
|
return newVersion
|
||||||
|
|
||||||
|
except CalledProcessError:
|
||||||
|
print(f"[!] Package {package.name} not installed [!]")
|
||||||
|
except Exception as err:
|
||||||
|
print(f"UpdatePackage Error: {err}")
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
def run_git_update() -> None:
|
||||||
|
check_call(['git', 'pull', 'origin', 'main'])
|
||||||
|
|
||||||
def check_python_requirement():
|
def check_python_requirement():
|
||||||
if PYTHON_SYSTEM_VERSION < PYTHON_REQUIRED_VERSION:
|
if PYTHON_SYSTEM_VERSION < PYTHON_REQUIRED_VERSION:
|
||||||
raise RuntimeError(f"Your Python Version is not meeting the requirement, System Version: {PYTHON_SYSTEM_VERSION} < Required Version {PYTHON_REQUIRED_VERSION}")
|
raise RuntimeError(f"Your Python Version is not meeting the requirement, System Version: {PYTHON_SYSTEM_VERSION} < Required Version {PYTHON_REQUIRED_VERSION}")
|
||||||
@@ -65,6 +141,10 @@ def main():
|
|||||||
create_service_file()
|
create_service_file()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
if args.git_update:
|
||||||
|
run_git_update()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -1,314 +0,0 @@
|
|||||||
import os
|
|
||||||
import json
|
|
||||||
from sys import exit, prefix
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from subprocess import check_call, run, CalledProcessError, PIPE, check_output
|
|
||||||
from platform import python_version, python_version_tuple
|
|
||||||
|
|
||||||
class Install:
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class CoreConfig:
|
|
||||||
install_log_file: str
|
|
||||||
unix_systemd_folder: str
|
|
||||||
service_file_name: str
|
|
||||||
service_cmd_executable: list
|
|
||||||
service_cmd_daemon_reload: list
|
|
||||||
defender_main_executable: str
|
|
||||||
python_min_version: str
|
|
||||||
python_current_version_tuple: tuple[int, int, int]
|
|
||||||
python_current_version: tuple[int, int, int]
|
|
||||||
defender_install_folder: str
|
|
||||||
venv_folder: str
|
|
||||||
venv_cmd_installation: list
|
|
||||||
venv_cmd_requirements: list[str]
|
|
||||||
venv_pip_executable: str
|
|
||||||
venv_python_executable: str
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Package:
|
|
||||||
name: str = None
|
|
||||||
version: str = None
|
|
||||||
|
|
||||||
DB_PACKAGES: list[Package] = []
|
|
||||||
|
|
||||||
def __init__(self) -> None:
|
|
||||||
|
|
||||||
self.set_configuration()
|
|
||||||
|
|
||||||
if self.skip_install:
|
|
||||||
self.install_dependencies()
|
|
||||||
self.check_packages_version()
|
|
||||||
return None
|
|
||||||
|
|
||||||
self.check_packages_version()
|
|
||||||
|
|
||||||
# Sinon tester les dependances python et les installer avec pip
|
|
||||||
if self.do_install():
|
|
||||||
|
|
||||||
self.install_dependencies()
|
|
||||||
|
|
||||||
self.create_service_file()
|
|
||||||
|
|
||||||
self.print_final_message()
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
def set_configuration(self):
|
|
||||||
|
|
||||||
self.skip_install = False
|
|
||||||
defender_install_folder = os.getcwd()
|
|
||||||
venv_folder = '.pyenv'
|
|
||||||
unix_user_home_directory = os.path.expanduser("~")
|
|
||||||
unix_systemd_folder = os.path.join(unix_user_home_directory, '.config', 'systemd', 'user')
|
|
||||||
defender_main_executable = os.path.join(defender_install_folder, 'defender.py')
|
|
||||||
|
|
||||||
self.config = self.CoreConfig(
|
|
||||||
install_log_file='install.log',
|
|
||||||
unix_systemd_folder=unix_systemd_folder,
|
|
||||||
service_file_name='defender.service',
|
|
||||||
service_cmd_executable=['systemctl', '--user', 'start', 'defender'],
|
|
||||||
service_cmd_daemon_reload=['systemctl', '--user', 'daemon-reload'],
|
|
||||||
defender_main_executable=defender_main_executable,
|
|
||||||
python_min_version=(3, 10, 0),
|
|
||||||
python_current_version_tuple=tuple(map(int, python_version_tuple())),
|
|
||||||
python_current_version=python_version(),
|
|
||||||
defender_install_folder=defender_install_folder,
|
|
||||||
venv_folder=venv_folder,
|
|
||||||
venv_cmd_installation=['python3', '-m', 'venv', venv_folder],
|
|
||||||
venv_cmd_requirements=['sqlalchemy','psutil','requests','faker','pyyaml','unrealircd_rpc_py'],
|
|
||||||
venv_pip_executable=f'{os.path.join(defender_install_folder, venv_folder, "bin")}{os.sep}pip',
|
|
||||||
venv_python_executable=f'{os.path.join(defender_install_folder, venv_folder, "bin")}{os.sep}python'
|
|
||||||
)
|
|
||||||
|
|
||||||
if not self.check_python_version():
|
|
||||||
# If the Python version is not good then Exit
|
|
||||||
exit("[!] Python version error [!]")
|
|
||||||
|
|
||||||
if not os.path.exists(os.path.join(self.config.defender_install_folder, 'config', 'configuration.yaml')):
|
|
||||||
# If configuration file do not exist
|
|
||||||
exit("[!] Configuration file (core/configuration.yaml) doesn't exist! please create it [!]")
|
|
||||||
|
|
||||||
# Exclude Windows OS from the installation
|
|
||||||
if os.name == 'nt':
|
|
||||||
# If windows, modify pip and python virtual environment executable
|
|
||||||
self.config.venv_pip_executable = f'{os.path.join(defender_install_folder, venv_folder, "Scripts")}{os.sep}pip.exe'
|
|
||||||
self.config.venv_python_executable = f'{os.path.join(defender_install_folder, venv_folder, "Scripts")}{os.sep}python.exe'
|
|
||||||
self.skip_install = True
|
|
||||||
return False
|
|
||||||
|
|
||||||
if self.is_root():
|
|
||||||
exit(f'[!] I highly not recommend running Defender as root [!]')
|
|
||||||
self.skip_install = True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def is_root(self) -> bool:
|
|
||||||
|
|
||||||
if os.geteuid() != 0:
|
|
||||||
print('> User without privileges ==> OK')
|
|
||||||
return False
|
|
||||||
elif os.geteuid() == 0:
|
|
||||||
print('[!] Do not use root to install Defender [!]')
|
|
||||||
exit("Do not use root to install Defender")
|
|
||||||
return True
|
|
||||||
|
|
||||||
def do_install(self) -> bool:
|
|
||||||
|
|
||||||
full_service_file_path = os.path.join(self.config.unix_systemd_folder, self.config.service_file_name)
|
|
||||||
|
|
||||||
if not os.path.exists(full_service_file_path):
|
|
||||||
print(f'[!] Service file does not exist [!]')
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Check if virtual env exist
|
|
||||||
if not os.path.exists(f'{os.path.join(self.config.defender_install_folder, self.config.venv_folder)}'):
|
|
||||||
self.run_subprocess(self.config.venv_cmd_installation)
|
|
||||||
print(f'[!] Virtual env does not exist run the install [!]')
|
|
||||||
return True
|
|
||||||
|
|
||||||
def run_subprocess(self, command:list) -> None:
|
|
||||||
|
|
||||||
print(f'> {command}')
|
|
||||||
try:
|
|
||||||
check_call(command)
|
|
||||||
print("The command completed successfully.")
|
|
||||||
except CalledProcessError as e:
|
|
||||||
print(f"The command failed with the return code: {e.returncode}")
|
|
||||||
print(f"Try to install dependencies ...")
|
|
||||||
exit(5)
|
|
||||||
|
|
||||||
def get_packages_version_from_json(self) -> None:
|
|
||||||
"""This will create Package model with package names and required version
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
|
|
||||||
version_filename = f'.{os.sep}version.json'
|
|
||||||
with open(version_filename, 'r') as version_data:
|
|
||||||
package_info:dict[str, str] = json.load(version_data)
|
|
||||||
|
|
||||||
for name, version in package_info.items():
|
|
||||||
if name == 'version':
|
|
||||||
continue
|
|
||||||
|
|
||||||
self.DB_PACKAGES.append(
|
|
||||||
self.Package(name=name, version=version)
|
|
||||||
)
|
|
||||||
|
|
||||||
return None
|
|
||||||
except FileNotFoundError as fe:
|
|
||||||
print(f"File not found: {fe}")
|
|
||||||
except Exception as err:
|
|
||||||
print(f"General Error: {err}")
|
|
||||||
|
|
||||||
def check_packages_version(self) -> bool:
|
|
||||||
|
|
||||||
try:
|
|
||||||
newVersion = False
|
|
||||||
self.get_packages_version_from_json()
|
|
||||||
|
|
||||||
if not self.config.venv_folder in prefix:
|
|
||||||
print(f"You are probably running a new installation or you are not using your virtual env {self.config.venv_folder}")
|
|
||||||
return newVersion
|
|
||||||
|
|
||||||
print(f"> Checking for dependencies versions ==> WAIT")
|
|
||||||
for package in self.DB_PACKAGES:
|
|
||||||
newVersion = False
|
|
||||||
_required_version = package.version
|
|
||||||
_installed_version: str = None
|
|
||||||
|
|
||||||
output = check_output([self.config.venv_pip_executable, 'show', package.name])
|
|
||||||
for line in output.decode().splitlines():
|
|
||||||
if line.startswith('Version:'):
|
|
||||||
_installed_version = line.split(':')[1].strip()
|
|
||||||
break
|
|
||||||
|
|
||||||
required_version = tuple(map(int, _required_version.split('.')))
|
|
||||||
installed_version = tuple(map(int, _installed_version.split('.')))
|
|
||||||
|
|
||||||
if required_version > installed_version:
|
|
||||||
print(f'> New version of {package.name} is available {installed_version} ==> {required_version}')
|
|
||||||
newVersion = True
|
|
||||||
|
|
||||||
if newVersion:
|
|
||||||
self.run_subprocess([self.config.venv_pip_executable, 'install', '--upgrade', package.name])
|
|
||||||
|
|
||||||
print(f"> Dependencies versions ==> OK")
|
|
||||||
return newVersion
|
|
||||||
|
|
||||||
except CalledProcessError:
|
|
||||||
print(f"[!] Package {package.name} not installed [!]")
|
|
||||||
except Exception as err:
|
|
||||||
print(f"General Error: {err}")
|
|
||||||
|
|
||||||
def check_python_version(self) -> bool:
|
|
||||||
"""Test si la version de python est autorisée ou non
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True si la version de python est autorisé sinon False
|
|
||||||
"""
|
|
||||||
if self.config.python_current_version_tuple < self.config.python_min_version:
|
|
||||||
print(f"## Your python version must be greather than or equal to {self.config.python_min_version} ##")
|
|
||||||
return False
|
|
||||||
|
|
||||||
print(f"> Version of python : {self.config.python_current_version} ==> OK")
|
|
||||||
return True
|
|
||||||
|
|
||||||
def check_package(self, package_name) -> bool:
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Run a command in the virtual environment's Python to check if the package is installed
|
|
||||||
run([self.config.venv_python_executable, '-c', f'import {package_name}'], check=True, stdout=PIPE, stderr=PIPE)
|
|
||||||
return True
|
|
||||||
except CalledProcessError as cpe:
|
|
||||||
print(cpe)
|
|
||||||
return False
|
|
||||||
|
|
||||||
def install_dependencies(self) -> None:
|
|
||||||
"""### Verifie les dépendances si elles sont installées
|
|
||||||
- Test si les modules sont installés
|
|
||||||
- Met a jour pip
|
|
||||||
- Install les modules manquants
|
|
||||||
"""
|
|
||||||
do_install = False
|
|
||||||
|
|
||||||
# Check if virtual env exist
|
|
||||||
if not os.path.exists(f'{os.path.join(self.config.defender_install_folder, self.config.venv_folder)}'):
|
|
||||||
self.run_subprocess(self.config.venv_cmd_installation)
|
|
||||||
do_install = True
|
|
||||||
|
|
||||||
for module in self.config.venv_cmd_requirements:
|
|
||||||
module = module.replace('pyyaml', 'yaml')
|
|
||||||
if not self.check_package(module):
|
|
||||||
do_install = True
|
|
||||||
|
|
||||||
if not do_install:
|
|
||||||
return None
|
|
||||||
|
|
||||||
print("===> Clean pip cache")
|
|
||||||
self.run_subprocess([self.config.venv_pip_executable, 'cache', 'purge'])
|
|
||||||
|
|
||||||
print("===> Check if pip is up to date")
|
|
||||||
self.run_subprocess([self.config.venv_python_executable, '-m', 'pip', 'install', '--upgrade', 'pip'])
|
|
||||||
|
|
||||||
if not self.check_package('greenlet'):
|
|
||||||
self.run_subprocess([self.config.venv_pip_executable, 'install', '--only-binary', ':all:', 'greenlet'])
|
|
||||||
print('====> Greenlet installed')
|
|
||||||
|
|
||||||
for module in self.config.venv_cmd_requirements:
|
|
||||||
if not self.check_package(module):
|
|
||||||
print("### Trying to install missing python packages ###")
|
|
||||||
self.run_subprocess([self.config.venv_pip_executable, 'install', module])
|
|
||||||
print(f"====> Module {module} installed!")
|
|
||||||
else:
|
|
||||||
print(f"==> {module} already installed")
|
|
||||||
|
|
||||||
def create_service_file(self) -> None:
|
|
||||||
|
|
||||||
full_service_file_path = os.path.join(self.config.unix_systemd_folder, self.config.service_file_name)
|
|
||||||
|
|
||||||
if os.path.exists(full_service_file_path):
|
|
||||||
print(f'[!] Service file already exist [!]')
|
|
||||||
self.run_subprocess(self.config.service_cmd_executable)
|
|
||||||
return None
|
|
||||||
|
|
||||||
contain = f'''[Unit]
|
|
||||||
Description=Defender IRC Service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
ExecStart={self.config.venv_python_executable} {self.config.defender_main_executable}
|
|
||||||
WorkingDirectory={self.config.defender_install_folder}
|
|
||||||
SyslogIdentifier=Defender
|
|
||||||
Restart=on-failure
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=default.target
|
|
||||||
'''
|
|
||||||
# Check if user systemd is available (.config/systemd/user/)
|
|
||||||
if not os.path.exists(self.config.unix_systemd_folder):
|
|
||||||
self.run_subprocess(['mkdir', '-p', self.config.unix_systemd_folder])
|
|
||||||
|
|
||||||
with open(full_service_file_path, 'w+') as servicefile:
|
|
||||||
servicefile.write(contain)
|
|
||||||
servicefile.close()
|
|
||||||
print('Service file generated with current configuration')
|
|
||||||
print('Running IRC Service ...')
|
|
||||||
self.run_subprocess(self.config.service_cmd_daemon_reload)
|
|
||||||
self.run_subprocess(self.config.service_cmd_executable)
|
|
||||||
|
|
||||||
else:
|
|
||||||
with open(full_service_file_path, 'w+') as servicefile:
|
|
||||||
servicefile.write(contain)
|
|
||||||
servicefile.close()
|
|
||||||
print('Service file generated with current configuration')
|
|
||||||
print('Running IRC Service ...')
|
|
||||||
self.run_subprocess(self.config.service_cmd_daemon_reload)
|
|
||||||
self.run_subprocess(self.config.service_cmd_executable)
|
|
||||||
|
|
||||||
def print_final_message(self) -> None:
|
|
||||||
|
|
||||||
print(f"#"*24)
|
|
||||||
print("Installation complete ...")
|
|
||||||
print("If the configuration is correct, then you must see your service connected to your irc server")
|
|
||||||
print(f"If any issue, you can see the log file for debug {self.config.defender_install_folder}{os.sep}logs{os.sep}defender.log")
|
|
||||||
print(f"#"*24)
|
|
||||||
exit(1)
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from core import installation
|
from core import install
|
||||||
|
|
||||||
#############################################
|
#############################################
|
||||||
# @Version : 6.3 #
|
# @Version : 6.3 #
|
||||||
@@ -10,7 +10,7 @@ from core import installation
|
|||||||
#############################################
|
#############################################
|
||||||
|
|
||||||
try:
|
try:
|
||||||
installation.Install()
|
install.update_packages()
|
||||||
from core.loader import Loader
|
from core.loader import Loader
|
||||||
loader = Loader()
|
loader = Loader()
|
||||||
loader.Irc.init_irc()
|
loader.Irc.init_irc()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
Faker==33.1.2
|
Faker==37.12.0
|
||||||
psutil==6.1.1
|
psutil==7.1.2
|
||||||
PyYAML==6.0.2
|
PyYAML==6.0.3
|
||||||
requests==2.32.3
|
requests==2.32.5
|
||||||
SQLAlchemy==2.0.36
|
SQLAlchemy==2.0.44
|
||||||
unrealircd_rpc_py==3.0.2
|
unrealircd_rpc_py==3.0.2
|
||||||
10
version.json
10
version.json
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"version": "6.3.2",
|
"version": "6.3.2",
|
||||||
|
|
||||||
"requests": "2.32.3",
|
"requests": "2.32.5",
|
||||||
"psutil": "6.0.0",
|
"psutil": "7.1.2",
|
||||||
"unrealircd_rpc_py": "3.0.1",
|
"unrealircd_rpc_py": "3.0.1",
|
||||||
"sqlalchemy": "2.0.35",
|
"sqlalchemy": "2.0.44",
|
||||||
"faker": "30.1.0",
|
"faker": "37.12.0",
|
||||||
"pyyaml": "6.0.2"
|
"pyyaml": "6.0.3"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user